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为). ...
随机推荐
- hdu4003/蓝桥杯 金属采集
思路: 树形dp + 分组背包dp. 参考https://www.cnblogs.com/kuangbin/archive/2012/08/29/2661928.html 实现: #include & ...
- Android Studio Terminal 不是内部或外部命令,也不是可运行程序或批处理文件
1.Android Studio Terminal 命令行无效的问题 在Android Studio中自带了命令行终端Terminal,但是我们在输入命令时经常会发现:“XXX”不是内部或外部命令,也 ...
- Linux常用终端快捷键
UNIX程序员对键盘以及快捷键的设置都遵循一个标准:"手移动最少的距离,作更多的操作." 所有的类UNIX的终端上都有一些快捷键Ctrl+n = 下,Ctrl+b = 左,Ctrl ...
- OCP 11g 第四章练习
练习 4-1 配置Oracle Net 在本练习中, 将使用图形化工具和命令行工具来建立一个完整的Oracle Net 环境. 由此, 读者可看出在Windows 和 Linux 系统中的区别. 1. ...
- 浅析HashSet add() 方法存储自定义类型对象的过程
一.自定义一个Student类 package date0504; public class Student { private String id; Student(String id){ this ...
- @click.native 会触发原生 click事件 vue
@click.native 会触发原生 click事件 vue
- windows10家庭版 远程桌面报错
windows10家庭版 远程桌面报错“要求的函数不受支持 ...”,Windows没有编辑组策略选项(gpedit.msc),所以无法按照微软提供的方法来修改组策略.所以我们需要修改注册表的方法来修 ...
- hdu 6441 Find Integer(费马大定理+勾股数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6441(本题来源于2018年中国大学生程序设计竞赛网络选拔赛) 题意:输入n和a,求满足等式a^n+b^ ...
- OVOO
题目描述: $zhx$有一个棵$n$个点的树,每条边有个权值. 定义一个连通块为一个点集与使这些点连通的所有边(这些点必须连通). 定义一个连通块的权值为这个连通块的边权和(如果一个连通块只包含一个点 ...
- InnoDB 事务隔离级别
InnoDB是一种平衡高可靠性和高性能的通用存储引擎.在MySQL数据库5.5.8版本开始,InnoDB是默认的MySQL存储引擎. InnoDB的主要优势 - 其DML操作遵循ACID,具有提交,回 ...