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的更多相关文章

  1. Linux MTD子系统 _从模型分析到Flash驱动模板

    MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框架中的设备驱动层,可以说,MTD就是针对Flash设备设计的标准化 ...

  2. Understanding Memory Technology Devices in Embedded Linux

    转: NAND Chip Drivers NAND technology users such as USB pen drives, DOMs, Compact Flash memory, and S ...

  3. 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 ...

  4. Linux MTD系统剖析【转】

    转自:http://blog.csdn.net/lwj103862095/article/details/21545791 版权声明:本文为博主原创文章,未经博主允许不得转载. MTD,Memory ...

  5. linux MTD系统解析(转)

    MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口.MTD将文件系统与底层FLASH存储 ...

  6. Linux MTD系统剖析

    MTD,Memory Technology Device即内存技术设备,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口.MTD将文件系统与底层FLASH存储 ...

  7. Linux MTD 子系统

    一.MTD子系统概述 MTD(Memory Technology Device, 内存技术设备)是用于访问memory 设备 (ROM.FLASH)的Linux子系统. 主要目的是为了使新的memor ...

  8. linux输入子系统(input subsystem)之evdev.c事件处理过程

    1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input ...

  9. Linux high memory 学习总结

    在free命令中有个参数l,它表示 show detailed low and high memory statistics.其实最先是对High Memory总是为零有些不解(Linux是64为). ...

随机推荐

  1. canvas绘制基础

    初始接口 <body> <canvas id=“canvas”></canvas> <script> var canvas = document.get ...

  2. obj.style 和currentstyle 等区别

    版权声明:本文为博主原创文章,未经博主允许不得转载. 获取样式  obj.style   和currentstyle  等区别   obj.style只能获得内嵌样式(inline Style)就是写 ...

  3. Elasticsearch插件清单

    1.API插件:主要对Elasticsearch添加的API特性或者功能,通常用于搜索或者映射 2. 报警插件: 当Elasticsearch的索引指标超过阀值时就会触发 3. 分词插件:ik是比较好 ...

  4. 【人工智能系列】python的Quepy库的学习

    第一篇 了解 什么是Quepy quepy是一个Python框架改造自然语言问题在数据库查询语言查询.它可以很容易地定制不同类型的问题,在自然语言和数据库查询.因此,用很少的代码,你可以建立自己的系统 ...

  5. itop安装中使用nginx安装后不能出现enter itop的问题

    安装中没有出现enter itop,  如下的网络请求给了我们原因 原来使用的是域名请求资源文件,而该域名并不能指向我的服务器,所以安装中资源文件请求不成功,查看了我的nginx配置,如下 [ro ...

  6. (转)使用Spring注解方式管理事务与传播行为详解

    http://blog.csdn.net/yerenyuan_pku/article/details/52885041 使用Spring注解方式管理事务 前面讲解了怎么使用@Transactional ...

  7. (转)配置Spring管理的bean的作用域

    http://blog.csdn.net/yerenyuan_pku/article/details/52833477 Spring管理的bean的作用域有: singleton 在每个Spring ...

  8. CAD交互绘制圆弧(网页版)

    在CAD设计时,需要绘制圆弧,用户可以在图面点圆弧起点,圆弧上的一点和圆弧的终点,这样就绘制出圆弧. 主要用到函数说明: _DMxDrawX::DrawArc2 由圆弧上的三点绘制一个圆弧.详细说明如 ...

  9. 线性判别分析(LDA)

    降维的作用: 高维数据特征个数多,特征样本多,维度也很大,计算量就会很大,调参和最后评估任务时,计算量非常大,导致效率低. 高位数据特征特别多,有的特征很重要,有的特征不重要,可以通过降维保留最好.最 ...

  10. Vue之数据绑定

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...