MTD坏块管理(二)-内核获取Nandflash的参数过程
MTD坏块管理机制中,起着核心作用的数据结构是nand_chip,在此以TCC8900-Linux中MTD的坏块管理为例作一次介绍。 MTD在Linux内核中同样以模块的形式被启用,TCC_MTD_IO_Init()函数完成了nand_chip初始化、mtd_info初始注册, 坏块表的管理机制建立等工作。 nand_chip在TCC_MTD_IO_Init函数中的实例名称是this,mtd_info 的实例名称为TCC_mtd,这里有一个比较巧妙的处理方法: TCC_mtd=kmalloc(sizeof(struct mtd_info)+sizeof(struct nand_chip),GFP_KERNEL); this=(struct nand_chip*)(&TCC_mtd[1]); 在以后的操作中,只需得知TCC_mtd即可找到对应的nan_chip实例。 获得必要的信息后(包括nand_chip方法的绑定),流程进入nand_scan(TCC_mtd,1). nand_scan(struct mdt_info *mtd,int maxchips); 调用nand_scan_ident(mtd,maxchips)和nand_scan_tail(mtd); nand_scan_ident(...)调用了一个很重要的函数:nand_get_flash_type(...) *从nand_get_flash_type(...)函数中可以看出每个nandflash前几个字节所代表的意思都是约定好了的: 第一个字节:制造商ID 第二个字节:设备ID 第三个字节:MLC 数据 第四个字节:extid (比较总要) 其中设备ID是访问nand_flash_ids表的参照,该表在drivers/mtd/nand/nand_ids.c中定义 Linux内核在nand_flash_ids参照表中,通过匹配上述设备ID来查找nandflash的详细信息, nand_flash_ids中的举例如下: struct nand_flash_dev nand_flash_ids[]={ ...... {"NAND 16MiB 1,8V 8-bit",? 0x33,512,16,0x4000,0}, {"NAND 16MiB 3,3V 8-bit",? 0x73, {"NAND 16MiB 1,8V 16-bit",?0x43,NAND_BUSWIDTH_16},3V 16-bit",?0x53, ...... } 466 struct nand_flash_dev { 467 ? ? char *name; 468 ? ? int id; 469 ? ? unsigned long pagesize; 470 ? ? unsigned long chipsize; 471 ? ? unsigned long erasesize; ? ? 472 ? ? unsigned long options; ? ? ? 473 };? 值得一提的是,MTD子系统会把从nand_flash_ids表中找到的chipsize复制给mtd->size,这在有些应用中显得不合适, 在有些方案中,并不是把nandflash的所有存储空间都划分为MTD分区,Telechips的TCC89XX方案就是这样,4G的nandflash 上,可以划分任意大小的MTD分区,错误的mtd->size的后果非常严重,造成系统启动慢,整个MTD的坏块管理机制瘫痪等等。 随后,nand_get_flash_type通过extid计算出了以下信息: mtd可写区大小:mtd->writesize=1024<<(extid&0x03); 这里可以看成1024*(1*2的(extid&0x03)次方), mtdoob区大小:extid>>=2;mtd->oobsize = (8<<(extid&0x1))*(mtd->writesize>>9); 每512字节对应(8*2的(extid&0x1)次方)字节oob数据 mtd擦写块大小:extid>>=2;mtd->erasesize=(64*1024)<<(extid&0x03); nand数据宽度 :extid>>=2;busw=(extid&0x01)?NAND_BUSEWIDTH_16:0; 现在大多为8位数据宽度 可以看出第四个字节extid的意义: 高|0 ? ?| ?0 ? ? ? ?| ? 00 ? ? ? ?| 0 ? | 0 ? ? ? ? | ?00 ? ? ? ? ? |低 ?? |无用|数据宽度|擦写块算阶|无用|oob算阶| ?可写区算阶| nand_get_flash_type(...)还确立了nandflash中的坏块标记在oob信息中的位置: if(mtd->writesize>512||(busw&NAND_BUSWIDTH_16)) ?? ?chip->badblockpos = NAND_LARGE_BADBLOCKS_POS;//大页面flash的坏块信息存储地址为oob信息中的第1个字节开始处 else ?? ?chip->badblockpos = NAND_SMALL_BADBLOCKS_POS;//大页面flash的坏块信息存储地址为oob信息中的第6个字节开始处 对于Samsun和Hynix的MLC型nandflash,坏块标记所在的页是每块的最后一个页,而Samsung,Hynix,和AMD的SLC型nandflash 中,坏块标记分别保存在每块开始的第1,2个页中,其他型号的nandflash大多都保存在第一个也中,为此需要作下标记: 坏块标记保存在块的最后一页中:chip->options |= NAND_BBT_SCANLASTPAGE; 坏块标记保存在块的第1,2页中 :chip->options |= NAND_BBT_SCAN2NDPAGE; nand_scan之后调用nand_scan_tail(mtd)函数, nand_scan_tail(...)函数主要完成MTD实例中各种方法的绑定,例如: 3338 ? ? mtd->read = nand_read; 3339 ? ? mtd->write = nand_write; 3340 ? ? mtd->panic_write = panic_nand_write; 3341 ? ? mtd->read_oob = nand_read_oob; 3342 ? ? mtd->write_oob = nand_write_oob; 3343 ? ? mtd->sync = nand_sync; nand_scan_tail(...)调用chip->scan_bbt()完成坏块表的有关操作。 chip->scan_bbt的绑定过程是在nand_scan_ident()->nand_set_defaults():chip->scan_bbt = nand_default_bbt. 即真正用于坏块操作的是nand_default_bbt函数,该函数在nand_bbt.c中被定义。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |