【转贴】-- MTD介绍

原帖地址:http://blog.csdn.net/bugouyonggan/article/details/9167213

MTD,Memory Technology Device即内存技术设备

字符设备和块设备的区别在于前者只能被顺序读写,后者可以随机访问;同时,两者读写数据的基本单元不同。

字符设备,以字节为基本单位,在Linux中,字符设备实现的比较简单,不需要缓冲区即可直接读写,内核例程和用户态API一一对应,用户层的Read函数直接对应了内核中的Read例程,这种映射关系由字符设备的file_operations维护。

块设备,则以块为单位接受输入和返回输出。对这种设备的读写是按块进行的,其接口相对于字符设备复杂,read、write API没有直接到块设备层,而是直接到文件系统层,然后再由文件系统层发起读写请求。 
同时,由于块设备的IO性能与CPU相比很差,因此,块设备的数据流往往会引入文件系统的Cache机制。

MTD设备既非块设备也不是字符设备,但可以同时提供字符设备和块设备接口来操作它。

MTD总概述

Linux中MTD的所有源码位于/drivers/mtd子目录下,

MTD设备通常可分为四层 
这四层从上到下依次是:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。

一、Flash硬件驱动层 
硬件驱动层负责在init时驱动Flash硬件并建立从具体设备到MTD原始设备映射关系 
tip: 映射关系通常包括 分区信息、I/O映射及特定函数的映射 
drivers/mtd/chips :   CFI/jedec接口通用驱动 
drivers/mtd/nand :   nand通用驱动和部分底层驱动程序 
drivers/mtd/maps :   nor flash映射关系相关函数 
drivers/mtd/devices:   nor flash底层驱动

二、MTD原始设备 
用于描述MTD原始设备的数据结构是mtd_info,它定义了大量的关于MTD的数据和操作函数。 
mtdcore.c :  MTD原始设备接口相关实现 
mtdpart.c :  MTD分区接口相关实现

三、MTD设备层 
基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90)。 
mtdchar.c :  MTD字符设备接口相关实现 
mtdblock.c : MTD块设备接口相关实现

四、设备节点 
通过mknod在/dev子目录下建立MTD块设备节点(主设备号为31)和MTD字符设备节点(主设备号为90) 
通过访问此设备节点即可访问MTD字符设备和块设备 
具体参考:  working-with-mtd-devices

五、文件系统 
内核启动后,通过mount 命令可以将flash中的其余分区作为文件系统挂载到mountpoint上。

MTD数据结构

重要的数据结构: 
1. mtd_info 表示mtd原始设备, 所有mtd_info结构体被存放在mtd_info数组mtd_table中

2. mtd_part   表示MTD分区,其中包含了 mtd_info,每一个分区都是被看成一个MTD 原始设备 
在mtd_table中,mtd_part.mtd_info中的大部分数据都从该分区的主分区mtd_part->master中获得 
tip: master不作为一个mtd原始设备加入mtd_table

各层之间的交互如下图

    
mtd_info的主要数据结构

作用
type mtd类型, 包括MTD_NORFLASH,MTD_NANDFLASH等(See mtd-abi.h)
flags 标志位, MTD_WRITEABLE,MTD_NO_ERASE等(See mtd-abi.h)
size mtd设备的大小
erasesize 主要的擦除大小, 即Flash的块大小 (tip: mtd设备可能有多个erasesize)
writesize 写大小, 对于norFlash是字节,对nandFlash为一页
oobsize 每块oob数据量, eg 16
oobavail  
name 命名
index  
ecclayout nand_ecclayout结构体指针, 表示的是ecc布局,可参考硬件手册的OOB中ecc布局
numeraseregions 可变擦除区域的数目, 通常为1
eraseregions mtd_erase_region_info结构体指针, 可变擦除区域
erase 擦除Flash函数
read/write 读写Flash函数
read_oob/write_oob 带oob读写Flash函数
suspend/resume Power Management functions
priv 私有数据, cfi接口flash指向map_info结构, 或指向自定义flash相关结构体
   

mtd_part的主要数据结构

作用
mtd 分区信息, 大部分由master决定
master 分区的主分区
offset 分区的偏移地址
index 分区号 (3.0后不存在该字段)
list 将mtd_part链成一个链表mtd_partitons
   

mtd_partition的主要数据结构

作用
name  
size  
offset  
mask_flags  
ecclayout  
mtdp  
   

map_info的主要数据结构

作用
name 名称
size 大小
phys 物理地址
bankwidth 总线宽度(in octets)
virt 虚拟地址,通常通过ioremap将物理地址进行映射得到
read/copy_from/write/copy_to 读写函数
map_priv_1/map_priv_2 驱动可用的私有数据
   

nand_chip的主要数据结构

作用
IO_ADDR_R/IO_ADDR_W 读/写8根io线的地址
read_byte/read_word 从芯片读一个字节/字
read_buf/write_buf 读芯片读取内容至缓冲区/将缓冲区内容写入芯片
verify_buf  
select_chip  
block_bad 检查是否坏块
block_markbad 标识坏块
cmd_ctrl 硬件相关控制函数
init_size  
dev_ready  
cmdfunc 命令处理函数
waitfunc  
erase_cmd 擦除命令
scan_bbt 扫描坏块
errstat  
write_page  
options 与具体的NAND 芯片相关的选项, 如NAND_USE_FLASH_BBT等(nand.h)
page_shift  
   
ecclayout nand_ecclayout类型结构体, ECC布局信息
ecc nand_ecc_ctrl类型结构体, ECC控制结构
   
   
   

nand_ecclayout的主要数据结构

作用
eccbytes ecc的字节数(For 512B-per-page, eccbytes is 3)
eccpos ecc数据在oob中的位置
oobavail oob中可用的字节数, MTD 会根据其它三个变量自动计算得到
oobfree nand_oobfree类型结构体, 显示定义空闲的oob 字节
   

MTD相关层实现

MTD设备层

mtd字符设备接口: 
mtdchar.c 实现了字符设备接口,通过它,用户可以直接操作Flash 设备。 
Ø 通过read()、write()系统调用可以读写Flash。 
Ø 通过一系列IOCTL 命令可以获取Flash 设备信息、擦除Flash、读写NAND 的OOB、获取OOB layout 及检查NAND 坏块等(MEMGETINFO、MEMERASE、MEMREADOOB、MEMWRITEOOB、MEMGETBADBLOCK IOCRL) 
tip: mtd_read和mtd_write直接直接调用mtd_info的read 函数,因此,字符设备接口跳过patition这一层

mtd块设备接口: 
主要原理是将Flash的erase block 中的数据在内存中建立映射,然后对其进行修改,最后擦除Flash 上的block,将内存中的映射块写入Flash 块。整个过程被称为read/modify/erase/rewrite 周期。 
但是,这样做是不安全的,当下列操作序列发生时,read/modify/erase/poweroff,就会丢失这个block 块的数据。 
块设备模拟驱动按照block 号和偏移量来定位文件,因此在Flash 上除了文件数据,基本没有额外的控制数据。

MTD原始设备层

MTD硬件驱动层

1. NOR Flash驱动结构

Linux系统实现了针对cfi,jedec等接口的通用NOR Flash驱动 
在上述接口驱动基础上,芯片级驱动较简单 
     定义具体内存映射结构体map_info,然后通过接口类型后调用do_map_probe()  
以h720x-flash.c为例(位于drivers/mtd/maps) 
- 定义map_info结构体, 初始化成员name, size, phys, bankwidth 
- 通过ioremap映射成员virt(虚拟内存地址) 
- 通过函数simple_map_init初始化map_info成员函数read,write,copy_from,copy_to 
- 调用do_map_probe进行cfi接口探测, 返回mtd_info结构体 
- 通过parse_mtd_partitions, add_mtd_partitions注册mtd原始设备

2. NAND Flash驱动结构

Linux实现了通用NAND驱动(drivers/mtd/nand/nand_base.c) 
tip: For more, check 内核中的NAND代码布局  
芯片级驱动需要实现nand_chip结构体 
MTD使用nand_chip来表示一个NAND FLASH芯片, 该结构体包含了关于Nand Flash的地址信息,读写方法,ECC模式,硬件控制等一系列底层机制。 
Ø NAND芯片级初始化 
主要有以下几个步骤: 
- 分配nand_chip内存,根据目标板及NAND控制器初始化nand_chip中成员函数(若未初始化则使用nand_base.c中的默认函数),将mtd_info中的priv指向nand_chip(或板相关私有结构),设置ecc模式及处理函数 
- 以mtd_info为参数调用nand_scan()探测NAND FLash。 
   nand_scan()会读取nand芯片ID,并根据mtd->priv即nand_chip中成员初始化mtd_info 
- 若有分区,则以mtd_info和mtd_partition为参数调用add_mtd_partitions()添加分区信息 
-

Ø MTD对NAND芯片的读写 
主要分三部分: 
A、struct mtd_info中的读写函数,如read,write_oob等,这是MTD原始设备层与FLASH硬件层之间的接口; 
B、struct nand_ecc_ctrl中的读写函数,如read_page_raw,write_page等,主要用来做一些与ecc有关的操作; 
C、struct nand_chip中的读写函数,如read_buf,cmdfunc等,与具体的NAND controller相关,就是这部分函数与硬件交互,通常需要我们自己来实现。 
tip: nand_chip中的读写函数虽然与具体的NAND controller相关,但是MTD也为我们提供了默认的读写函数,如果NAND controller比较通用(使用PIO模式),那么对NAND芯片的读写与MTD提供的这些函数一致,就不必自己实现这些函数。

上面三部分读写函数相互配合完成对NAND芯片的读写 
首先,MTD上层需要读写NAND芯片时,会调用struct mtd_info中的读写函数,接着struct mtd_info中的读写函数就会调用struct nand_chip或struct nand_ecc_ctrl中的读写函数,最后,若调用的是struct nand_ecc_ctrl中的读写函数,那么它又会接着调用struct nand_chip中的读写函数。 
eg:  以读为例 
MTD上层会调用struct mtd_info中的读page函数,即nand_read函数。 
接着nand_read函数会调用struct nand_chip中cmdfunc函数,这个cmdfunc函数与具体的NAND controller相关,它的作用是使NAND controller向NAND 芯片发出读命令,NAND芯片收到命令后,就会做好准备等待NAND controller下一步的读取。 
接着nand_read函数又会调用struct nand_ecc_ctrl中的read_page函数,而read_page函数又会调用struct nand_chip中read_buf函数,从而真正把NAND芯片中的数据读取到buffer中(所以这个read_buf的意思其实应该是read into buffer,另外,这个buffer是struct mtd_info中的nand_read函数传下来的)。 
read_buf函数返回后,read_page函数就会对buffer中的数据做一些处理,比如校验ecc,以及若数据有错,就根据ecc对数据修正之类的,最后read_page函数返回到nand_read函数中。 
对NAND芯片的其它操作,如写,擦除等,都与读操作类似

http://www.cnblogs.com/hzl6255/archive/2012/12/18/2824043.html

MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱 动更加简单,为此它在硬件和上层之间提供了一个抽象的接口。MTD的所有源代码在/drivers/mtd子目录下。我将CFI接口的MTD设备分为四层 (从设备节点直到底层硬件驱动),这四层从上到下依次是:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。

  一、Flash硬件驱动层:硬件驱动层负责在init时驱动Flash硬件,Linux MTD设备的NOR Flash芯片驱动遵循CFI接口标准,其驱动程序位于drivers/mtd/chips子目录下。NAND型Flash的驱动程 序则位于/drivers/mtd/nand子目录下。

  二、MTD原始设备:原始设备层有两部分组成,一部分是MTD原始设备的通用代码,另一部分是各个特定的Flash的数据,例如分区。 用于描述MTD原始设备的数据结构是mtd_info,这其中定义了大量的关于MTD的数据和操作函数。mtd_table(mtdcore.c)则是所 有MTD原始设备的列表,mtd_part(mtd_part.c)是用于表示MTD原始设备分区的结构,其中包含了mtd_info,因为每一个分区都 是被看成一个MTD原始设备加在mtd_table中的,mtd_part.mtd_info中的大部分数据都从该分区的主分区 mtd_part->master中获得。 在drivers/mtd/maps/子目录下存放的是特定的flash的数据,每一个文件都描述了一块板子上的flash。其中调用 add_mtd_device()、del_mtd_device()建立/删除mtd_info结构并将其加入/删除mtd_table(或者调用 add_mtd_partition()、del_mtd_partition()(mtdpart.c)建立/删除mtd_part结构并将 mtd_part.mtd_info加入/删除mtd_table 中)。

  三、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上。

http://www.cnblogs.com/hoys/archive/2012/05/30/2526230.html

时间: 2024-10-11 04:24:07

【转贴】-- MTD介绍的相关文章

MTD技术介绍

MTD(Memory Technology device)是用于访问memory设备(ROM.Flash)的Linux子系统,在Linux中引入这一层的主要目的是为了更加简单的添加新的Memory存储设备,它提供一层抽象的接口. 从上图可以看出,mtd原始设备层可以让底层Flash以字符设备呈现为应用层,表现形式为/dev/mtdN,也可以以块设备呈现给应用层,表现形式为/dev/mtdblockN.在应用层面上,对于字符形式的Flash设备,可以通过mtd-utils工具来控制.对于块设备形式

第3阶段——内核启动分析之挂载根文件系统和mtd分区介绍(6)

内核启动并初始化后,最终目的是像Windows一样能启动应用程序 在windows中每个应用程序都存在C盘.D盘等 而linux中每个应用程序是存放在根文件系统里面 那么挂载根文件系统在哪里,怎么实现最终目的运行应用程序? 1.进入stext函数启动内核 2.进入strat_kernel(): ... setup_arch(&command_line);           //解析uboot传入的启动参数 setup_command_line(command_line);    //解析ubo

uboot的介绍

uboot的介绍 1.1 uboot的介绍Uboot是德国DENX小组的开发用于多种嵌入式CPU的bootloader程序, UBoot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统.UBoot除了支持PowerPC系列的处理器外,还能支持MIPS. x86.ARM.NIOS.XScale等诸多常用系列的处理器.1.2 uboot的体系结构目录树|--board|--common|--cpu|

linux设备驱动程序该添加哪些头文件以及驱动常用头文件介绍(转)

原文链接:http://blog.chinaunix.net/uid-22609852-id-3506475.html 驱动常用头文件介绍 #include <linux/***.h> 是在linux-2.6.29/include/linux下面寻找源文件.#include <asm/***.h> 是在linux-2.6.29/arch/arm/include/asm下面寻找源文件.#include <mach/***.h> 是在linux-2.6.29/arch/ar

uboot环境变量与内核MTD分区关系

uboot 与系统内核中MTD分区的关系: 分区只是内核的概念,就是说A-B地址放内核,C-D地址放文件系统,(也就是规定哪个地址区间放内核或者文件系统)等等. 1:在内核MTD中可以定义分区A~B,C~D......并予以绝对的地址赋值给每个分区.我们可以来看看在内核中是怎样来对MTD进行分区的:arch/arm/plat-s3c24xx/common-smdk.c static struct mtd_partition smdk_default_nand_part[] = { [0] = {

u-boot中分区和内核MTD分区关系

一.u-boot中环境变量与uImage中MTD的分区关系 分区只是内核的概念,就是说A-B地址放内核,C-D地址放文件系统,(也就是规定哪个地址区间放内核或者文件系统)等等. 一般我们只需要分3-4个区,第一个为boot区,一个为boot参数区(传递给内核的参数),一个为内核区,一个为文件系统区.(但是有的内核就会有很多分区,比如内核参数会有两个,还有会Logo的地址) 而对于bootloader中只要能将内核下载到A~B区的A地址开始处就可以,C~D区的C起始地址下载文件系统…….这些起始地

btrfs的介绍与使用

源文献:http://www.ibm.com/developerworks/cn/linux/l-cn-btrfs/index.html#ibm-pcon 简单看了一下这篇文章,对其中一些机制的实现还不是很明白,还需要研究,在此做个记号. Btrfs 简介 文件系统似乎是内核中比较稳定的部分,多年来,人们一直使用 ext2/3,ext 文件系统以其卓越的稳定性成为了事实上的 Linux 标准文件系统.近年来 ext2/3 暴露出了一些扩展性问题,于是便催生了 ext4 .在 2008 年发布的

KVM 介绍(3):I/O 全虚拟化和准虚拟化 [KVM I/O QEMU Full-Virtualizaiton Para-virtualization]

学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分配和 SR-IOV (5)libvirt 介绍 (6)Nova 通过 libvirt 管理 QEMU/KVM 虚机 (7)快照 (snapshot) (8)迁移 (migration) 在 QEMU/KVM 中,客户机可以使用的设备大致可分为三类: 1. 模拟设备:完全由 QEMU 纯软件模拟的设备

利用mtd工具实现嵌入式设备在线升级

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 主要思路是:通过web post方式将升级文件交给CGI程序处理,然后通过mtd工具实现设备在线升级. 1.页面部分 <form target="_blank" enctype="multipart/form-data" method="POST" action="./update.cgi"> <p>选择升级文件: <inpu