《Linux内核MTD驱动程序与SD卡驱动程序》由会员分享,可在线阅读,更多相关《Linux内核MTD驱动程序与SD卡驱动程序(70页珍藏版)》请在金锄头文库上搜索。
1、Linux 内核 MTD 驱动程序与 SD 卡驱动程序flash 闪存设备和 SD 插卡设备是嵌入式设备用到的主要存储设备,它们相当于 PC 机的硬盘。在嵌入设备特别是手持设备中,flash 闪存是焊接在嵌入设备主 板上的 flash 闪存芯片。在嵌入设备上有 MMC/SD 卡控制器及插槽,可通过 MMC/SD 来扩充存储空间。 嵌入设备的存储设备的空间划分及所有逻辑设备和文件系统示例列出如下图: 图:嵌入设备的存储空间划分及文件系统示例图在嵌入设备上的 flash 芯片上 blob 和 zImage 直接按内存线性地址存储管理, 对于 flash 芯片上留出的供用户使用的存储空间,使用 MT
2、DBLOCK 块设备和 JFFS2 文件系统。对于 flash 芯片的分区表信息则以 MTDCHAR 字符设备来存储 管理。 在嵌入设备上的 MMC/SD 插卡则由 MMCBLOCK 驱动程序和 VFAT 文件系统进行存储 管理。本章分析了 MTD 设备和 MMC/SD 驱动程序。 Figure 3-1. UBI/MTD Integration 目目录录隐藏1 MTD 内存技术设备 o1.1 MTD 内存技术设备层次结构 o1.2 设备层和原始设备层的函数调用关系 o1.3 MTD 相关结构 o1.4 MTD 块设备初始化 o1.5 MTD 块设备的读写操作 o1.6 MTD 核心初始化 o1
3、.7 MTD 字符设备 o1.8 具体 flash 芯片的探测及映射 o1.9 驱动程序实例分析 2 SD/MMC 卡块设备驱动程序 o2.1 MMC 抽象设备层相关结构 2.1.1 (1)设备描述结构 2.1.2 (2) 读写请求相关结构 o2.2 MMC 抽象设备层 MMC 块设备驱动程序 2.2.1 (1)MMC 块设备驱动程序初始化 2.2.2 (2)MMC 块设备驱动程序探测函数 2.2.3 (3)MMC 卡请求的处理 o2.3 具体 MMC 控制器驱动程序示例 2.3.1 (1)amba 控制器驱动程序相关结构 2.3.2 (2)amba 控制器的初始化 2.3.3 (3)设备探测
4、函数 mmci_probe 2.3.4 (4)amba 控制器操作函数 MTDMTD 内存技术设备内存技术设备 Linux 中 MTD 子系统在系统的硬件驱动程序和文件系统之间提供通用接口。在 MTD 上常用的文件文件系统是 JFFS2 日志闪存文件系统版本 2(Journaling Flash File System)。JFFS2 用于微型嵌入式设备的原始闪存芯片的文件系统。 JFFS2 文件系统是日志结构化的,这意味着它基本上是一长列节点。每个节点 包含有关文件的部分信息 可能是文件的名称、也许是一些数据。与 Ext2 文 件系统相比,JFFS2 因为有以下这些优点: JFFS2 在扇区级
5、别上执行闪存擦除写读操作要比 Ext2 文件系统好。JFFS2 提供了比 Ext2fs 更好的崩溃掉电安全保护。当需要更改少量数据时,Ext2 文件系统将整个扇区复制到内存(DRAM)中,在内存中合并新数据,并写回整 个扇区。这意味着为了更改单个字,必须对整个扇区(64 KB)执行读擦除 写例程 ,这样做的效率非常低。JFFS2 是附加文件而不是重写整个扇区,并且 具有崩溃掉电安全保护这一功能。 JFFS2 是是为 FLASH 定制的文件系统,JFFS1 实现了日志功能,JFFS2 实现了压 缩功能。它的整个设计提供了更好的闪存管理。JFFS2 的 缺点很少,主要是当 文件系统已满或接近满时,
6、JFFS2 会大大放慢运行速度。这是因为垃圾收集的 问题。 MTD 驱动程序是专门为基于闪存的设备所设计的,它提供了基于扇区的擦除和 读写操作的更好的接口。MTD 子系统支持众多的闪存设备,并且有越来越多的 驱动程序正被添加进来以用于不同的闪存芯片。 MTD 子系统提供了对字符设备 MTD_CHAR 和块设备 MTD_BLOCK 的支持。MTD_CHAR 提供对闪存的原始字符访问,象通常的 IDE 硬盘一样,在 MTD_BLOCK 块设备上 可创建文件系统。MTD_CHAR 字符设备文件是 /dev/mtd0、mtd1、mtd2 等, MTD_BLOCK 块设备文件是 /dev/mtdbloc
7、k0、mtdblock1 等等。 NAND 和 NOR 是制作 Flash 的工艺,CFI 和 JEDEC 是 flash 硬件提供的接口, linux 通过这些用通用接口抽象出 MTD 设备。JFFS2 文件系统就建立在 MTD 设备 上。 NOR flash 带有 SRAM 接口,可以直接存取内部的每一个字节。NAND 器件使用串 行 I/O 口来存取数据, 8 个引脚用来传送控制、地址和数据信息。NAND 读和写 操作用 512 字节的块。 MTDMTD 内存技术设备层次结构内存技术设备层次结构 MTD(memory technology device 内存技术设备) 在硬件和文件系统层
8、之间的提 供了一个抽象的接口,MTD 是用来访问内存设备(如:ROM、flash)的中间层, 它将内存设备的共有特性抽取出来,从而使增加新的内存设备驱动程序变得更 简单。MTD 的源代码都在/drivers/mtd 目录中。 MTD 中间层细分为四层,按从上到下依次为:设备节点、MTD 设备层、MTD 原始 设备层和硬件驱动层。MTD 中间层层次结构图如下: 图 1 MTD 中间层层次结构图Flash 硬件驱动层对应的是不同硬件的驱动程序,它负责驱动具体的硬件。例 如:符合 CFI 接口标准的 Flash 芯片驱动驱动程序在 drivers/mtd/chips 目录 中,NAND 型 Flas
9、h 的驱动程序在/drivers/mtd/nand 中。 在原始设备层中,各种内存设备抽象化为原始设备,原始设备实际上是一种块 设备,MTD 字符设备的读写函数也调用原始设备的操作函数来实现。MTD 使用 MTD 信息结构 mtd_info 来描述了原始设备的操作函数、各种信息,所有原始设 备的信息也用一个全局的结构数组来描述,列出如下(在 drivers/mtd/mtdcore.c 中): struct mtd_info *mtd_tableMAX_MTD_DEVICES;每个原始设备可能分成多个设备分区,设备分区是将一个内存分成多个块,每 个设备分区用一个结构 mtd_part 来描述,所
10、有的分区组成一个链表 mtd_partitions,这个链表的声明列出如下(在 drivers/mtd/mtdpart.c 中):/* Our partition linked list */ static LIST_HEAD(mtd_partitions);MTD 原始设备到具体设备之间存在的一些映射关系数据在 drivers/mtd/maps/目录下的对应文件中。这些映射数据包括分区信息、I/O 映射及特定函数的映射 等。这种映射关系用映射信息结构 map_info 描述。 在 MTD 设备层中,MTD 字 符设备通过注册的 file operation 函数集来操作设备,而这些函数是通过
11、原始 设备层的操作函数来实现的,即调用了块设备的操作函数。MTD 块设备实际了 从块层到块设备的接口函数。所有的块设备组成一个数组 *mtdblksMAX_MTD_DEVICES,这个结构数组列出如下(在 drivers/mtd/mtdblock.c 中): static struct mtdblk_dev struct mtd_info *mtd;int count;struct semaphore cache_sem;unsigned char *cache_data;unsigned long cache_offset;unsigned int cache_size;enum STATE
12、_EMPTY, STATE_CLEAN, STATE_DIRTY cache_state; *mtdblksMAX_MTD_DEVICES;由于 flash 设备种类的多样性,MTD 用 MTD 翻译层将三大类 flash 设备进行的 封装。每大类设备有自己的操作函数集,它们的 mtdblk_dev 结构实例都存在 mtdblks 数组中。MTD 设备在内核中的层次图如下图。 图 MTD 设备在内核中的层次图MTD 原始设备层中封装了三大类设备,分别是 Inverse Flash、NAND Flash 和 MTD。它们的上体读写方法不一样。这里只分析了 MTD,因为它是最常用的。 设备层和原始
13、设备层的函数调用关系设备层和原始设备层的函数调用关系 原始设备层主要是通过 mtd_info 结构来管理设备,函数 add_mtd_partitions()和del_mtd_partitions()将的设备分区的 mtd_info 结构加入 mtd_table 数组中, mtdpart.c 中还实现了 part_read、part_write 等函数,这些函数注册在每个 分区中,指向主分区的 read、write 函数,之所以这样做而不直接将主分区的 read、write 函数连接到每个分区中的原因是因为函数中的参数 mtd_info 会被 调用者置为函数所属的 mtd_info,即 mtd-
14、read(mtd),而参数 mtd_info 其 实应该指向主分区。 设备层和原始设备层的函数调用关系图如图 2。MTD 各种结构之间的关系图如图 3。 图 2 设备层和原始设备层的函数调用关系图 3 MTD 各种结构之间的关系MTDMTD 相关结构相关结构 MTD 块设备的结构 mtdblk_dev 代表了一个闪存块设备,MTD 字符设备没有相对 应的结构。结构 mtdblk_dev 列出如下: struct mtdblk_dev struct mtd_info mtd; / Locked */下层原始设备层的 MTD 设备结构int count;struct semaphore cache
15、_sem;unsigned char *cache_data; /缓冲区数据地址unsigned long cache_offset;/在缓冲区中读写位置偏移/缓冲区中的读写数据大小(通常被设置为 MTD 设备的 erasesize)unsigned int cache_size;enum STATE_EMPTY, STATE_CLEAN, STATE_DIRTY cache_state;/缓冲 区状态 结构 mtd_info 描述了一个 MTD 原始设备,每个分区也被实现为一个 mtd_info,如果有两个 MTD 原始设备,每个上有三个分区,在系统中就一共有 6 个 mtd_info 结构
16、,这些 mtd_info 的指针被存放在名为 mtd_table 的数组里。 结构 mtd_info 分析如下: struct mtd_info u_char type;/内存技术的类型u_int32_t flags;/标志位u_int32_t size; / mtd 设备的大小/“主要的”erasesize(同一个 mtd 设备可能有数种不同的 erasesize)u_int32_t erasesize; u_int32_t oobblock; / oob 块大小,例如:512u_int32_t oobsize; /每个块 oob 数据量,例如 16u_int32_t ecctype; /ecc 类型u_int32_t eccsize; /自动 ecc 可以工作的范围/ Kernel-only stuff starts here.char *name;int index;/可变擦除区域的数据,如果是 0,意味着整个设备为 erasesizeint n