Linux如何获取mtd数据,【转载】上接Linux MTD下获取Nand flash各个参数的过程的详细解析【转】...

本文详细解读了NAND Flash的页面大小(Page Size)计算方法,通过extid的位操作确定OBB区域大小,并介绍了块大小(Block Size)和组织方式(Organization)。同时讲解了如何通过设备ID识别制造商和适配硬件宽度。最后,涉及了现代NAND Flash的特殊处理,如大容量支持和自动增页功能。
摘要由CSDN通过智能技术生成

(1)Page Size:

如图,页大小,是bit0和bit1组合起来所表示的。

extid & 0x3,就是取得bit0和bit1的值,而左移1024位,是因为上面表中的单位是KB=2^10=1024。此处关于1024 << (extid & 0x3)这样的写法,再多说一下。

我之前也是看了很长时间,都没看懂,后来才看懂具体的意思的。

1024 << (extid & 0x3)其实就是

1024×(1<< (extid & 0x3))=前面的1024是因为单位是KB,而后面的写法,就是2的extid & 0x3的次方,比如,如果extid & 0x3是3,那么,1<< (extid & 0x3)就是1<<3=8,对应的上面的8KB。

*/

2477/* Calc pagesize */

(2)Redundant Area Size(byte/512byte):

前面介绍过了,此处的oob,就是datasheet中的redundant area size就是linux中的oob大小。

上面表中的意思是,512个byte,对应8还是16个字节的redundant area。

之所以是512字节对应多少个是因为以前的nand flash页大小是512(除了最早的好像是256之外),所以估计是硬件设计就这样设计了,512个字节对应多少个冗余的数据用作oob,而后来的页大小,对应的是512的整数倍,比如2K,4K等,所以,此处,可以按照每个512对应几个字节的oob,然后再算页大小是512的多少倍,即:

此处的extid & 0x01算出来的值,对应上面的8或16,而mtd->writesize >> 9,其实就是

td->writesize /512,到此,才算清楚,为何此处oob是这么算的。

*/

2480/* Calc oobsize */

2481mtd->oobsize= (8 << (extid& 0x01)) * (mtd->writesize>> 9);

/*

(3)Block Size:

具体算法很清楚,算出是64KB的多少倍,得出总大小。

*/

2483/* Calc blocksize. Blocksize is multiples of 64KiB */

2484mtd->erasesize= (64 * 1024) << (extid& 0x03);

/*

(4)Organization:

X8/X16,表示的是,硬件I/O位宽(Bus Width)是8位的还是16位的。

目前大多数,都是X8的。

*/

2486/* Get buswidth information */

2489} else {

旧的nand flash的一些参数,是知道设备ID后,可以直接从表中读取出来的。

*/

2491* Old devices have chip data hardcoded in the device id table

/*

根据读取出来的生长厂商的ID,去和表中对应项匹配,找到是哪家的nand flash芯片。

其中,nand_manuf_ids和上面nand_flash_ids类似,也是个预先定义好的数组,其定义和nand_flash_ids同文件:

drivers\mtd\nand\nand_ids.c中:

/*

*Manufacturer ID list

*/

struct nand_manufacturers nand_manuf_ids[] = {

{NAND_MFR_TOSHIBA, "Toshiba"},

{NAND_MFR_SAMSUNG, "Samsung"},

{NAND_MFR_FUJITSU, "Fujitsu"},

{NAND_MFR_NATIONAL, "National"},

{NAND_MFR_RENESAS, "Renesas"},

{NAND_MFR_STMICRO, "ST Micro"},

{NAND_MFR_HYNIX, "Hynix"},

{NAND_MFR_MICRON, "Micron"},

{NAND_MFR_AMD, "AMD"},

{0x0, "Unknown"}

};

比如最对应的宏和结构体定义在:

include\linux\mtd\nand.h中:

/*

* NAND Flash Manufacturer ID Codes

*/

#define NAND_MFR_TOSHIBA0x98

#define NAND_MFR_SAMSUNG0xec

#define NAND_MFR_FUJITSU0x04

#define NAND_MFR_NATIONAL0x8f

#define NAND_MFR_RENESAS0x07

#define NAND_MFR_STMICRO0x20

#define NAND_MFR_HYNIX0xad

#define NAND_MFR_MICRON0x2c

#define NAND_MFR_AMD0x01

/**

* struct nand_manufacturers - NAND Flash Manufacturer ID Structure

* @name:Manufacturer name

* @id:manufacturer ID code of device.

*/

struct nand_manufacturers {

int id;

char * name;

};

比如我们读到的是,最常见的0xEC,对照上面的定义,就是Samsung,表示此款nand flash是三星家的。

*/

2499/* Try to identify manufacturer */

2502break;

/*

检测你的驱动中的关于位宽的定义,适合和硬件所一致。

*/

2506* Check, if buswidth is correct. Hardware drivers should set

2507* chip correct !

2510printk(KERN_INFO"NAND device: Manufacturer ID:"

2511"0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,

2513printk(KERN_WARNING"NAND bus width %d instead %d bit\n",

2515busw? 16 : 8);

/*

此处计算的pagesize,blocksize等的shift,是为了后期的对这些值的除操作更加高效而做的。

对于代码中的除操作,如果直接只是/pagesize,则没有直接算出其是2的多少次方,然后用位移操作,更加高效。因此,此处直接计算好是多少个shift,以后的除于pagesize,blocksize,就可以直接用对应的位移操作了。

*/

2519/* Calculate the address shift from the page size */

算出mask,为了后期保证传入的地址不越界,所以会对其mask一下。

*/

2521/* Convert chipsize to number of pages per chip -1. */

/*

这段,貌似是新的kernel里面新加的,而且把chip->chipsize定义换成uint64_t了,支持超过4GB大小的nand flash了,否则,如果你正好是4GB,对于旧的代码chip->chipsize是uint32_t类型的,那么正好就变成0了。

此处之所以去chip->chipsize & 0xffffffff判断是超过4GB,看起来,估计是ffs函数最多支持32位,所以,没法计算超过此大小的ffs。

简单说一下,ffs是计算一个数值的第一个被置位的位置,全称好像是find first set bit,其简单解释如下:

ffs

查找第一个已设置的位

int ffs (int x)

x为要搜索的字。

刚百度了一下,好像还有个对应的函数:ffz,找到第一个0的位置,估计就是find first zero bit了。呵呵。

而且,这些,好像是Linux提供的基本函数库里面的,自己之前都没怎么听说过呢。汗一个先。。。

*/

2526if (chip->chipsize& 0xffffffff)

2528else

2529chip->chip_shift=ffs((unsigned)(chip->chipsize>> 32)) + 32 - 1;

/*

设置坏块的标记位置。

关于nand flash的small block和large block,据我了解,好像就是对应的small pagesize和large pagesize,而此处的大小,是针对于旧的nand flash,其页大小pagesize是512,所以,

Small block就是页大小是512B的nand flash,而larger block就是新的,页大小大于512B的,比如2KB,4KB等的nand flash。

下面的宏定义在

include\linux\mtd\nand.h中:

/*

* Constants for oob configuration

*/

#define NAND_SMALL_BADBLOCK_POS5

#define NAND_LARGE_BADBLOCK_POS0

约定俗成的,small block的nand,坏块标记在byte5,而large block的nand flash在byte0。

关于坏块标记,实际情况更复杂些:

【Nand Flash坏块标记位置】

对于2K页的nand flash,标记位置都是页内oob开始处,都是非0xFF表示坏块,

但是,对于是第几页,不同nand flash就有不同的规定了:

有些nand flash,是标记在坏块的第一个页(或者是第二个页,这点是考虑到,万一第一个页是坏的,所以才做此规定的。一般都是在第一个页处做标记),比如三星的多数SLC,Hynix等;另一些,是在一个块内的最后一页或倒数第二页做此标记,比如samsung MLC , Numonyx等。所以,真正比较完整的检查坏块的做法,至少要检测块内第一,第二,倒数第一,倒数第二页,是否是0xFF,才能比较全面的判断是否是坏块的。

*/

2531/* Set the bad block position */

获得上面nand id表中的默认设置的那些option:LP_OPTIONS(如果是X16则是,LP_OPTIONS16)。

*/

2535/* Get chip options, preserve non chip based options */

自动增加页数???没太搞懂啥意思,估计是cache program/read相关的吧,目前据我了解的,好像页只有cache program/read,能和auto increment pages有点关系。

*/

2540* Set chip as a default. Board drivers can override it, if necessary

/*

如果有extentID且不是三星的nand flash,则清除掉上面我们默认设置的那些参数:LP_OPTIONS。

*/

2544/* Check if chip is a not a samsung device. Do not clear the

2545* options for chips which are not having an extended id.

/*

一种特殊的nand flash,AND chip。所以,也要赋值给特殊的擦除函数。

具体关于此类nand flash的介绍,感兴趣的自己参考上面drivers\mtd\nand\nand_ids.c中nand_flash_ids数组中的解释。

*/

2550/* Check for AND chips with 4 page planes */

2553else

如果nand flash的页大小是大于512B,也就是2KB,4KB等新的,被称作large block或largepage的nand flash,此处的lp,应该也就是large page的缩写。

此类的nand flash比旧的,在发送地址的时候,多一个地址周期。具体参考datasheet。

*/

2556/* Do not replace user supplied command function ! */

/*

终于检测完所有需要的信息了。最后打印出nand flash的相关信息。

*/

2560printk(KERN_INFO"NAND device: Manufacturer ID:"

2561"0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,dev_id,

/*

活干完了,就可以return回家了,呵呵。

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值