<div>
<span style="">嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤。一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便。如有错误之处,谢请指正。</span>
</div>
<ul>
<li>
<span style="">共享资源,欢迎转载:</span>
<a href="http://hbhuanggang.cublog.cn/"><span style="">http://hbhuanggang.cublog.cn</span>
</a>
</li>
</ul>
<p><strong><span style="">一、Linux中Flash硬件知识</span>
</strong>
</p>
<ol>
<li>
<span style="font-size: x-small;">Flash用途和分类:<br><br>
在嵌入式系统开发设计中,存储模块是不可缺少的重要部分,而
Flash是目前市场上主要的非易失闪存技术,他主要分为:Nor Flash和Nand Flash两种。那么他们有什么区别呢?简单的讲:Nor
Flash容量小,价格高,写速度慢但随机读速度快,所以较适合存储少量的程序代码,比如u-boot启动代码;而Nand
Flash则容量大,价格低,写速度快但读速度慢,所以他相当于PC上的硬盘用于存储大量的数据。Nor Flash与Nand
Flash更详细区别如下表:<br><img src="http://blog.chinaunix.net/photo/101649_100629103038.png" alt=""><br></span>
</li>
<li>
<span style="font-size: x-small;">Flash在硬件设计中的应用:<br><br>
以Mini2440开发板为例:该开发板上带有一块2M的Nor Flash和一块64M的Nand Flash。下面先看看他们是怎样被应用于嵌入式Linux的。Nor Flash和Nand Flash电路原理图分别如下:(由mini2440提供)<br><img src="http://blog.chinaunix.net/photo/101649_100629104856.png" alt=""><br><br>
从
原理图上可以看到,Nor Flash内部提供的是有类似于DRam之类的地址总线,可以直接与CPU相连,CPU可以直接通过地址总线对Nor
Flash进行访问;而Nand Flash没有这类的总线,其内部只提供IO接口,因此只能通过IO接口发送命令和地址,对Nand
Flash内部数据进行访问。这可以说是二者最大的区别了,也说明了二者读写速度不同的所在。因此,各有各的优点,Nor Flash访问快,Nand
Flash简化了电路。注意:电路原理图中字母上面有一横杠的表示该引脚是低电平有效,没有的是默认的高电平。</span>
</li>
</ol>
<div>
<strong><span style="">二、Linux中Flash软件知识</span>
</strong>
</div>
<ol>
<li>
<span style="">Linux MTD子系统:<br><br>
在Linux系统中,提供了MTD(内存技术设备)子系统来建立Flash针对Linux的统一、抽象的接口。MTD子系统将上层文件系统与底层
Flash硬件进行了隔离,使Flash驱动开发者无需再关心Flash作为字符设备或者块设备与Linux内核的接口。MTD将Linux系统
Flash设备驱动及接口分成了4个层次,如图所示,从上往下分别为:设备节点、MTD设备层、MTD原始设备层和Flash硬件驱动层。<br><img src="http://blog.chinaunix.net/photo/101649_100629160140.png" alt=""><br><br><strong>设备节点:</strong>
用户在/dev目录下使用mknod命令建立MTD字符设备节点(主设备号为90),或者MTD块设备节点(主设备号为31),使用该设备节点即可访问MTD设备。<br><br><strong>MTD设备层:</strong>
基于MTD原始设备层,系统将MTD设备可以定义为MTD字符设备(在/mtd/mtdchar.c中实现)和MTD块设备(在/mtd/mtdblock.c中实现)。<br><br><strong>MTD原始设备层:</strong>
MTD原始设备层由两个部分组成,分别是MTD原始设备的通用代码和各个特定的Flash的数据,如分区信息。<br><br><strong>Flash硬件驱动层:</strong>
Flash硬件驱动层负责对Flash硬件的读、写和擦除操作。MTD设备的Nor Flash芯片驱动一般位于drivers/mtd/chips/子目录下,Nand Flash芯片的驱动则位于drivers/mtd/nand/子目录下。<br><br>
综
合上述我们可知,MTD子系统已经对Flash设备对于上层的应用进行了封装,我们在写硬件驱动的时候直接调用MTD原始设备层提供的接口函数做相应的操
作即可。那么,对于MTD设备层,MTD原始设备层提供了哪些接口呢?对于Flash硬件驱动层,MTD原始设备层又提供了哪些接口呢?下面开始了解。<br><br></span>
</li>
<li>
<span style="font-size: x-small;">MTD子系统接口:<br><br>
在MTD子系统中,MTD设备层、MTD原始设备层和Flash硬件驱动层之间的接口关系如下图所示:<br><img src="http://blog.chinaunix.net/photo/101649_100701145306.png" alt=""><br>
从上图可知,MTD设备层是通过原始设备层提供的接口来注册MTD字符设备或MTD块设备的,同样,驱动工程师要编写的Flash硬件驱动也是通过原始设备层提供的接口来添加MTD设备和MTD分区的,分别如下:
<table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #ff9933;">//使用这两个接口函数进行添加和删除MTD设备</span>
<br><span style="color: #0000ff;">int</span>
add_mtd_device<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
del_mtd_device<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
</span>
</span>
</code>
</p>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"></span>
</span>
</code>
</p>
<code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000cc;">
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #ff9933;">//使用这两个接口函数进行添加和删除MTD分区</span>
<br><span style="color: #0000ff;">int</span>
add_mtd_partitions<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*<span style="color: #000000;">master</span>
, struct <span style="color: #000000;">mtd_partition</span>
*<span style="color: #000000;">parts</span>
, int <span style="color: #000000;">nbparts</span>
</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
del_mtd_partitions<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*<span style="color: #000000;">master</span>
</span>
<span style="color: #0000cc;">)</span>
</span>
</span>
</code>
</p>
</span>
</span>
</span>
</code>
</td>
</tr></tbody></table>
<br><br>
在
MTD中,一个MTD原始设备用mtd_info结构体来表示,定义在include/linux/mtd/mtd.h中;一个MTD原始设备分区用
mtd_part结构体来表示,定义在drivers/mtd/mtdpart.c中。其中每个分区也被认为是一个mtd_info,比如:有一个MTD
原始设备,上面有3个分区,那么将共有3个mtd_info,而这3个mtd_info的指针将被存放在mtd_table的数组中进行管理,定义在
drivers/mtd/mtdcore.h中,如下所示:
<table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000ff;">extern</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd_table<span style="color: #0000cc;">[</span>
MAX_MTD_DEVICES<span style="color: #0000cc;">]</span>
<span style="color: #0000cc;">;<span style="color: #ff9933;">//最多有MAX_MTD_DEVICES(默认定义为32)个设备</span>
</span>
</span>
</span>
</code>
</p>
</td>
</tr></tbody></table>
<br><br></span>
</li>
<li>
<span style="font-size: x-small;">MTD子系统中重要的一些数据结构:<br><table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000ff;">struct</span>
mtd_info <br><span style="color: #0000cc;">{</span>
<br><span style="color: #ff9900;">//硬件设备的类型,如:MTD_RAM,MTD_ROM,MTD_NORFlash,MTD_NANDFlash,MTD_PEROM等</span>
<br>
u_char type<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//设备支持的选项,如:MTD_ERASEABLE(可擦除),MTD_WRITEB_WRITEALBE(可编程),</span>
<br><span style="color: #ff9900;">//MTD_XIP(可片内执行),MTD_OOB(NAND额外数据),MTD_ECC(支持自动ECC)等</span>
<br><span style="color: #ff0000;">uint32_t</span>
flags<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff0000;">uint64_t</span>
size<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//MTD设备的大小</span>
<br><span style="color: #ff0000;">uint32_t</span>
erasesize<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//主要的擦除块大小(注意:同一个MTD设备可能有几种不同的erasesize)</span>
<br><span style="color: #ff0000;">uint32_t</span>
writesize<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//编程块大小</span>
<br><span style="color: #ff0000;">uint32_t</span>
oobsize<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//OOB数据大小</span>
<br><span style="color: #ff0000;">uint32_t</span>
oobavail<span style="color: #0000cc;">;</span>
<br><br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">int</span>
erasesize_shift<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">int</span>
writesize_shift<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">int</span>
erasesize_mask<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">int</span>
writesize_mask<span style="color: #0000cc;">;</span>
<br><br><span style="color: #0000ff;">const</span>
<span style="color: #0000ff;">char</span>
<span style="color: #0000cc;">*</span>
name<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
index<span style="color: #0000cc;">;</span>
<br><br><span style="color: #0000ff;">struct</span>
nand_ecclayout <span style="color: #0000cc;">*</span>
ecclayout<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//ECC布局结构</span>
<br><br><span style="color: #0000ff;">int</span>
numeraseregions<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//擦除区域的个数,通常为1</span>
<br><span style="color: #0000ff;">struct</span>
mtd_erase_region_info <span style="color: #0000cc;">*</span>
eraseregions<span style="color: #0000cc;">;</span>
</span>
<span style="font-family: NSimsun;"><span style="color: #ff9900;">//擦除区域的指针<br></span>
<br><span style="color: #ff9900;">//此方法将一个erase_info结构放入擦除队列中</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
erase<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
erase_info <span style="color: #0000cc;">*</span>
instr<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//point和unpoint方法分别用于允许和禁止芯片内执行(eXecute-In-Place,简称XIP),如果unpoint为NULL,则表示禁止XIP</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
point<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">*</span>
<span style="color: #0000cc;">*</span>
virt<span style="color: #0000cc;">,</span>
resource_size_t <span style="color: #0000cc;">*</span>
phys<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
unpoint<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//如果不为NULL,则表示允许无MMU单元的虚拟地址映射</span>
<br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
get_unmapped_area<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
offset<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
flags<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">struct</span>
backing_dev_info <span style="color: #0000cc;">*</span>
backing_dev_info<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//read和write分别用于MTD设备的读和写</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
<span style="color: #ff0000;">read</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
<span style="color: #ff0000;">write</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t to<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">const</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
panic_write<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t to<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">const</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//read_oob和write_oob分别用于读写MTD设备的OOB数据</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
read_oob<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
mtd_oob_ops <span style="color: #0000cc;">*</span>
ops<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
write_oob<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t to<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
mtd_oob_ops <span style="color: #0000cc;">*</span>
ops<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//一下几个方法是用于实现访问一些受保护的寄存器(一般这只是出现在某些特定的Flash设备上)</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
get_fact_prot_info<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
otp_info <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
read_fact_prot_reg<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
get_user_prot_info<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
otp_info <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
read_user_prot_reg<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
write_user_prot_reg<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
lock_user_prot_reg<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//基于kvec的形式写</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
writev<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">const</span>
<span style="color: #0000ff;">struct</span>
kvec <span style="color: #0000cc;">*</span>
vecs<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
<span style="color: #ff0000;">count</span>
<span style="color: #0000cc;">,</span>
loff_t to<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//实现MTD设备的同步操作</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
sync<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//实现特定芯片的加锁和解锁</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
lock<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t ofs<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">uint64_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
unlock<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t ofs<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">uint64_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//实现支持电源管理</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
suspend<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
resume<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//坏块管理功能</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
block_isbad<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t ofs<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
block_markbad<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t ofs<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//默认重启的MTD设备工作模式</span>
<br><span style="color: #0000ff;">struct</span>
notifier_block reboot_notifier<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//用于记录ECC状态的信息</span>
<br><span style="color: #0000ff;">struct</span>
mtd_ecc_stats ecc_stats<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">/* Subpage shift (NAND) */</span>
<br><span style="color: #0000ff;">int</span>
subpage_sft<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//私有数据,注意是void类型的指针</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">*</span>
priv<span style="color: #0000cc;">;</span>
<br><br><span style="color: #0000ff;">struct</span>
module <span style="color: #0000cc;">*</span>
owner<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">struct</span>
device dev<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
usecount<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//记录用户的个数</span>
<br><br><span style="color: #ff9900;">//这两个方法用于设备驱动的回调,可以根据具体需要来决定是否实现他们</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
get_device<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
put_device<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000cc;">}</span>
<span style="color: #0000cc;">;</span>
</span>
</span>
</code>
</p>
</td>
</tr></tbody></table>
<br><table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000ff;">struct</span>
mtd_part <br><span style="color: #0000cc;">{</span>
<br><span style="color: #0000ff;">struct</span>
mtd_info mtd<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//本分区信息(会被加入到mtd_table中,其大部分成员由其master决定)</span>
<br><span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
master<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//该分区的主分区(不作为一个mtd_info加入到mtd_table。这也解释了上面的一个比喻,1个原始设备上有3个分区,最后将只有3个mtd_info加入到mtd_table而不是4个)</span>
<br><span style="color: #ff0000;">uint64_t</span>
offset<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//该分区的偏移地址</span>
<br><span style="color: #0000ff;">int</span>
index<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//该分区号</span>
<br><span style="color: #0000ff;">struct</span>
list_head <span style="color: #ff0000;">list</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
registered<span style="color: #0000cc;">;</span>
<br><span style="color: #0000cc;">}</span>
<span style="color: #0000cc;">;</span>
</span>
</span>
</code>
</p>
</td>
</tr></tbody></table></span>
</li>
</ol>
<div>
<strong><span style="">三、Linux中的Nor Flash驱动</span>
</strong>
</div>
<p></p>
<div>未完,待续。。。。。。</div>
<span style="">嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤。一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便。如有错误之处,谢请指正。</span>
</div>
<ul>
<li>
<span style="">共享资源,欢迎转载:</span>
<a href="http://hbhuanggang.cublog.cn/"><span style="">http://hbhuanggang.cublog.cn</span>
</a>
</li>
</ul>
<p><strong><span style="">一、Linux中Flash硬件知识</span>
</strong>
</p>
<ol>
<li>
<span style="font-size: x-small;">Flash用途和分类:<br><br>
在嵌入式系统开发设计中,存储模块是不可缺少的重要部分,而
Flash是目前市场上主要的非易失闪存技术,他主要分为:Nor Flash和Nand Flash两种。那么他们有什么区别呢?简单的讲:Nor
Flash容量小,价格高,写速度慢但随机读速度快,所以较适合存储少量的程序代码,比如u-boot启动代码;而Nand
Flash则容量大,价格低,写速度快但读速度慢,所以他相当于PC上的硬盘用于存储大量的数据。Nor Flash与Nand
Flash更详细区别如下表:<br><img src="http://blog.chinaunix.net/photo/101649_100629103038.png" alt=""><br></span>
</li>
<li>
<span style="font-size: x-small;">Flash在硬件设计中的应用:<br><br>
以Mini2440开发板为例:该开发板上带有一块2M的Nor Flash和一块64M的Nand Flash。下面先看看他们是怎样被应用于嵌入式Linux的。Nor Flash和Nand Flash电路原理图分别如下:(由mini2440提供)<br><img src="http://blog.chinaunix.net/photo/101649_100629104856.png" alt=""><br><br>
从
原理图上可以看到,Nor Flash内部提供的是有类似于DRam之类的地址总线,可以直接与CPU相连,CPU可以直接通过地址总线对Nor
Flash进行访问;而Nand Flash没有这类的总线,其内部只提供IO接口,因此只能通过IO接口发送命令和地址,对Nand
Flash内部数据进行访问。这可以说是二者最大的区别了,也说明了二者读写速度不同的所在。因此,各有各的优点,Nor Flash访问快,Nand
Flash简化了电路。注意:电路原理图中字母上面有一横杠的表示该引脚是低电平有效,没有的是默认的高电平。</span>
</li>
</ol>
<div>
<strong><span style="">二、Linux中Flash软件知识</span>
</strong>
</div>
<ol>
<li>
<span style="">Linux MTD子系统:<br><br>
在Linux系统中,提供了MTD(内存技术设备)子系统来建立Flash针对Linux的统一、抽象的接口。MTD子系统将上层文件系统与底层
Flash硬件进行了隔离,使Flash驱动开发者无需再关心Flash作为字符设备或者块设备与Linux内核的接口。MTD将Linux系统
Flash设备驱动及接口分成了4个层次,如图所示,从上往下分别为:设备节点、MTD设备层、MTD原始设备层和Flash硬件驱动层。<br><img src="http://blog.chinaunix.net/photo/101649_100629160140.png" alt=""><br><br><strong>设备节点:</strong>
用户在/dev目录下使用mknod命令建立MTD字符设备节点(主设备号为90),或者MTD块设备节点(主设备号为31),使用该设备节点即可访问MTD设备。<br><br><strong>MTD设备层:</strong>
基于MTD原始设备层,系统将MTD设备可以定义为MTD字符设备(在/mtd/mtdchar.c中实现)和MTD块设备(在/mtd/mtdblock.c中实现)。<br><br><strong>MTD原始设备层:</strong>
MTD原始设备层由两个部分组成,分别是MTD原始设备的通用代码和各个特定的Flash的数据,如分区信息。<br><br><strong>Flash硬件驱动层:</strong>
Flash硬件驱动层负责对Flash硬件的读、写和擦除操作。MTD设备的Nor Flash芯片驱动一般位于drivers/mtd/chips/子目录下,Nand Flash芯片的驱动则位于drivers/mtd/nand/子目录下。<br><br>
综
合上述我们可知,MTD子系统已经对Flash设备对于上层的应用进行了封装,我们在写硬件驱动的时候直接调用MTD原始设备层提供的接口函数做相应的操
作即可。那么,对于MTD设备层,MTD原始设备层提供了哪些接口呢?对于Flash硬件驱动层,MTD原始设备层又提供了哪些接口呢?下面开始了解。<br><br></span>
</li>
<li>
<span style="font-size: x-small;">MTD子系统接口:<br><br>
在MTD子系统中,MTD设备层、MTD原始设备层和Flash硬件驱动层之间的接口关系如下图所示:<br><img src="http://blog.chinaunix.net/photo/101649_100701145306.png" alt=""><br>
从上图可知,MTD设备层是通过原始设备层提供的接口来注册MTD字符设备或MTD块设备的,同样,驱动工程师要编写的Flash硬件驱动也是通过原始设备层提供的接口来添加MTD设备和MTD分区的,分别如下:
<table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #ff9933;">//使用这两个接口函数进行添加和删除MTD设备</span>
<br><span style="color: #0000ff;">int</span>
add_mtd_device<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
del_mtd_device<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
</span>
</span>
</code>
</p>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"></span>
</span>
</code>
</p>
<code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000cc;">
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #ff9933;">//使用这两个接口函数进行添加和删除MTD分区</span>
<br><span style="color: #0000ff;">int</span>
add_mtd_partitions<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*<span style="color: #000000;">master</span>
, struct <span style="color: #000000;">mtd_partition</span>
*<span style="color: #000000;">parts</span>
, int <span style="color: #000000;">nbparts</span>
</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
del_mtd_partitions<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*<span style="color: #000000;">master</span>
</span>
<span style="color: #0000cc;">)</span>
</span>
</span>
</code>
</p>
</span>
</span>
</span>
</code>
</td>
</tr></tbody></table>
<br><br>
在
MTD中,一个MTD原始设备用mtd_info结构体来表示,定义在include/linux/mtd/mtd.h中;一个MTD原始设备分区用
mtd_part结构体来表示,定义在drivers/mtd/mtdpart.c中。其中每个分区也被认为是一个mtd_info,比如:有一个MTD
原始设备,上面有3个分区,那么将共有3个mtd_info,而这3个mtd_info的指针将被存放在mtd_table的数组中进行管理,定义在
drivers/mtd/mtdcore.h中,如下所示:
<table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000ff;">extern</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd_table<span style="color: #0000cc;">[</span>
MAX_MTD_DEVICES<span style="color: #0000cc;">]</span>
<span style="color: #0000cc;">;<span style="color: #ff9933;">//最多有MAX_MTD_DEVICES(默认定义为32)个设备</span>
</span>
</span>
</span>
</code>
</p>
</td>
</tr></tbody></table>
<br><br></span>
</li>
<li>
<span style="font-size: x-small;">MTD子系统中重要的一些数据结构:<br><table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000ff;">struct</span>
mtd_info <br><span style="color: #0000cc;">{</span>
<br><span style="color: #ff9900;">//硬件设备的类型,如:MTD_RAM,MTD_ROM,MTD_NORFlash,MTD_NANDFlash,MTD_PEROM等</span>
<br>
u_char type<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//设备支持的选项,如:MTD_ERASEABLE(可擦除),MTD_WRITEB_WRITEALBE(可编程),</span>
<br><span style="color: #ff9900;">//MTD_XIP(可片内执行),MTD_OOB(NAND额外数据),MTD_ECC(支持自动ECC)等</span>
<br><span style="color: #ff0000;">uint32_t</span>
flags<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff0000;">uint64_t</span>
size<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//MTD设备的大小</span>
<br><span style="color: #ff0000;">uint32_t</span>
erasesize<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//主要的擦除块大小(注意:同一个MTD设备可能有几种不同的erasesize)</span>
<br><span style="color: #ff0000;">uint32_t</span>
writesize<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//编程块大小</span>
<br><span style="color: #ff0000;">uint32_t</span>
oobsize<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//OOB数据大小</span>
<br><span style="color: #ff0000;">uint32_t</span>
oobavail<span style="color: #0000cc;">;</span>
<br><br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">int</span>
erasesize_shift<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">int</span>
writesize_shift<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">int</span>
erasesize_mask<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">int</span>
writesize_mask<span style="color: #0000cc;">;</span>
<br><br><span style="color: #0000ff;">const</span>
<span style="color: #0000ff;">char</span>
<span style="color: #0000cc;">*</span>
name<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
index<span style="color: #0000cc;">;</span>
<br><br><span style="color: #0000ff;">struct</span>
nand_ecclayout <span style="color: #0000cc;">*</span>
ecclayout<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//ECC布局结构</span>
<br><br><span style="color: #0000ff;">int</span>
numeraseregions<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//擦除区域的个数,通常为1</span>
<br><span style="color: #0000ff;">struct</span>
mtd_erase_region_info <span style="color: #0000cc;">*</span>
eraseregions<span style="color: #0000cc;">;</span>
</span>
<span style="font-family: NSimsun;"><span style="color: #ff9900;">//擦除区域的指针<br></span>
<br><span style="color: #ff9900;">//此方法将一个erase_info结构放入擦除队列中</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
erase<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
erase_info <span style="color: #0000cc;">*</span>
instr<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//point和unpoint方法分别用于允许和禁止芯片内执行(eXecute-In-Place,简称XIP),如果unpoint为NULL,则表示禁止XIP</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
point<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">*</span>
<span style="color: #0000cc;">*</span>
virt<span style="color: #0000cc;">,</span>
resource_size_t <span style="color: #0000cc;">*</span>
phys<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
unpoint<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//如果不为NULL,则表示允许无MMU单元的虚拟地址映射</span>
<br><span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
get_unmapped_area<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
offset<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
flags<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">struct</span>
backing_dev_info <span style="color: #0000cc;">*</span>
backing_dev_info<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//read和write分别用于MTD设备的读和写</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
<span style="color: #ff0000;">read</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
<span style="color: #ff0000;">write</span>
<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t to<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">const</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
panic_write<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t to<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">const</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//read_oob和write_oob分别用于读写MTD设备的OOB数据</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
read_oob<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
mtd_oob_ops <span style="color: #0000cc;">*</span>
ops<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
write_oob<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t to<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
mtd_oob_ops <span style="color: #0000cc;">*</span>
ops<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//一下几个方法是用于实现访问一些受保护的寄存器(一般这只是出现在某些特定的Flash设备上)</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
get_fact_prot_info<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
otp_info <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
read_fact_prot_reg<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
get_user_prot_info<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">struct</span>
otp_info <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
read_user_prot_reg<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
write_user_prot_reg<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">,</span>
u_char <span style="color: #0000cc;">*</span>
buf<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
lock_user_prot_reg<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t from<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//基于kvec的形式写</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
writev<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">const</span>
<span style="color: #0000ff;">struct</span>
kvec <span style="color: #0000cc;">*</span>
vecs<span style="color: #0000cc;">,</span>
<span style="color: #0000ff;">unsigned</span>
<span style="color: #0000ff;">long</span>
<span style="color: #ff0000;">count</span>
<span style="color: #0000cc;">,</span>
loff_t to<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">size_t</span>
<span style="color: #0000cc;">*</span>
retlen<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//实现MTD设备的同步操作</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
sync<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//实现特定芯片的加锁和解锁</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
lock<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t ofs<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">uint64_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
unlock<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t ofs<span style="color: #0000cc;">,</span>
<span style="color: #ff0000;">uint64_t</span>
len<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//实现支持电源管理</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
suspend<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
resume<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//坏块管理功能</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
block_isbad<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t ofs<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
block_markbad<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">,</span>
loff_t ofs<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//默认重启的MTD设备工作模式</span>
<br><span style="color: #0000ff;">struct</span>
notifier_block reboot_notifier<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//用于记录ECC状态的信息</span>
<br><span style="color: #0000ff;">struct</span>
mtd_ecc_stats ecc_stats<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">/* Subpage shift (NAND) */</span>
<br><span style="color: #0000ff;">int</span>
subpage_sft<span style="color: #0000cc;">;</span>
<br><br><span style="color: #ff9900;">//私有数据,注意是void类型的指针</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">*</span>
priv<span style="color: #0000cc;">;</span>
<br><br><span style="color: #0000ff;">struct</span>
module <span style="color: #0000cc;">*</span>
owner<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">struct</span>
device dev<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
usecount<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//记录用户的个数</span>
<br><br><span style="color: #ff9900;">//这两个方法用于设备驱动的回调,可以根据具体需要来决定是否实现他们</span>
<br><span style="color: #0000ff;">int</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
get_device<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">void</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000cc;">*</span>
put_device<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">(</span>
<span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
mtd<span style="color: #0000cc;">)</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000cc;">}</span>
<span style="color: #0000cc;">;</span>
</span>
</span>
</code>
</p>
</td>
</tr></tbody></table>
<br><table style="border-collapse: collapse; width: 95%;" border="1" cellspacing="0" cellpadding="0"><tbody><tr>
<td>
<p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="font-family: NSimsun;"><span style="color: #0000ff;">struct</span>
mtd_part <br><span style="color: #0000cc;">{</span>
<br><span style="color: #0000ff;">struct</span>
mtd_info mtd<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//本分区信息(会被加入到mtd_table中,其大部分成员由其master决定)</span>
<br><span style="color: #0000ff;">struct</span>
mtd_info <span style="color: #0000cc;">*</span>
master<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//该分区的主分区(不作为一个mtd_info加入到mtd_table。这也解释了上面的一个比喻,1个原始设备上有3个分区,最后将只有3个mtd_info加入到mtd_table而不是4个)</span>
<br><span style="color: #ff0000;">uint64_t</span>
offset<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//该分区的偏移地址</span>
<br><span style="color: #0000ff;">int</span>
index<span style="color: #0000cc;">;</span>
<span style="color: #ff9900;">//该分区号</span>
<br><span style="color: #0000ff;">struct</span>
list_head <span style="color: #ff0000;">list</span>
<span style="color: #0000cc;">;</span>
<br><span style="color: #0000ff;">int</span>
registered<span style="color: #0000cc;">;</span>
<br><span style="color: #0000cc;">}</span>
<span style="color: #0000cc;">;</span>
</span>
</span>
</code>
</p>
</td>
</tr></tbody></table></span>
</li>
</ol>
<div>
<strong><span style="">三、Linux中的Nor Flash驱动</span>
</strong>
</div>
<p></p>
<div>未完,待续。。。。。。</div>