u-boot中Nand flash的驱动主要分为三层
一层:涉及到硬件
二层:封装(mtd)
三层:驱动的注册和相关调用
一层:涉及到硬件
举512字节一页的nand flash为例,
在copy_main中,已经介绍的nand_flash的最底层的操作,结合SPC来看,以HY系列的NAND为例,首先是nand_flash的芯片,关注的是IO CE WE RE ALE CLE RB,这里WE RE与AT91sam9260直接相连,CE 片选 CLE 命令锁存, ALE地址锁存, R/B ready/busy
(1)与flash相连的相关口线的配置
(2) 发送命令ReadId 读取marker Code和Device Code,分析而到页大小,块大小,OOB大小,对于页大小大于512字节的,需要再读后面的2字节
(3)发送read命令读取连续数据
Sequential read 命令为00,页内地址,页偏移,等待ready,读取一页的数据,包括oob,然后再等待ready,在进行读
这里读完一页之后busy的原因是,此时flash将下一页数据从flash写到缓存中,不允许读
(4)校验通过ECC
如果使用的是硬件ECC,在读取数据之后会将校验值放在相关寄存器中,读取相关寄存器,进行判断即可。
这里移植或者开发的时候需要注意 ECC校验位长度和起始字节 坏块的起始和长度
像HY27US中有这么两句话,
Any block where 6th byte/ 1st word in the spare area of the 1 st or 2nd page(if the 1st page is bad) does not contain FFh is bad block
The copy back program command can be used to copy the data to a valid block
(5)擦除命令
发送命令0x60,设置需要擦除的页地址(擦除一块),写擦除命令0Xd0,等待擦除完毕,读取I/O0数值,为0则表示擦除成功
(6)写数据
写数据先发送命令0X80,页内地址,页偏移,后数据(在一页范围内数据),
Program command 0X10,接着FLASH进入BUSY,等待ready之后,写0x70(read status Command),之后通过读取I/O0判断写数据是否正确
以上就是NAND FLASH中一些比较基本的命令(read_oob之类略)
二层:封装(mtd)
对于MTD(memory technology device)
将所有的方法封装在两个结构体中 mtd_info 和 nand_chip
在注册驱动时,调用nand_init_chip,最终注册的就是这两个结构体
上图是mtd_info 和 nand_chip的一些结构封装,对于移植(更换新的NAND FLASH,或者不同的SOC),只要改写底层(就是第二层)的相关函数就可以。
比如读数据的命令,在MTD封装中包括两部分,一部分是nand_chip->cmdctrl发送命令,一部分是nand_chip->read_page,而这两部分都封装在mtd_info *info的info->read中,Write和erase,isbad_block类似。
至于ECC部分(移植相关,可以参看stage1中copy_main函数的实现),根据不同的页大小配置不同的ECC.Layout
其相关操作在nand_chip中
所以移植过程只要注意修改nand_chip结构下的操作方法即可。
三层:驱动的注册和相关调用
U-BOOT中注册驱动的时候调用 nand_init_chip
有四个调用,Board_nand_init(mtd),Nand_scan_ident,Board_nand_ecc_init,
Nand_scan_tail
对于这四个调用不细说,注册之后只要学会第三层相关调用。
得到对应的mtd_info 结构指针之后,就可以调用相应方法了
包括
Info->read,Info->write,Info->isbad_block,Info->erase等
关键的问题在于如何得到mtd_info结构指针,而这个取决于写的上层程序,只要在希望读写的分区的结构中嵌入mtd_info *info结构指针,并对其初始化,对相应的分区进行操作便可以调用相应函数。