一、区块管理:
在每个块的开头放置一个较小的标头。您需要跟踪“最旧”和“最新”的主要内容是块号,它只是以模数递增k. k必须大于您的块总数。理想情况下,使k小于您的最大值(例如 0xFFFF),因此您可以轻松判断什么是已擦除块。
At start-up, your code reads the headers of each block in turn, and locates the first and last blocks in the sequence that is ni+1 = (ni + 1) MODULO k. Take care not to get confused by erased blocks (block number is e.g. 0xFFFF) or data that is somehow corrupted (e.g. incomplete erase).
每个区块内
每个块最初都是空的(每个字节是 0xFF)。每条记录只是一个接一个地写入。如果您有固定大小的记录,那么您可以使用简单的索引来访问它。如果您有可变大小的记录,那么要读取它,您必须从块的开头开始扫描,采用链表样式。
如果您想要具有可变大小的记录,但避免线性扫描,那么您可以在每个记录上有一个明确定义的标题。例如。使用 0 作为记录分隔符,并且COBS-编码(或COBS/R-编码)每条记录。或者使用您选择的字节作为分隔符,如果该字节出现在每个记录中,则“转义”该字节(类似于点对点协议).
在启动时,一旦知道最新的块,就可以对最新的记录进行线性扫描。或者,如果您有固定大小的记录或记录分隔符,则可以进行二分搜索。
擦除调度
对于某些闪存芯片,擦除一个块可能会花费大量时间 - 例如5秒。考虑将擦除安排为稍微“提前”的后台任务。例如。当当前块已满 x% 时,则开始擦除下一个块。
记录编号
您可能想要对记录进行编号。我过去的做法是将第一条记录的记录号放入每个块的标头中。然后软件必须计算块内每条记录的数量。
校验和或 CRC
如果您想检测损坏的数据(例如,由于意外电源故障而导致的不完整写入或擦除),那么您可以向每个记录(也许还有块头)添加校验和或 CRC。请注意,块头 CRC 仅覆盖头本身,而不覆盖记录,因为写入每个新记录时无法重写它。