高手进阶Linux系统下MTD/CFI驱动介绍

2016-01-29 17:38 1 1 收藏

高手进阶Linux系统下MTD/CFI驱动介绍,高手进阶 Linux系统下MTD/CFI驱动介绍

【 tulaoshi.com - Linux 】

因为前不久作了些关于FLASH编程方面的东西,加上看了Linux下MTD/CFI代码,感觉收获不小,就准备记个笔记,没想到竟然花了半天时间才写好。

  某些Intel的FLASH芯片(如StrataFlash系列)支持多分区,也就是各个分区可以同时进行操作。应该说这是不错的特性,但是也会带来些问题。记得当初移植Linux-2.4.21,挂JFFS2文件系统的时候,经常会报一些"Magic bitmask not found"之类的错误,跟进去发现FLASH读出来的都是些0x80之类的数据,查看资料发现该款FLASH有分区的特性,而Linux的FLASH驱动只用一个状态变量表示整个FLASH的状态,这就会造成某个分区的实际状态和系统记录的不符,从而导致读FLASH的时候该点实际上不处在读状态。当时的解决办法是,每次读的时候,不管记录的状态是什么,先进入读状态再说,当然这会带来性能的下降,具体损失多少个时钟周期就不算了。

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/linux/)

   话说进入Linux-2.6.x的时代(具体是2.6.13),除了Lock/Unlock(Linux在擦/写的时候不先Unlock,解决办法就是初始化的时候先全部Unlock)这个老问题外,竟然多分区的错误没有出现,惊讶之下决定好好研究下Linux的MTD/FLASH驱动。

  说驱动之前,先明确几个编程要点:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/linux/)

  1:读写,要按照总线位宽读写,注意不是FLASH芯片位宽(例如背靠背)。

  2:寻址,程序要访问的地址和FLASH芯片地址引脚得到的值是不一样的,例如16位的FLASH芯片,对于CPU,0x00和0x01表示2个不同的字节,但是到了FLASH引脚得到的都是0,也就是都指向FLASH的第一个WORD。可以认为地址总线的bit0悬空,或者认为转换总线, bit0上实际输出的是bit1。这个解释了要点1。

  3:芯片手册提到偏移量都是基于WORD的,而WORD的位宽取决于芯片的位宽,因此在下命令的时候,实际偏移=手册偏移*buswidth/8。

  4:芯片手册提到的变量长度(典型如CFI信息)例如2,指的是,变量是个16bit数,但是读的时候,要读2个WORD,然后把每个WORD的低8位拼成1个16bit数。读WORD再拼凑确实挺麻烦,尤其是读取大结构的时候,不过参照cfi_util.c的cfi_read_pri函数的做法就简单了。

  5:背靠背,也就是比方说2块16位的芯片一起接在32位的总线上。带来的就是寻址的问题,很显然,首先要按32位读写;其次就是下命令的地址,实际偏移=手册偏移*interleave*device_type/8,device_type=buswidth/interleave,而buswidth这个时候是32(总线位宽)。另外就是背靠背的时候,命令和返回的状态码是“双份的”,例如2块16位背靠背,读命令是0x00ff00ff。

  如果不是想写像Linux那么灵活的代码(考虑各种接法/位宽/CFI获取信息等),那事情就简单很多,只要考虑要点1以及擦除块的大小就好了,当然如果是背靠背接法,擦除块的实际大小要乘个interleave。

  下面就进入Linux代码,不过关于CHIP/MAP/MTD之间绕来绕去的关系现在还糊涂着呢,因此下面只是简单的跟一下脉络和各个编程要点。

  1:构造map_info结构,指定基址/位宽/大小等信息以及"cfi_probe"限定,然后调用do_map_probe()。

  2:do_map_probe()根据名字"cfi_probe"找到芯片驱动"cfi_probe.c"直接调用cfi_probe()。

  3:cfi_probe()直接调用mtd_do_chip_probe(),传入cfi_probe_chip()函数指针。

  4:mtd_do_chip_probe()分2步,先调用genprobe_ident_chips()探测芯片信息,后调用check_cmd_set()获取和初始化芯片命令集(多分区初始化就在里面)。

  5:genprobe_ident_chips()函数如果不考虑多芯片串连的情况,那只需看前面的genprobe_new_chip()调用,完成后cfi.chipshift=cfi.cfiq-DevSize,2^chipshift=FLASH大小。

  6:genprobe_new_chip()枚举各种不同的芯片位宽和背靠背数量,结合配置设定依次调用步骤3的cfi_probe_chip(),注意cfi-device_type=bankwidth/nr_chips,bankwidth是总线位宽,device_type是芯片位宽。这里我们只需要注意有限复杂情况即可,所谓有限复杂指的是编译时确定的复杂连接。这样,cfi_probe_chip()只有第1次调用才成功,如果考虑32位宽的FLASH插在16bit总线上的情况,那第2次调用成功。

  7:cfi_probe_chip(),由于步骤6的原因,函数就在cfi_chip_setup()直接返回,后面的代码就不用考虑了。

  8:cfi_chip_setup()读取CFI信息,可以留意下Linux是怎么实现要点4的。

  9:回到步骤4的check_cmd_set()阶段,进入cfi_cmdset_0001()函数,先调用read_pri_intelext()读取Intel的扩展信息,然后调用cfi_intelext_setup()初始化自身结构。

  10:read_pri_intelext()函数,可以留意下怎么读取变长结构的技巧,也就是"need_more"的用法。这里说明下一些变量的含义,例如对于StrataFlash 128Mb Bottom类型的的FLASH芯片,块结构是4*32KB+127*128KB=16MB,一共16个分区,每个分区1MB。nb_parts=2。

  第1部分

  NumIdentPartitions=1 // 有1个重复的分区

来源:https://www.tulaoshi.com/n/20160129/1502274.html

延伸阅读
标签: PHP
            { 相信大多数人在安装Linux时遇到的第一个难题,就是Linux不认你的显卡。而显卡安装不正确或胡乱选一个驱动程序安上则难以进入X Window。即使勉强进去了,因为分辨率太低,桌面上的文字和图片都放大了好几倍,仍无法使用。我的Linux是Red Hat,显卡是Trident Blade 3D...
标签: 电脑入门
系统中首先要安装过相应的播放软件及解码器。 比如: mplayer和Xine. 1.安装 mplayerplug-in for mozilla 可以在Firefox中在地址栏输入about:plugins 来查看安装的插件 2.安装 Firefox 扩展mediawrap 下载页面 http://addons.mozine.cn/firefox/116/ mediawrap 是一个很小的 Firefox 扩展。它能够将 ActiveX 控...
原来电脑装的是windows和redflag linux,后来感觉不爽,就准备卸载linux。于是,开始了卸载之旅: 一、在windows下的我的电脑→管理→磁盘管理,会看到没有名字的linux分区,在上面点右键,删除逻辑分区 二、重新启动,改动bios启动顺序,把从磁盘启动给禁用,一定要禁用。 三、保存bios设置,并重新启动,插入windows安...
    针对好多Linux 爱好者对内核很有兴趣却无从下口,本文旨在介绍一种解读linux内核源码的入门方法,而不是解说linux复杂的内核机制; 一.核心源程序的文件组织:   1.Linux核心源程序通常都安装在/usr/src/linux下,而且它有一个非常简单的编号约定:任何偶数的核心(例如2.0.30)都是一个稳定地发行的核心...
标签: 电脑入门
不少用户总认为将网卡设备的驱动程序及时升级到最新版本,能够最大限度地挖掘出网卡设备的全部能量来,为此这些用户常常努力地进行网卡驱动更新操作。事实上,目前不少最新版本的网卡驱动程序,不是存在这样的BUG,就是存在那样的BUG,要是轻易地将它们安装在本地计算机系统中时,网卡设备反而不能稳定工作,甚至还可能导致网卡无法工作。因此...

经验教程

529

收藏

39
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部