Linux 2.6.11 MTD驱动情景分析
来源:互联网 发布:常州哪里有单片机卖 编辑:程序博客网 时间:2024/05/21 09:17
Linux 2.6.11 MTD驱动情景分析
最近几天为了熟悉linux的驱动开发,我选择了其MTD驱动做了一些研究。我能找到的文章中我觉得有些部分不够细致,所以我还是自己写了一部分分析,希望对别人也能有所帮助,也做为自己的一个备忘,。蓝色文字的部分是从网络上摘录的。
一个嵌入式系统经常会使用NOR flash 或NAND flash来存放bootload,内核和文件系统等等。
下面是网络上找到的linux下的mtd驱动的分析:
一、Flash硬件驱动层:硬件驱动层负责在init时驱动Flash硬件,Linux MTD设备的NOR Flash芯片驱动遵循CFI接口标准,其驱动程序位于drivers/mtd/chips子目录下。NAND型Flash的驱动程序则位于/drivers/mtd/nand子目录下
二、MTD原始设备:原始设备层有两部分组成,一部分是MTD原始设备的通用代码,另一部分是各个特定的Flash的数据,例如分区。
三、MTD设备层:基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90)。MTD字符设备的定义在mtdchar.c中实现,通过注册一系列file operation函数(lseek、open、close、read、write)。MTD块设备则是定义了一个描述MTD块设备的结构mtdblk_dev,并声明了一个名为mtdblks的指针数组,这数组中的每一个mtdblk_dev和mtd_table中的每一个mtd_info一一对应。
四、设备节点:通过mknod在/dev子目录下建立MTD字符设备节点(主设备号为90)和MTD块设备节点(主设备号为31),通过访问此设备节点即可访问MTD字符设备和块设备。
五、根文件系统:在Bootloader中将JFFS(或JFFS2)的文件系统映像jffs.image(或jffs2.img)烧到flash的某一个分区中,在/arch/arm/mach-your/arch.c文件的your_fixup函数中将该分区作为根文件系统挂载。
六、文件系统:内核启动后,通过mount 命令可以将flash中的其余分区作为文件系统挂载到mountpoint上。
NOR型Flash芯片驱动与MTD原始设备
每个MTD原始设备都有一个mtd_info结构,其中的priv指针指向一个map_info结构,map_info结构中的fldrv_priv指向一个cfi_private结构,cfi_private结构的cfiq指针指向一个cfi_ident结构,chips指针指向一个flchip结构的数组。其中mtd_info、map_info和cfi_private结构用于描述MTD原始设备;因为组成MTD原始设备的NOR型Flash相同,cfi_ident结构用于描述Flash芯片的信息;而flchip结构用于描述每个Flash芯片的专有信息(比如说起始地址)
总的来说,嵌入式系统中一般来说会有一块或多块连续的NOR flash或NAND flash空间(每一个可能是多块相同的芯片来构成)每一个这样的空间被看成一个MTD原始设备(我不知道这个名字谁起的,我也这么用吧)根据一些文章和代码中使用的变量名,我后面称呼它为主分区。你可以按照自己的需要把主分区分成几个区,我的开发板用的分区信息如下:
来自alchemy_flash.c:
static struct mtd_partition alchemy_partitions[] = {
};
如果你增加或者是减少了你的flash空间(通过增加或减少flash芯片)或则你想调整几个分区的大小,你只需要修改这个表就可以了。
如果你还有一块NAND区,那么你可能有如下的分区表(au1550nd.c):
const static struct mtd_partition partition_info[] = {
};
整个alchemy_flash.c就两个函数: alchemy_mtd_init(void)和 alchemy_mtd_cleanup()。
int __init alchemy_mtd_init(void)
{
#ifdef CONFIG_MIPS_MIRAGE_WHY
#endif
}
看看红色的区域,do_map_probe返回了一个mtd_info结构指针。那么表明这个函数在正确找到你的驱动(cfi驱动)后会填好这个表把其中的读写函数等设置到正确的值,具体的实现放到以后分析吧,其中的一个map_info参数,我暂时没有完全读懂,因为我以前不曾研究flash的底层驱动,你需要设置好bankwidth和基地址,和驱动名字,我只能通过一些信息猜测他用来管理这个主分区并给底层驱动使用的,如坏块信息就保存在这里。
最后是调用add_mtd_partitions根据你设置的分区表和主分区的mtd_info来分区。其实如果你不打算给这个主分区分成几个区,你可以直接把这个mtd_info加到mtd_table而不需要mtdpart.c中的处理。这是后话,先沿着这条路分析一下:这个函数跳到了文件mtdpart.c。当你的把主分区分成几个区以后这几个分区的mtd_info和你的主分区是大部分是一样的,只是在size,name等方面不一样。add_mtd_partitions函数太大了点,全部贴出来不合适,我挑几行吧。
static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
{
}
这下清楚了:还是调用主分区的读函数,就是加上了偏移量而已。
add_mtd_partitions的最后调用add_mtd_device(&slave->mtd);把每个分区加进了mtd_table。这个函数在mtdcore.c中,前面提到的如果不分区,你可以直接把主分区做为参数加到mtd_table中。
Mtdcore.c如其名,它叫core是有原因的:它不调用mtd驱动各层次的任何外部函数(除了注册的回调函数)而只是输出函数,它管理着mtd_table。底层通过add_mtd_device和del_mtd_device来添加和删除原始设备(分区)。上层字符设备和块设备部分通过get_mtd_device和put_mtd_device来申请和释放分区等等。
int add_mtd_device(struct mtd_info *mtd)
{
//部分是没有必要的。系统初始化mtd设备时,这个链表也是空的。
}
整个函数比较简单,在mtd_table中选择一个空位置放置你的分区的mtd_info。红色部分是比较难懂一点的:这个mtd_notifiers链表起什么作用?看看谁在这个链表中加了东西。register_mtd_user是唯一向这个链表添加了成员的,谁调了?看一下下面的程序
void register_mtd_user (struct mtd_notifier *new)
{
}
static inline void mtdchar_devfs_init(void)
{
}
int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
{
}
看来这个链表里面通常就只有两个成员。作用是当删除或添加一个mtd分区时告诉建立在其上的字符设备和块设备驱动。干什么?
当创建mtd字符设备时会调用mtdchar_devfs_init,他的notifier是这样的:
static struct mtd_notifier notifier = {
};
static void mtd_notify_add(struct mtd_info* mtd)
{
}
这个devfs_mk_cdev应该就是自动创建devfs的节点吧,是不是就是不用再mknod了?我真的是linux新手,如果有人知道请不吝赐教,我只是从名字上猜测的。
总结一下:
以我的理解是上面的mtd设备驱动架构分析对于移植来说大都不是特别重要,除了那个分区表。但是当你更换了flash芯片型号时,我该如何做?我粗略地看了一下驱动部分,参考了下面这个链接的文章:http://os.yesky.com/lin/233/3386733.shtml 高手进阶 Linux系统下MTD/CFI驱动介绍。
我只是粗粗了解了一下所谓CFI(Common Flash Interface)。是否真的这个驱动就可以解决所有问题了?改天好好trace一下,就从那个do_map_probe开始。
- Linux 2.6.11 MTD驱动情景分析
- Linux 2.6.11 MTD驱动情景分析
- Linux 2.6.11 MTD驱动情景分析
- LINUX 2.6.11 MTD驱动情景分析
- Linux 2.6.11 MTD驱动情景分析[转]
- mtd 情景分析
- ARM-Linux驱动--MTD驱动分析(一)
- ARM-Linux驱动--MTD驱动分析(二)
- ARM-Linux驱动--MTD驱动分析(三)
- ARM-Linux驱动--MTD驱动分析(二)
- ARM-Linux驱动--MTD驱动分析(三)
- ARM-Linux驱动--MTD驱动分析(一)
- ARM-Linux驱动--MTD驱动分析(一)
- ARM-Linux驱动--MTD驱动分析(一)
- ARM-Linux驱动--MTD驱动分析(三)
- Binder驱动情景分析
- mtd子系统驱动分析
- 【驱动】MTD子系统分析
- WordPress官方插件开发文档
- dasdwqwedwqeqweqweqweqwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
- WordPress官方函数参考
- 我的第一个iOS App从开发到上线经历
- WordPress官方中文所有文档
- Linux 2.6.11 MTD驱动情景分析
- 导入文本文件时如何指定字段类型?
- U-Boot的设备管理
- WordPress官方模板标签文档
- 汉诺塔问题,递归
- Failed to create the Java Virtual Machine
- 身份证号码验证方法
- C语言输入以空格隔开字符串存入数组,直到遇到回车停下
- 吸血鬼数字