Fal主 要包括MappingTable, SectorMgr, Compactor 几个模块。MappingTable是映射表,nand驱动加载后扫 描nand并在内存建立映射表用来实现logical地址到实际physical地址的转换。 SectorMgr是扇区管理模块, Compactor 是垃圾回收模块。地址重映射应该是FAL最主要的功能。
按思维习惯,先了解下为什么?下面2个特性决定了设计FAL的原因。
1. 常见的nand, 一个block是32个sector, 或者256个sector等等。Flash的擦写单位是block, 而Filesys的读写单位是sector。需要FTL转换。
2. 文件系统对磁盘扇区的访问是不平衡的,有些区域的扇区访问频率特别高,而flash是寿命有限的设备,所以需要进行磨损平衡处理(wear leveling),使得擦写尽可能均匀分布到每个block。
阅读完FAL代码后,按照我会怎么设计的思维思考,总结几个想法:
1.如 果需要修改已保存的数据,首先要erase数据所在的block,然后writer更新后的数据, 相对而言这个过程是很慢的, 所以常见的做法不这样 做。而是把修改后的整个block数据先写到一个新的block, 然后Mark原来的block为dirty block。 注意到Mark操作实际是个直接write(没有Erase)的操作。一个说法:SLC支持这样的行为,而MLC不允许这样。恐怕对MLC的设备要修改FAL。上面的整个流程是设计成事务型处理流程的,就是要记录下处理阶段和状态,确认处理完毕。 --这是必须的,避免意外掉电造成严重后果。
2.地 址映射是设计的核心部分。FAL设计思路是这样的, 在初始化时候建立一张表,描绘logicla和physical的映射关系。这种办法代价在于每次开 机都要全盘扫描,可见扫描时间是和size相关的。更优的做法是保存表到固定地址,开机只要读取表就可以了,空间换时间。不过也要机制保障(想想坏块无处 不在以及掉电随时发生)。FAL扫描时候都扫描什么呢?FAL读取每一个有效扇区的spare区域的16个字节, 前面4个字节是扇区地址, 下1个字节 是OEM状态, 下一个字节是坏块标识, 接下来2个字节是FAL的状态,用于事务型处理机制。
3.第一点描述了修改数据的处理方式,那些dirty block怎么办?FAL在后台有一个thread擦除并回收这些dirty blocks。重新标识为FREE,供使用。这是所谓的垃圾回收机制。
4.一个基本前提是:认定读操作不会导致坏块产生。FAL也没有对此处理。(说到这, 到底道什么时候会产生坏块?电压不稳?宇宙射线?外星人进攻?)如果这个前提成立的话,bootloader读取wince image加载启动也是安全可靠的(一块心病)
5.关 于bootloader。 Bootloader可以标识一些block为保留块,这样FAL会仁慈的跳过这些块,否则,后果很严重,FAL很生气。你是 不是经常发现你的Bootloader莫名其妙的失踪了?呵呵。另外,Bootloader直接用物理地址访问文件系统区是不恰当的。没有FAL的 Bootloader(一般都没有)怎么访问呢?比如从文件系统里面读取一个bmp文件作为logo,在开机时候显示。比如wince里面设定一个配置文 件,指示bootloader下一次开机时候做一些其他动作。有一个傻瓜办法是,bootloader每一次读一个扇区时候,全盘扫描一次,找到这个扇区 实际的地址。这是世界上最傻的办法了, 我觉得慢死了,弄了一次后不想弄第二次。聪明的办法是自己想办法去建立映射表了.