为什么不能两次写入同一地址的内部闪存

Why can't write internal flash of same address twice

我正在尝试写入 STM32F1xxC 的内部闪存(每页 2KB),我可以在页面擦除后写入闪存,这会将该页的每个字节转换为 0xFF。

很奇怪我不能把flash的同一个地址写两次,只有那个地址的前一个值是“0xFFFF[才有可能=22=]".

这个限制的原因是什么? 而且我想知道为什么我不能写奇怪的地址? (例如 0x803F0A1)

我不认为我的问题是特定于平台(或供应商)的,所以我没有添加任何代码。

感谢任何帮助。

这不是很奇怪,但由于底层技术(我不敢解释,我不是物理学家),所以有flash的规则。看看这里:

https://en.wikipedia.org/wiki/Flash_memory#Block_erasure

A location can, however, be rewritten as long as the new value's 0 bits are a superset of the over-written values. For example, a nibble value may be erased to 1111, then written as 1110. Successive writes to that nibble can change it to 1010, then 0010, and finally 0000. Essentially, erasure sets all bits to 1, and programming can only clear bits to 0.

至于:

And also I was wondering why I can't write to odd addresses?

这是您的 CPU 的 内存对齐 限制 - 一个很常见的限制,不要为此责怪它!这里有一个很好的解释:

因此,要写入未对齐的地址,您还必须先写入对齐的地址:

  • 加载16位(或32位,取决于你的对齐粒度限制)位内存对齐地址值,其中包括你感兴趣的部分,

  • 改变这部分,其余部分保持不变,

  • 将新的 16(或 32)位值写回内存对齐地址。

编辑:

对于STM32F1xx 更严格的设计的具体见解,请务必查看@Clifford 评论。

闪存的本质是写入 操作只允许位从 1 到 0 的转换。要将位从 0 设置为 1 需要 erase 操作和一个擦除操作适用于整个擦除块。擦除块的大小因设备而异。

在大多数闪存实现中,如果唯一的位变化是从 1 到 0,则可以修改已写入的字。然而,在 STM32F1xx 上,即使这样也不可能,因为字大小为 16位,如果已写入另一半字,则无法写入单个字节。

STM32F2xx(还有F4和F7范围)允许以8、16和32位模式写入flash,部分解决了这个问题,但仍然无法将位从1写入0当同一个字中的位已经为零时。

您可能需要注意的另一个 STM32 片上闪存问题是,在写入或擦除操作期间,总线会停顿很长一段时间。在传统的闪存部件上,您可以在写入一页的同时从一页读取,但在 STM32 上,整个闪存都被阻塞了。由于通常指令从闪存中提取,这种读取阻塞意味着在闪存 erase/write 操作期间 没有指令被处理 - 整个处理器内核处于 等待状态(外围设备继续运行 - 除非使用 DMA 读取闪存)。对于擦除,延迟取决于页面大小;在 STM32F1xx 上,此延迟可能高达 40 毫秒,在 F2 上为 800 毫秒!这使得片上闪存 write/erase 操作在实时系统中出现问题。

虽然闪存通常会对 write/erase 操作施加限制,但 ST 的实现会施加其自身的额外限制,如上所述。您始终需要将您的非易失性存储器技术与应用程序相匹配,或者编写您的应用程序以使用可用的非易失性存储器。外部(片外)设备可能适合您的情况。大多数技术都以某种方式在速度、可用性、耐用性、密度和成本方面做出某种妥协,但您可以考虑使用外部闪存、EEPROM、FRAM 或电池供电的 SRAM 等。如果您的处理器缺少外部存储器接口,或者您负担不起使用地址总线访问设备所需的引脚数,则大多数技术都可用,例如通过 SPI 或 I2C 的串行访问设备。

另请注意,STM32F1xx 闪存实现的详细信息在通用用户手册的单独文档中进行了描述。参考PM0075 编程手册 - STM32F10xxx 闪存微控制器

公平地说,STM32 闪存的限制性实施并非完全随意。与 "full" 实现相比,该实现无疑需要更少的芯片 space,允许 space 用于更多外围设备、更大的内存或更小的芯片尺寸(以降低成本)。芯片设计涉及许多妥协,ST 似乎选择为大型外围设备妥协闪存的灵活性。

作为 Clifford 响应的补充,需要注意的是,如果值为 0x0000,STM32 闪存控制器允许第二次写入一个字。 这允许在闪存页面擦除之间有 3 个字状态:

  1. 页面擦除后为 0xffff
  2. 0xxxxx 写入的任何值
  3. 0x0000 第二次也是最后一次写入 0。

这在闪存中构建动态数据存储(如 EEPROM 仿真)以具有状态 'free'、'in use' 和 'deleted' 时非常方便。