基于MTD的NANDFLASH设备驱动底层实现原理分析(五)
Linux内核在MTD的下层实现了通用的NAND驱动(/driver/mtd/nand/nand_base.c)因此芯片级的驱动实现不再需要我们关心mtd中的那些成员函数了主题转移到nand_chip数据结构中 先了解了解nand_chip结构体 struct nand_chip { ??? int?? ??? ?(*verify_buf)(struct mtd_info *mtd,int len); //验证芯片和写入缓冲区中的数据 ?? int ? ? ? ? (*block_bad)(struct mtd_info *mtd,loff_t ofs,int getchip);//检查是否坏块 ??? void?? ??? ?(*select_chip)(struct mtd_info *mtd,int chip);????????? //实现选中芯片 ??? int?? ??? ?(*waitfunc)(struct mtd_info *mtd,struct nand_chip *this); ??? int?? ??? ?(*write_page)(struct mtd_info *mtd,struct nand_chip *chip, ?? unsigned int?? ?options;//与具体的NAND芯片相关的一些选项,如NAND_NO_AUTOINCR,NAND_BUSWIDTH_16等,至于这些选项具体表示什么含义,可以参考<linux/mtd/nand.h>,那里有较为详细的说明; ?? ?int?? ??? ?page_shift;//用位表示的NAND芯片的page大小,如某片NAND芯片的一个page有512个字节,那么page_shift就是9; ?? ?int?? ??? ?phys_erase_shift;//用位表示的NAND芯片的每次可擦除的大小,如某片NAND芯片每次可擦除16K字节(通常就是一个block的大小),那么phys_erase_shift就是14; ?? ?int?? ??? ?bbt_erase_shift;//用位表示的bad block table的大小,通常一个bbt占用一个block,所以bbt_erase_shift通常与phys_erase_shift相等; ?? ?int?? ??? ?chip_shift;用位表示的NAND芯片的容量; ?? ?int?? ??? ?numchips;表示系统中有多少片NAND芯片; ?? ?uint64_t?? ?chipsize;//NAND芯片的大小; ?? ?int?? ??? ?pagemask;//计算page number时的掩码,总是等于chipsize/page大小- 1; ?? ?int?? ??? ?pagebuf;用来保存当前读取的NAND芯片的page number,这样一来,下次读取的数据若还是属于同一个page,就不必再从NAND芯片读取了,而是从data_buf中直接得到; ?? ?int?? ??? ?subpagesize; ?? ?uint8_t?? ??? ?cellinfo; ?? ?int?? ??? ?badblockpos; ?? ?int?? ??? ?badblockbits; ?? ?flstate_t?? ?state; ?? ?uint8_t?? ??? ?*oob_poi; ?? ?struct nand_hw_control? *controller; ?? ?struct nand_ecclayout?? ?*ecclayout; ?? ?struct nand_ecc_ctrl ecc; ?? ?struct nand_buffers *buffers; ?? ?struct nand_hw_control hwcontrol; ?? ?struct mtd_oob_ops ops; ?? ?uint8_t?? ??? ?*bbt; ?? ?struct nand_bbt_descr?? ?*bbt_td; ?? ?struct nand_bbt_descr?? ?*bbt_md; ?? ?struct nand_bbt_descr?? ?*badblock_pattern; ?? ?void?? ??? ?*priv; }; 这上面有一个与ECC相关的结构体?struct nand_ecc_ctrl struct nand_ecc_ctrl {
hwctl:这个函数用来控制硬件产生ecc,其实它主要的工作就是控制NAND controller向NAND芯片发出NAND_ECC_READ、NAND_ECC_WRITE和NAND_ECC_READSYN等命令,与struct nand_chip结构体中的cmdfunc类似,只不过发起的命令是ECC相关的罢了;
?
calculate:根据data计算ecc值;
?
correct:根据ecc值,判断读写数据时是否有错误发生,若有错,则立即试着纠正,纠正失败则返回错误;
?
read_page_raw和write_page_raw:从NAND芯片中读取一个page的原始数据和向NAND芯片写入一个page的原始数据,所谓的原始数据,即不对读写的数据做ecc处理,该读写什么值就读写什么值。另外,这两个函数会读写整个page中的所有内容,即不但会读写一个page中MAIN部分,还会读写OOB部分。
?
read_page和write_page:与read_page_raw和write_page_raw类似,但不同的是,read_page和write_page在读写过程中会加入ecc的计算,校验,和纠正等处理。
read_oob和write_oob:读写oob中的内容,不包括MAIN部分。
?
其实,以上提到的这几个read_xxx和write_xxx函数,最终都会调用struct nand_chip中的read_buf和write_buf这两个函数,所以如果没有特殊需求的话,我认为不必自己实现,使用MTD提供的default的函数即可。
下面这个结构体用来ECC在oob中布局的一个结构体。 struct nand_ecclayout { 大家都知道OOB但是OOB里面究竟存了些什么,OOB主要用来存储两种信息:坏块信息和ECC数据,对于小页的NANDFLASH一般坏块占据一个字节(并且是在第6个字节),ECC占3个字节,上面这个结构体就是起到了这个作用告诉那些与操作ECC无关的函数,在OOB区域里那部分是来存储ECC的(不可他用),那些字节是空闲的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |