最近研究了下 nor flash 的掉电问题, 对 nor 的掉电有了更多的认识. 总结分享如下
nor flash 的物理特性是, 写入之前需要先进行擦除. 擦除后数据为全 0xFF, 此时写入操作, 实际上是将数据从 1 改成 0.
一般先擦后写, 但实际上擦除后每个位置是可以写入多次的, 只要每次写入都是让某些 bit 从 1 变 0 即可.
例如在擦除后数据为 0xFF, 此时写入 0x0F, 可读出 0x0F, 再写入 0x01, 可读出 0x01, 再写入 0x00, 可读出 0x00.
而对于 0x00, 就无法再改写成任何值了, 因为此时每个 bit 都是 0, 想要改写就必须先擦除, 让其恢复到 0xFF, 再进行写入改成目标值.
多次写入的例子
在 uboot 中就有一个利用 nor 这个特性的例子. 当使用了冗余 env 功能时, flash 上会维护两份 env, 我们记为 envA 和 envB 吧.
既然有两份 env, 那就需要一种方式来区分哪份 env 的数据更新. 对此 uboot 支持几种策略, 其中一种可适用于 nor 的策略 FLAG_BOOLEAN,uboot 会在 env 的头部结构中, 使用了一个字节 flags 来表示其是否有效.
假设当前 A 有效, B 无效, 则 A 的 flags 为 0x1,B 的 flags 为 0x0. 读取时可以据此判断哪份 env 为新的.
写入时, uboot 会先在 ram 的 buffer 中构造好 flags 为 1 的新 env 数据, 再对 envB 进行擦除和写入. 写入后 flash 上两份 env 的 flags 就都是 0x1 了. 接着 uboot 直接对 A 的 flags 的位置写入 0x0, 即将原本的 0x1 不经擦除, 直接改写为 0, 这样就快速地达到将 A 标记为无效的目的了.
写入过程掉电
对于 nor 来说, 一次写入可以连续写 256 bytes, 那如果在中途发生了掉电, 再次上电后读出来的数据会是什么样的呢?
这个问题我们很容易得到两种猜测:
假设 nor 中存在一片 buffer, 集齐 256 bytes 后再一次性刷到颗粒中, 那么中途掉电大概率就是完全没有写入, 因为数据还在 buffer 中. 也有小概率是正在刷 buffer 到颗粒中掉电了, 那么这个时候写入的数据应该是乱序的.
假设 nor 中没有维护 buffer, 每个 bytes 的波形接收到之后就写入固化下来, 那么中途掉电大概率就是部分写入, 而且是顺序的, 即前面的数据写入了, 后面的数据仍然为 0xFF.
实测实际情况为假设二所述.
当写入一笔数据时, nor 就是按顺序写入的, 掉电后的数据特征为前面部分数据是正确数据, 后面部分数据是 0xFF. 前后的交界点并未对齐到 256 bytes.
擦除过程中掉电
从 nor flash 原厂了解到, erase 操作其实在 flash 内部分成三个步骤:
- )pre-program all "00";
- )erase;
- )post-program all "FF"
那么在擦除过程中掉电, 可能出现的数据特征就比较多了.
第一步骤: pre-program all "00";
当收到擦除命令时, 首先 flash 会对这 4k 写入全 0 数据, 这个是按先后顺序串行写入的, 就理解为一个正常的写入全 0 数据.
如果在这个过程中掉电, 那么观察到的数据会是, 前半部分的数据为 0x00, 后半部分的数据为原始的数据. 情况跟上面描述的写入过程掉电一样.
第二步骤: erase
全部写入 0 之后, 就进行擦除, 擦除是会将所有的 0 都变成 0xFF, 这个是 4k 的数据并行进行的, 在这个过程中掉电, 可以看到所有的数据都介于 0-0xFF 之间, 乱七八糟的数据, 没有任何规律.
第三步骤: post-program all "FF"
这一步其实我没太理解, 但从掉电后的数据特征看, 有一种状态可能跟这一步没完成有关.
即 4k 的数据, 处于不稳定的 0xFF 状态. 不稳定的意思是, 某次上电读出来为全 0xFF, 重新上电再读, 可能就是夹杂着一些 0xFD, 0xBF 之类的数据.
总结
以上我们观察了写入和擦除中途掉电的数据特征.
从写入过程掉电的特征看, 写入过程掉电可能导致 nor 仅将部分数据写入的, 导致头部数据存在但整体数据是不完整的, 因此不能简单依赖头部结构的 MAGIC 值来判定数据是否有效, 重要数据需要做完整性校验.
从擦除过程掉电的特征看, 擦除过程掉电可能导致 flash 上存在杂乱数据, 或者不稳定的全 0xFF 数据, 因此对于全 0xFF 的数据, 写入之前还是要先做一次擦除让 nor 达到稳定状态.
本文链接: https://www.cnblogs.com/zqb-all/p/12207924.html
来源: https://www.cnblogs.com/zqb-all/p/12207924.html