很久没接触过 nandflash 驱动,最近工作又摸了,于是顺便整理总结一下。nandflash 在我看来算是比较落后的存储设备,所以文章里没有太多细节的东西,更多的是一些开发思路和经验,希望能帮助到有需要的人。
一、了解 nandflash 当前发展状况
什么是 nandflash?
nandflash 由许多保存位( bit )的单元( cell )组成,这些位通过电荷开启或关闭。这些开/关单元的组织方式表示存储在nandflash 上的数据。这些单元中的位数也决定了 nandflash 的命名,例如 Single Level Cell ( SLC ) nandflash 在每个单元中都包含一个位。MLC nandflash将每个单元的位数增加了一倍,而 TLC nandflash 则增加了三倍,这为更高容量的 nandflash 开辟了道路。
SLC 的优点是速度最快,最耐用,但缺点是价格昂贵,并且无法提供更高的存储容量。SLC 是企业使用的首选。与 SLC 相比,MLC 和 TLC 闪存的生产成本更低,存储容量更高,但要权衡相对较短的使用寿命和较慢的读/写速度。MLC 和 TLC 是日常消费计算机等个人用品的首选。
SLC \ MLC \ TLC nandflash 对照表:
为什么在嵌入式设备上 emmc 取代了 nandflash?
由于NAND Flash芯片的不同厂牌包括三星、KingMax、东芝(Toshiba)或海力士(Hynix)、美光(Micron)等,都需要根据每家公司的产品和技术特性来重新设计,过去并没有哪个技术能够通用所有厂牌的NAND Flash芯片。
而每次NAND Flash制程技术改朝换代,包括70纳米演进至50纳米,再演进至40纳米或30纳米制程技术,手机客户也都要重新设计(重新设计什么?因为你要通讯,就需要通讯的电压,时序,甚至接口命令,这些都随着不同厂商,不同制程技术而不同,你作为手机制造商或者soc厂商,想要把每种新的 nandflash 集成到你的产品中,就要根据这些新的特性来花时间设计。soc这边会有一个nandflash controller,你要根据采用的nandflash特性来配置nand flash controller,以达到成功通讯的目的)。
但半导体产品每1年制程技术都会推陈出新,存储器问题也拖累手机新机种推出的速度,因此像eMMC这种把所有存储器和管理nandflash的控制芯片都包在1颗MCP上的概念,逐渐风行起来。即:
NAND Flash 是一种存储介质,要在上面读写数据,外部要加主控和电路设计;
eMMC是NAND Flash+主控IC ,对外的接口协议与SD、TF卡类似;
emmc 内部根本的存储介质还是 nandflash,而不是一种全新的 storage。但是他定义并规范了统一接口比如:emmc 4.3, 4.4, 4.5(类似于usb 2.0, 3.0 这样的), 把和 nand flash 的通讯封装在emmc内部,而提供给外部的接口就是 emmc 接口。同理, 外部,比如soc就需要有个 sdmmc controller, 并且宣布支持 emmc 4.3/4.4…,那么,你需要做的就是,根据选用的emmc的版本号,来给 sdmmc controller 来选择一个通讯的接口版本号4.4。
二、如何驱动一款NAND Flash?
参考:
《韦东山嵌入式Linux视频第一期-nandflash》
(一) 基础硬件知识
nandflash 是一个存储芯片,那么它应该能提供“读地址A的数据,把数据B写到地址A"的功能。
问1:原理图上 NAND FLASH 和 S3C2440 之间只有数据线,如何传输地址呢?
答1.在DATA0~DATA7上既传输数据,又传输地址,当ALE为高电平时传输的是地址。
问2:从NAND FLASH芯片手册可知,要读写NAND FLASH需要先发出命令,如何传入命令?
在DATA0~DATA7上既传输数据,又传输地址,也传输命令;
答2:
当ALE为高电平时传输的是地址;
当CLE为高电平时传输的是命令;
当ALE和CLE都为低电平时传输的是数据;
问3:数据线LDATAn既接到NAND FLASH,也接到NOR FLASH,还接到SDRAM、DM9000等等,cpu如何准确的将某个地址发到正确的芯片上而不干扰其他芯片呢?
答3:这些芯片,要访问之必须"选中"(即片选信号为低),没有选中的芯片不会工作,相当于没接一样。
问4:假设烧写NAND FLASH,把命令、地址、数据发给它之后,NAND FLASH肯定不可能瞬间完成烧写的,怎么判断烧写完成?
答4:通过状态引脚RnB来判断:它为高电平表示就绪,它为低电平表示正忙。
问5:怎么操作NAND FLASH呢?
答5. 根据NAND FLASH的芯片手册,一般的过程是:
(1) 发出命令
(2) 发出地址
(3) 写数据/读数据
(4) 等待
(二) CPU nandflash 控制器章节导读
以三星 s5pv210 芯片为例,摘选一下我认为比较重要的点:
SLC nandflash一般是1bit ecc,对应的编解码的过程需阅读上述内容。
MLC nandflash 一般是8/12/16 bit ecc,对应的编解码的过程需阅读上述内容。
(三) nandflash 芯片手册导读
以镁光 nandflash 芯片为例,摘选一下我认为比较重要的点:
特性列表,一般位于芯片手册首页,可以帮助我们快速了解芯片特性,基本可以认为是最重要的信息。
不同芯片厂商的nandflash芯片引脚定义基本是一致的,但是可能会有1~2引脚是有差异,需要核对。
上图可用于确定nandflash的存储布局;
(四) nandflash 调试思路:
1.通读 CPU 芯片手册 nandflash 控制器章节:
2.通读 nandflash 芯片手册:
3.在 U-boot 或者 Linux 下实现读取 nandflash 芯片的ID值的功能:nand_read_id()
4.在 U-boot 或者 Linux 下实现读取擦除 一块数据的功能:nand_erase_block()
5.在 U-boot 或者 Linux 下实现裸读一页数据( 不考虑ecc校验 )的功能:nand_read_page_raw()
6.在 U-boot 或者 Linux 下实现裸写一页数据( 不考虑ecc校验 )的功能;nand_write_page_raw()- 裸写一页和裸读一页的操作可以相互协同验证;- uboot 的 cmp 命令可以对比两块内存的数据是否相同,该命令可以用于验证写操作是否成功;
7.在 U-boot 或者 Linux 下实现写一页数据到 main区域,并将 nandflash 控制器生成的 ecc 校验码填写到oob区域:nand_write_page()
8.在 U-boot 或者 Linux 下实现读一页数据的功能,包括读 main 区域的数据和 spare 区域的 ecc 校验码:nand_read_page()
9.由于bit 错误的问题不容易出现,所以在调试阶段需要人为制造出与 spare 区域 不匹配的 main 数据,以检验ecc 校验功能是否正常,即数据是否能被纠正,大体的思路是:
10.如果 main 区域的 ecc 校验码字节数比较多,并且 spare 区域足够大的话,可以对存放在 spare 区域里的 main ecc校验码进行二次 ecc,这时生成的 ecc 校验码我将其称为 spare ecc,它一般会存放在spare区域的末尾,并不是必须的;
(五) Linux Nand Flash驱动
参考:
《韦东山嵌入式Linux视频第二期-nandflash》
对于nandflash 驱动,需要重点关注的地方:
Flash memory abstraction layer/MTD layer drivers/mtd/mtd*.c
Flash type abstration layer/NAND core drivers/mtd/nand/nand_*.c
Flash controller drivers drivers/mtd/nand/*_nand.c
NAND legacy stack( Linux-4.16 之前)
/dev/mtd0是nandflash设备的字符设备驱动节点,上图展示了 read("/dev/mtd0") 的底层实现(MTD layer->NAND core->Controller driver)。
NAND legacy stack 的弊端
NAND new stack( Linux-4.16 之后)
将NAND 的控制逻辑下放到Controller driver层,NAND Core统一调用Controller driver提供的钩子函数:exec_op();
(六) 测试稳定性和性能
MTD tests support
insmod mtd_stresstest.ko dev=9 count=1000
[ 3289.273771] =================================================
[ 3289.279826] mtd_stresstest: MTD device: 9
[ 3289.284079] mtd_stresstest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 64
[ 3289.303250] mtd_stresstest: scanning for bad eraseblocks
[ 3289.420267] mtd_stresstest: scanned 2048 eraseblocks, 0 are bad
[ 3289.426534] mtd_stresstest: doing operations
[ 3289.431031] mtd_stresstest: 0 operations done
[ 3339.606972] mtd_stresstest: finished, 1000 operations done
[ 3339.612992] =================================================
一个反复读写并校验数据正确性的小脚本:
#!/bin/sh
rm -rf /media/local/
count=1
while [ ${count} -lt 600 ]; do
TSTAMP="`date` | ---> ${count}"
echo "$TSTAMP"
mkdir -p /media
time cp /usr/local /media/ -raf
diff /usr/local /media/local -r || exit -1
rm -rf /media/local;
sync
let count=${count}+1
done
三、NAND Flash 文件系统的选择:YAFFS2
参考:
《基于nand flash的文件系统的整理》
《Cramfs、JFFS2、YAFFS2的全面对比》
针对 nandflash 特点优化其性能以及克服其缺点
1.nanflash 不是通常意义上的块设备,块设备的特点是可以对数据块进行读、写操作(如磁盘,文件系统等),但是对于nanflash 来说有三种操作分别是:读、写、擦除。只有对已擦除的块才能进行写操作。所以为了使其兼容传统的硬件和系统,需要对其进行特殊处理;
2.当一个闪存处在干净状态时(被擦除过,但是还没有写操作发生),这块flash上的每一位(bit)都是逻辑1;
3.闪存的使用寿命是有限的,具体来说,闪存的使用寿命是由擦除块的最大可擦除次数来决定的。超过了最大可擦除次数,这个擦除块就成为坏块(bad block)了。因此要避免某个擦除块被过度使用,以至于先于其他擦除块变成坏块,应该在尽量少影响性能的前提下,使擦写操作均匀分布在每个擦除块上,叫做损耗均衡(wear leveling)。
YAFFS意为「Yet Another Flash File System」,是目前唯一一个专门为NAND Flash设计的文件系统。它采用了类日志结构,结合NAND Flash的特点,提供了损耗平衡和掉电保护机制,可以有效地避免意外掉电对文件系统一致性和完整性的影响。
nanflash 和 YAFFS2之间是如何配合的?
通过分析mkyaffs2iamge.c可知:
参考资料
[1]
YAFF2官网: https://yaffs.net/documents/how-yaffs-works