4. 坏块表管理:BBT结构设计、RAM维护与NAND存储更新
坏块表,简称BBT。这玩意儿是NAND Flash管理的核心之一。说白了,它就是一张“黑名单”,记录着哪些块是坏的、不能用的。
我刚开始做NAND驱动时,觉得BBT不就是个标记嘛,有啥难的?后来踩了坑才明白——BBT的设计好坏,直接决定了系统的稳定性和寿命。今天咱们就把它掰开揉碎了讲清楚。
4.1 BBT结构设计——这张表长什么样?
BBT的结构,不同厂家有不同玩法。但核心思路是一致的:用最少的空间,管理最多的坏块。
我个人习惯把BBT设计成两级结构:
- 一级表(主表):记录每个块的坏块状态。一个bit对应一个块,0表示好块,1表示坏块。
- 二级表(扩展表):当主表所在的块也坏了,就用扩展表来记录。
举个例子,一颗8GB的NAND,假设有4096个块。用bitmap方式,只需要4096个bit,也就是512字节。你看,空间效率很高。
BBT条目格式(我常用的):
// 每个块对应1个bit
// 0x00 = 好块
// 0x01 = 坏块
// 假设有4096个块,BBT大小为512字节
uint8_t bbt[512]; // 512字节 = 4096 bit
这里要注意:BBT本身也要占用一个块。这个块必须是好块,否则BBT存哪儿?
我曾经踩过的坑: 有一次设计BBT时,没考虑主表块损坏的情况。结果主表块坏了,整个系统找不到坏块信息,直接崩溃。后来我加上了二级表机制,才彻底解决这个问题。
4.2 RAM中BBT的维护——快,但要小心
BBT在NAND里存着,但每次读写都去NAND里查,速度太慢了。所以,我们会在RAM里维护一份BBT的副本。
RAM中的BBT,说白了就是NAND中BBT的“缓存”。系统启动时,从NAND加载到RAM;运行时,在RAM里更新;需要时,再写回NAND。
我建议用以下方式维护RAM中的BBT:
- 启动时加载:从NAND的指定位置读取BBT,存入RAM。
- 运行时更新:每次发现新坏块,立即更新RAM中的BBT。
- 定期回写:将RAM中的BBT写回NAND,防止掉电丢失。
小技巧: 我习惯在RAM中维护一个“脏标记”。只要BBT有更新,就把脏标记置1。回写时,只回写脏标记为1的BBT。这样可以减少NAND的写入次数,延长寿命。
你想想看,如果每次发现坏块都立刻写回NAND,那NAND的寿命会急剧下降。所以,延迟回写是个好策略。
4.3 NAND中BBT的存储与更新——怎么存?怎么改?
NAND里的BBT,通常存储在最后一个块或者前几个块。不同厂家有不同约定,但海力士的习惯是存在最后一个块。
BBT在NAND中的存储格式,我一般这样设计:
| 偏移 | 内容 | 大小 |
|---|---|---|
| 0x00 | BBT标识(固定为0x424254) | 4字节 |
| 0x04 | 版本号 | 4字节 |
| 0x08 | 块总数 | 4字节 |
| 0x0C | 坏块位图 | 可变 |
| 末尾 | CRC校验 | 4字节 |
更新BBT时,流程是这样的:
- 在RAM中标记新坏块。
- 将RAM中的BBT数据准备好。
- 擦除NAND中存放BBT的块。
- 将新BBT写入该块。
- 验证写入是否正确。
注意: 擦除操作有风险。如果擦除过程中掉电,BBT就丢了。我建议在擦除前,先把BBT备份到另一个块。等擦除完成、写入成功后,再释放备份块。
嗯,这里还要提一点:BBT的更新频率。我个人建议,每次系统关机或休眠前,强制回写一次BBT。平时运行时,可以每发现10个新坏块,或者每过1小时,回写一次。具体频率,得看你的系统对数据安全的要求。
4.4 核心逻辑流程图
下面这张图,是我根据多年经验总结的BBT管理核心流程。你看一眼,基本就明白整个体系了。
这张图把BBT的整个生命周期都串起来了。从启动加载,到运行时更新,再到条件回写,每一步都环环相扣。
4.5 实战中的几个要点
最后,分享几个我在项目中积累的经验:
- BBT的备份:至少保留两份BBT副本。一份在主块,一份在备用块。万一主块坏了,还有救。
- 版本控制:每次更新BBT,版本号加1。这样能判断哪份BBT是最新的。
- CRC校验:BBT数据必须带CRC。NAND有比特翻转的风险,CRC能帮你发现数据是否损坏。
- 原子操作:更新BBT时,尽量保证操作的原子性。如果做不到,至少要有回滚机制。
我的个人习惯: 每次设计BBT时,我都会预留一些扩展字段。比如预留16字节的厂商自定义区域。这样后续要加功能,不用改整体结构。你想想看,产品迭代时,这个预留字段能省多少事。
好了,BBT这块的内容就讲到这里。记住一句话:BBT是NAND的生命线,设计时多花心思,运行时少出问题。
公众号:蓝海资料掘金营,微信deep3321