Linux MTD (Memory Technology Device) subsystem analysis -For Atheros char device
Linux MTD (Memory Technology Device) subsystem analysis
For Atheros char device
读了Linux MTD 源代码分析 对这部分有了整体的认识,结合现有代码,分析一下Atheros的MTD是如何使用的。
Linux kernel: 2.6.31.
Atheros platform: QCA9890???
参考Linux MTD 源代码分析,这里把MTD分为4层,从上到下依次是:字符设备节点、字符设备、MTD 核心、FLASH 硬件驱动。
字符设备节点:/dev/mtd0 /dev/mtd1 等节点,可以通过fopen()等直接使用。这些节点是MTD子系统创建的,用户通过访问这些节点操作MTD。
字符设备:MTD子系统把MTD封装为字符设备。
MTD核心:管理所有的MTD设备,提供get/add/del MTD功能;同时,一个MTD设备可能逻辑上会被划分为多个区,每个区被当成一个MTD设备,所以还提供了通过分区信息批量加入、删除MTD设备的功能。为了从kernel启动参数获取分区信息,MTD核心提供了分析启动参数中分区信息的功能。
FLASH硬件驱动:提供FLASH的read/write/erase等功能。因为Atheros的分区信息是在kernel的启动参数里面取得,所以这里还有分析启动参数分区信息的功能;根据分区信息把MTD设备加到MTD核心中。
系统启动时,MTD核心层可以直接编译到kernel中,FLASH驱动层在系统启动时解析分区信息,把MTD加入到MTD核心层,MTD核心层完成设备节点的创建,MTD字符设备注册MTD字符设备信息,这样访问设备节点的时候就可以找到具体的执行函数。

图1 Atheros MTD Subsystem Architecture
图1显示了各层的主要信息。
MTD设备的使用是通过访问设备节点/dev/mtd0 /dev/mtd1,一般用法是
|
File *f = fopen(“/dev/mtd0”, “r”);
fread(void *ptr, size_t size, size_t nmemb, FILE *stream); fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); |
/dev/mtd0 等设备是由MTD核心创建的,由add_mtd_device()->device_register()创建。fread/fwrite是由MTD字符设备层实现具体的读写,至于是如何找到MTD字符设备层的函数的,以及设备节点如何和这些函数关联的,需要看下fread以及Linux的驱动模型(device_register/register_chrdev),以后再总结吧。
MTD字符设备层是通过register_chrdev()来实现的,需要提供struct file_operations中的函数,这些函数完成对指定MTD的read/write/erase等。register_chrdev()之后,当用fread等访问MTD的时候,就会找到这里注册的函数。
|
static const struct file_operations mtd_fops = { .owner = THIS_MODULE, .llseek = mtd_lseek, .read = mtd_read, .write = mtd_write, .ioctl = mtd_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = mtd_compat_ioctl, #endif .open = mtd_open, .release = mtd_close, .mmap = mtd_mmap, #ifndef CONFIG_MMU .get_unmapped_area = mtd_get_unmapped_area, #endif };
static int __init init_mtdchar(void) { int status;
status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); if (status < 0) { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", MTD_CHAR_MAJOR); }
return status; } |
具体看下open/read/close是如何使用MTD的,get/put_mtd_device有MTD核心层提供,下面会具体看到。mtd_open 通过inode取得设备号,进一步通过get_mtd_device取得MTD的struct mtd_info信息,也就获得了具体操作MTD的函数;以后的mtd_read/write等函数就可以直接使用mtd->read/mtd->write完成具体的操作。
|
static int mtd_open(struct inode *inode, struct file *file) { int minor = iminor(inode); int devnum = minor >> 1; … mtd = get_mtd_device(NULL, devnum); …. mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); mfi->mtd = mtd; file->private_data = mfi; out: unlock_kernel(); return ret; } /* mtd_open */
static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) { struct mtd_file_info *mfi = file->private_data; struct mtd_info *mtd = mfi->mtd; … while (count) { switch (mfi->mode) { default: ret = mtd->read(mtd, *ppos, len, &retlen, kbuf); } } … return total_retlen; } /* mtd_read */
static int mtd_close(struct inode *inode, struct file *file) { struct mtd_file_info *mfi = file->private_data; struct mtd_info *mtd = mfi->mtd; put_mtd_device(mtd); file->private_data = NULL; kfree(mfi); return 0; } /* mtd_close */ |
MTD核心层提供的功能可以分为两部分:面向上层用户的API和面向底层用户的API。上层用户主要是指MTD字符设备层,字符设备层可以通过get_mtd_device获得MTD的struct mtd_info 信息,然后通过mtd->read、mtd->write等操作MTD。使用方法可以参考字符设备层中函数的实现。下层用户是FLASH驱动层,FLASH驱动层通过parse_mtd_partitions获得kernel启动参数中的分区信息,然后通过add_mtd_partitions把各个分区当做单独的MTD设备加入到MTD核心层;为了分析kernel启动参数,需要注册parser函数,通过register_mtd_parser实现,这个函数的注册可以由FLASH驱动层完成,也可以编译到kernel中(make menuconfig->Device drivers->MTD support->Command line partition table parsing)。
至于注册的parser是如何得到kernel启动参数的,大概的过程是,bootloader通过bootargs的mtdparts传入分区信息,这个分区信息会被当成kernel的启动参数;kernel通过__setup("mtdparts=", mtdpart_setup) 注册函数mtdpart_setup,mtdpart_setup保存分区信息,parser解析保存的信息,参考(cmdlinepart.c)。
MTD核心层的实现原理是:
每个MTD用一个struct mtd_info描述,所有的mtd_info保存在struct mtd_info *mtd_table[]中,get/add/del_mtd_device都是操作mtd_table。
一个MTD FLASH可以逻辑上分为多个区,每个区当成一个MTD,分区信息用struct mtd_partition描述,通过分区信息加入MTD时,需要知道master MTD的信息,每个分区的信息多数来源于master MTD,master MTD不会加入MTD核心层,只有里面的各个分区会加入核心层,当成单独的MTD。
MTD核心层还有notifier的功能,保存在struct mtd_notifier,所有的notifier保存在一个链表中。
具体可以参考Linux MTD 源代码分析。
FLASH驱动层提供mtd_info中read/write等的具体实现,如果有逻辑分区的话,这个mtd_info就是master MTD。然后调用parser_mtd_partitions 和add_mtd_partitions把逻辑分区加入到MTD核心层。
Linux MTD (Memory Technology Device) subsystem analysis -For Atheros char device的更多相关文章
- Linux MTD子系统 _从模型分析到Flash驱动模板
MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框架中的设备驱动层,可以说,MTD就是针对Flash设备设计的标准化 ...
- Understanding Memory Technology Devices in Embedded Linux
转: NAND Chip Drivers NAND technology users such as USB pen drives, DOMs, Compact Flash memory, and S ...
- Is an MTD device a block device or a char device?
转:http://www.linux-mtd.infradead.org/faq/general.html#L_mtd_what Note, you can find Ukranian transla ...
- Linux MTD系统剖析【转】
转自:http://blog.csdn.net/lwj103862095/article/details/21545791 版权声明:本文为博主原创文章,未经博主允许不得转载. MTD,Memory ...
- linux MTD系统解析(转)
MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口.MTD将文件系统与底层FLASH存储 ...
- Linux MTD系统剖析
MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口.MTD将文件系统与底层FLASH存储 ...
- Linux MTD 子系统
一.MTD子系统概述 MTD(Memory Technology Device, 内存技术设备)是用于访问memory 设备 (ROM.FLASH)的Linux子系统. 主要目的是为了使新的memor ...
- linux输入子系统(input subsystem)之evdev.c事件处理过程
1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input ...
- Linux high memory 学习总结
在free命令中有个参数l,它表示 show detailed low and high memory statistics.其实最先是对High Memory总是为零有些不解(Linux是64为). ...
随机推荐
- Hibernate中的inverse和cascade属性
Hibernate中的inverse和cascade属性 inverse的值有两种,"true"和"false".inverse="false&quo ...
- java实现批量修改指定文件夹下所有后缀名的文件为另外后缀名的代码
java实现批量修改指定文件夹下所有后缀名的文件为另外后缀名的代码 作者:Vashon package com.ywx.batchrename; import java.io.File; import ...
- Web开发者不容错过的10个HTML5工具
HTML5已经成为当今世界的一个必然组成部分.由于World Wide Web万维网是使用超文本标记语言来架构和呈现的,于是HTML5成为了最流行的编程语言之一.随着网络的不断扩张,Web开发人员非常 ...
- 【整理】iview Tree数据格式问题,无限递归树处理数据
iview Tree数据格式问题,无限递归树处理数据 https://juejin.im/post/5b51a8a4e51d455d6825be20
- P2257 YY的GCD (莫比乌斯反演)
题意:求\[\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j) = prim]\] 题解:那就开始化式子吧!! \[f(d) = \sum_{i=1}^{n}\sum_{j=1 ...
- margin塌陷和margin合并问题及解决方案
margin塌陷 先举个例子 <style> body{ background-color:#000; } .wrapper{ width:200px; height:200px; bac ...
- composer 设置代理
在命令行终端中输入以下内容: export https_proxy='192.168.1.133:1080' export http_proxy='192.168.1.133:1080' 此前提是你已 ...
- [HIHO] 1048 铺地板
历经千辛万苦,小Hi和小Ho终于到达了举办美食节的城市!虽然人山人海,但小Hi和小Ho仍然抑制不住兴奋之情,他们放下行李便投入到了美食节的活动当中.美食节的各个摊位上各自有着非常多的有意思的小游戏,其 ...
- bash实现自动补全
yum install -y bash-completion source /usr/share/bash-completion/bash_completion 执行后yum拥有选项自动补全功能 对于 ...
- ps----像素与分辨率
1.为了用于印刷,所以调整文档尺寸也很重要. 2.像素的多少决定了文件的大小,像素越多图像越清晰越逼真. 3.文档的尺寸改变需要结合分辨率. 4.像素固定的情况下修改分辨率高度宽度也会变化. 5.画面 ...