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

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

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

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个重复的分区

NumBlockTypes=2      // 分区内有2种不同的Block类型

第1类型

NumIdentBlocks=3   // 有4个Block(3+1)

BlockSize=0x80     // 32KB(0x80*256)

第2类型

NumIdentBlocks=6   // 有7个Block(6+1)

BlockSize=0x200    // 128KB(0x200*256)

第2部分

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

NumBlockTypes=1      // 分区内有1种Block类型

第1类型

NumIdentBlocks=7   // 有8个Block(7+1)

BlockSize=0x200    // 128KB(0x200*256)

11:cfi_intelext_setup()函数首先根据CFI建立mtd_erase_region_info信息,然后调用cfi_intelext_partition_fixup()来支持分区。

12:cfi_intelext_partition_fixup()用来建立虚拟Chip,每个分区对应1个Chip,不过并没有完全根据CFI扩展信息来建立,而是假定每个分区的大小都一致。cfi->chipshift调整为partshift,各个虚拟chip->start调整为各分区的基址。将来访问FLASH的入口函数cfi_varsize_frob()就根据ofs得到chipnum(chipnum=ofs>>cfi->chipshift),这也是为什么要假定分区一致的原因。

linux CFI接口,高手进阶 Linux系统下MTD/CFI驱动介绍相关推荐

  1. linux系统下编写I2C驱动

    I2C 概述 I2C是philips提出的外设总线. I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线. ...

  2. Linux(CentOS 7_x64位)系统下安装RDkit(修正)

    Linux(CentOS 7_x64位)系统下安装RDkit(修正) 一.RDKit简介 Linux(CentOS 7_x64位)系统下安装RDkit点击打开链接 前面写的一篇CentOS 7下安装R ...

  3. OK6410开发板linux系统下的SPI驱动和测试

    OK6410下的SPI驱动是可以用的,但是飞凌把它作为其它用途了,我们修改一些代码才能在/dev目录下创建SPI的设备节点文件 Step1:打开arch/arm/mach_s3c64XX/mach_m ...

  4. 联想打印机 linux驱动怎么安装步骤,如何在MAC系统下安装打印机驱动

    故障现象: 如何在MAC系统下安装打印机驱动?解决方案: 一.LJ2208安装苹果驱动步骤: 1.运行lenovo Lj2208 install: 2.点击"继续": 3.软件许可 ...

  5. usrp运行完整linux,Ubuntu系统下USRP硬件驱动(UHD)的编译与安装

    在Ubuntu系统下USRP硬件驱动(UHD)安装最简单的方式就是直接从Ettus Research官方提供的PPA源安装,不过本文介绍的是如何从源代码进行编译与安装. 1.从PPA源安装只需要下面三 ...

  6. 【Ubuntu系列】Ubuntu20.04系统下3060显卡驱动安装记录

    [Ubuntu系列]Ubuntu20.04系统下3060显卡驱动安装记录 设备及相关信息简介 具体安装步骤 step1 获取显卡硬件信息 step2 在Ubuntu系统中卸载显卡驱动 step3 安装 ...

  7. 服务器双系统快捷键,Mac/Win7双系统下截屏快捷键介绍

    由于苹果电脑采用的是mac系统,使用的用户相对较少,不少购买苹果电脑的朋友经常会遇到一些截图困扰,接下来是小编为大家收集的Mac/Win7双系统下截屏快捷键介绍,希望能帮到大家. Mac/Win7双系 ...

  8. Linux(CentOS 7_x64位)系统下安装GaussView5

    GaussView GaussView是一个专门设计与高斯配套使用的软件,其主要用途有两个:构建高斯的输入文件和以图的形式显示高斯计算的结果.除了可以自己构建输入文件外,GaussView还可读入Ch ...

  9. xp下添加linux启动,如何在windows xp系统下安装linux???

    我刚刚想开始学linux,请教如何安装! | 我今天才安装了Redhat 9.0. LINUX不可能在WINDOWS下安装. 比较简单的方法是先在XP下用PQMAGIC分好区 boot  ext3 1 ...

最新文章

  1. Python剑指offer:和为s的连续整数序列
  2. android模拟器插件,Android模拟器插件找不到android SDK
  3. 纪念张首晟教授:英魂长存于行行字迹 何惧漫漫征途
  4. OpenJudge NOI 1.5 15:银行利息
  5. codeigniter view 试图里再引入view视图
  6. Unix——学习《Unix环境高级编程》找不到“apue.h”方法
  7. 高仿阴阳师官网轮播图效果的jQuery插件
  8. 吴恩达深度学习1.4笔记_Neural Networks and Deep Learning_深层神经网络
  9. 苹果笔记本调整 pycharm 字体大小的地方
  10. python 空列表对象的布尔值_python – 从TensorFlow对象中检索数据 – 来自correct_prediction的布尔值列表...
  11. utc时间 单位换算_utc时间(utc时间转换北京时间)
  12. 511遇见易语言教程API模块制作cmd复制文件
  13. vc html插件,VC++6.0插件系列(绝对经典)
  14. Resin服务器配置指南
  15. 损失函数、代价函数、目标函数、适应度函数的区别与联系
  16. (七)数字后端之形式验证
  17. 【解决方法】iOS 开发小技巧(一)
  18. NetFPGA-SUME上电测试
  19. iPad安卓协议是怎么实现功能的
  20. TcPlayer.js 实现文字朗读

热门文章

  1. 给初中级JAVA准备的面试题
  2. dynatrace_克服将Dynatrace部署到IBM Bluemix Local中的限制
  3. 持续交付-Blue Ocean 应用
  4. 如何处理连续值的概率问题?(概率密度)
  5. 本土浏览器如何步步演绎对国外浏览器的逆袭?
  6. 给自己写个过生日的贼简单的C 语言程序吧
  7. TYVJ p1006 isbn
  8. [洛谷P3946]ことりのおやつ(小鸟的点心)
  9. GVIM开发工具的使用方法
  10. django 国际化支持 I18N