Linux NAND FLASH驱动程序分析(mini2440)
一、Linux-MTD Subsystem介绍
FLASH在嵌入式系统中是必不可少的,它是bootloader、linux内核和文件系统的最佳载体。在Linux内核中引入了MTD子系统为NOR FLASH和NAND FLASH设备提供统一的接口,从而使得FLASH驱动的设计大为简化。
在引入MTD后Linux系统中FLASH设备驱动可分为四层,如图:
1. 硬件驱动层
FLASH硬件驱动层负责FLASH硬件设备的读、写、擦出,LINUX MTD设备的NOR FLASH驱动位于/driver/mtd/chips子目录下,NAND FLASH驱动则位于/driver/mtd/nand子目录下。
特定硬件层负责完成特定硬件的读写,例如2440的/driver/mtd/nand/s3c2410.c
通用驱动为所有nand的通用部分,实现nand设备发现,通用读写等./driver/mtd/nand/nand_base.c
2. MTD原始设备层:MTD原始设备层由两部分构成,一部分是MTD原始设备的通用代码(mtdcore.c、mtdpart.c),另一部分是各个 特定的FLASH的数据,例如分区。
3. MTD设备层:基于MTD原始设备,LINUX系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90),构成设备层。MTD字符设备在mtdchar.c实现,MTD块设备在mtdblock.c实现。
4. 设备节点:通过mknod在/dev子目录下建立MTD字符设备节点(主设备号为90)和块设备节点(主设备号为31),用户通过访问此设备节点即可访问MTD字符设备和块设备。
也可通过下图理解:
从上图可以看出,MTD设备层与原始设备层打交道。通过分析源代码我们可以知道当上层要求对FLASH进行读写时,它会像设备层发出请求,设备层的读写函数会调用原始设备层中的读写函数,即mtd_info结构体(mtd原始设备层中描述设备的专用结构体)中的读写函数,而mtd_info中的函数会调用nand_chip(nand硬件驱动层中描述设备的结构体,其中包含了针对特定设备的基本参数和设备操作函数)中的读写函数。所以一个flash硬件驱动程序时的步骤大致如下:
1. 如果FLASH要分区,则定义mtd_partition数组,将FLASH分区信息记录其中。
mtd_partition friendly_arm_default_nand_part[],arch/arm/plat-s3c24xx/common-friendly-arm.c
2. 在模块加载时为每一个chip(主分区)分配mtd_info和nand_chip的内存,根据目标板nand 控制器的特殊情况初始化nand_chip中的实现对FLASH操作的成员函数,如hwcontrol()、dev_ready()、read_byte()、write_byte()等。填充mtd_info,并将其priv成员指向nand_chip。 driver/mtd/nand/s3c2410/c
3. 以mtd_info为参数调用nand_scan()函数探测NAND FLASH的存在。nand_scan()函数会从FLASH芯片中读取其参数,填充相应nand_chip成员。 driver/mtd/nand/nand_base/c
nand_scan()分为两步,首先是nand_scan_ident(),主要完成flashID的读取等,然后是nand_scan_tail(),主要完成chip结构体中未初始化函数的默认赋值,以及坏块的扫描。
4. 如果要分区,则以mtd_info和mtd_partition为参数调用add_mtd_partions(),添加分区信息。在这个函数里面会为每一个分区分配一个mtd_info结构体填充,并注册。
二、nand flash驱动程序实例分析
我们以2.6.29内核中mini2440的nand flash驱动程序为例来分析一下这个过程,这里的flash驱动被写成了platform驱动的形式。我们下面分析其过程:
1. 注册nand flash设备
nand flash分区:
nand控制器资源
2.注册nand flash driver
当platform_driver驱动被加载时或者是当platform_device被注册时,总线驱动程序
会查找与设备匹配的驱动程序,找到时设备驱动程序的probe函数会被调用,下面我们来分析一下在我们驱动程序中的probe函数
probe的具体调用流程见 Linux NAND FLASH驱动代码分析