我试图写入STM32F1xxC的内部闪存(每页2KB),我可以在页面擦除后写入闪存,将该页面的每个字节转换为0xFF。
很奇怪,我无法写两次相同的flash地址,只有当该地址的前一个值为&#34; 0xFFFF <时才有可能/强>&#34;
这种限制的原因是什么? 而且我想知道为什么我不能写入奇数地址? (例如0x803F0A1)
我认为我的问题不是平台(或供应商),所以我没有添加任何代码。
我感谢任何帮助。
答案 0 :(得分:6)
闪存的性质是写操作只允许从1到0的位转换。要将位从0设置为1,需要擦除操作和擦除操作适用于整个擦除块。擦除块的大小因设备而异。
在大多数闪存实现中,如果唯一的位从1变为0,则可以修改已经写入的字。然而,在STM32F1xx上,即使这样也是不可能的,并且由于字大小为16位,如果已写入另一半字,则无法写入单个字节。
STM32F2xx(以及F4和F7范围)通过允许以8,16和32位模式写入闪存来部分解决此问题,但是当位时仍然无法从1写入一个位在同一个单词中已经为零。
您可能需要注意的STM32片上闪存的另一个问题是,在写入或擦除操作期间,总线会停顿很长一段时间。在传统的闪存部件上,您可以在写入时从一个页面读取,但在STM32上,整个闪存被阻止。由于通常指令取指来自闪存,因此读取阻塞意味着在闪存擦除/写入操作期间没有处理指令 - 整个处理器内核处于等待状态 (外围设备继续运行 - 除非使用从闪存中读取DMA)。对于擦除,延迟取决于页面大小;在STM32F1xx上,这个延迟可以长达40ms,在F2上是800ms!这使得片上闪存写入/擦除操作在实时系统中存在问题。
虽然闪存通常对写/擦除操作施加限制,但ST实现强加了其自身的附加限制,如上所述。您始终需要将非易失性存储器技术与应用程序匹配,或编写应用程序以使用可用的非易失性存储器。在您的情况下,外部(片外)设备可能是合适的。大多数技术都是以某种方式对速度,可用性,耐用性,密度和成本进行某种折衷,但您可以考虑使用外部闪存,EEPROM,FRAM或电池备份SRAM。如果您的处理器缺少外部存储器接口,或者您无法承担使用地址总线访问设备所需的引脚数,那么大多数技术都可通过SPI或I2C等串行访问设备获得。
另请注意,STM32F1xx闪存实现的详细信息在一般用户手册的单独文档中进行了描述。请参阅PM0075 Programming manual - STM32F10xxx Flash memory microcontrollers
为了公平对待ST,限制性STM32闪存实现并非完全随意。毫无疑问,实施所需的芯片空间比完全&#34;实现允许更多外围设备,更大存储器或更小芯片尺寸的空间(降低成本)。芯片设计涉及许多妥协,ST选择牺牲闪存灵活性,以满足大型外设的需求。
答案 1 :(得分:1)
这不是很奇怪,但闪光的规则,因为基础技术(我不敢解释,我不是物理学家)。看看这里:
https://en.wikipedia.org/wiki/Flash_memory#Block_erasure
然而,只要新值为0,就可以重写位置 位是重写值的超集。例如,一个半字节 值可以擦除到1111,然后写为1110.连续写入 到那个半字节可以改为1010,然后是0010,最后是0000。 从本质上讲,擦除将所有位设置为1,并且只能编程 将位清零。
至于:
我也想知道为什么我不能写到奇数地址?
这是你的CPU的内存对齐限制 - 一个非常常见的,不要因此而责备它!这里有一个很好的解释:
https://stackoverflow.com/a/3025225/5257515
因此,要写入未对齐的地址,您必须先写入对齐的地址:
加载16位(或32位,具体取决于您的对齐粒度限制)位内存对齐的地址值,其中包括您感兴趣的部分,
更改此部分,其余部分保持不变,
将新的16(或32)位值写回到内存对齐的地址。
编辑:
有关STM32F1xx更具限制性设计的具体见解,请务必查看@Clifford评论。