(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回家了,呵呵。

*/

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

  1. 嵌入式 linux nand flash 容量查看,Linux MTD下获取Nand flash 各个参数的过程的详细解析...

    下面是Linux MTD中,获取nand flash型号,各个参数,以及硬件特性的函数,其实也就是nand_get_flash_type,下面对其详细解析:1.1. Program(编程)此处的编程, ...

  2. Linux MTD架构下的nand flash驱动详解

    转载自:http://blog.csdn.net/wang_zheng_kai/article/details/18988521 有了前面的基础(Nandflash详解:https://blog.cs ...

  3. linux的系统架构,(转载)图解Linux系统的系统架构

    我以下图为基础,说明Linux的架构(architecture).(该图参考<Advanced Programming in Unix Environment>) 最内层是硬件,最外层是用 ...

  4. vuex获取php数据,Nuxt中如何使用Vuex-Store异步获取数据

    Nuxt持发秀事应差互过来商类如处.,到图近就这是一个基于Vue.js的通用型框架,它集成了使用Vue开发的绝大数组件/框架到二新,为都础过过发等宗和发制数事前理业待很理断到屏能击示和站公下图以使箭分 ...

  5. python 获取金融数据_class类在python中如何获取金融数据

    class类在python中如何获取金融数据 发布时间:2020-12-11 11:12:06 来源:亿速云 阅读:101 作者:小新 这篇文章主要介绍了class类在python中如何获取金融数据, ...

  6. ajax获取后台数据的几种方式及如何获取ajax内部的数据供外部使用

    文章目录 1 ajax获取后台数据的几种方式 1.1 原生js的ajax方式 1.1.1 get 1.1.2 post 1.2 jQuery封装的ajax方式 1.2.1 $.ajax 1.2.2 $ ...

  7. Java获取当前时间的上一个月和下一个月,第一天和最后一天,任意时间的第一天和最后一天,任意时间上一个月和下一个月

    /*** 获取当前时间* * @param args*/public static String getNowTime() {Calendar cal = Calendar.getInstance() ...

  8. surface pro linux服务器,Surface Pro平板电脑上安装Linux / Ubuntu的技巧

    嗯,Windows 10和Windows 8.1在Surface Pro上运行顺畅,但我认为有些用户想知道如何以及他们是否可以在上安装任何其他操作系统.您会很高兴听到答案是'是'.您始终可以将操作系统 ...

  9. 北京linux嵌入式培训,北京嵌入式培训上嵌Linux开发基础和嵌入式C语言初级编程总结...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 说到学习Linux开发基础,有一样是不得不说,而且Llinux系统中最常用也最有用的东西,那就是各种命令.虽然Linux桌面应用发展很快,但是命 令在Li ...

最新文章

  1. 【lidar】3D目标检测PointPillars:论文解读、代码解读、部署实现(1)
  2. 数据库性能测试---前阿里数据库团队资深DBA杨奇龙
  3. netty系列之:channelHandlerContext详解
  4. 原地置换法寻找数组中重复的数
  5. Java加密与解密的艺术~数字证书~证书管理openssl
  6. Internet Explorer 6 中的 CSS 增强功能
  7. hystrix基于request cache请求缓存技术优化批量数据查询接口
  8. ArcGISEngine二次开发(5):添加矢量要素
  9. html5表格制作教程,html怎么做表格
  10. js模板引擎—art-template的使用
  11. Latex常见数学符号写法
  12. NOIP2020总结
  13. win10多用户同时远程桌面登陆(允许多个RDP会话)-支持win10最新1909版2004版
  14. 我的大学 --- 郭天祥【1】
  15. 电脑故障维修判断指导大全(3)
  16. 国泰煤炭运销管理系统
  17. 计算机网络原理【第三章 数据链路层】课后习题答案
  18. c语言实现图片缩放,图片缩放与合并(C语言实现)
  19. linux新建分区步骤
  20. 中国汽车用品行业需求态势及销售前景规模调研报告2021-2027年

热门文章

  1. 深入剖析基于并发AQS的(独占锁)重入锁(ReetrantLock)及其Condition实现原理
  2. 【已解决】iphone和mac的备忘录、提醒事项、日历等无法同步。MacBook点击“更新Apple ID 设置”无反应。
  3. 决策树--信息增益、信息增益比、Geni指数的理解
  4. 4.TradingView K线和成交量没有自适应区域显示,ma线显示会错乱,高低不齐(巨坑)
  5. Spring Boot的shiro整合(下)
  6. 使用Python,OpenCV进行基本的图像处理——提取红色圆圈轮廓并绘制
  7. centos服务器部署
  8. 调用WindowsMedia播放器与Flash播放器
  9. 千万别删VS之ProgramData目录(血泪教训)
  10. CSS 中最后一行中元素如何向左对齐