阅读:4001回复:0
[原创,总结]wince下的FAL
http://chenyq2008.spaces.live.com/Settings/Stats/fakehandlerpage.aspx?date=633600930948570000&id=1666281&next=true&wa=wsignin1.0&sa=624410254
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每一次读一个扇区时候,全盘扫描一次,找到这个扇区实际的地址。这是世界上最傻的办法了, 我觉得慢死了,弄了一次后不想弄第二次。聪明的办法是自己想办法去建立映射表了. 最后来个总结:我看了一些linux的yaffs的描述。 FAL很类似yaffs。不过yaffs是filesystem,而FAL实际上是 nand flash驱动的一部分。他有地址转换和垃圾回收机制,根据nand特性来处理nand的坏块和读写。目前分析,FAL的设计使得nand的使用变得安全可靠,至于性能方面就不说了...当然有优化的空间. |
|