<p><span style="font-size:14px;"><span style="white-space:pre;">MTD,Memory Technology Device即内存技术设备</span>,在Linux内核中,引入MTD层为NOR FLASH和NAND FLASH设备提供统一接口。MTD将文件系统与底层FLASH存储器进行了隔离。</span></p> <p><span style="font-size:14px;"><img src="https://img-blog.csdn.net/20140319173537937?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbHdqMTAzODYyMDk1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""><br></span></p> <p><span style="font-size:14px;"><span style="white-space:pre;"></span>如上图所示,MTD设备通常可分为四层,从上到下依次是:设备节点、MTD设备层、MTD原始设备层、硬件驱动层。</span></p> <p><span style="font-size:14px;"><span style="color:#ff0000;"><strong>Flash硬件驱动层</strong></span>:Flash硬件驱动层负责对Flash硬件的读、写和擦除操作。MTD设备的Nand Flash芯片的驱动则drivers/mtd/nand/子目录下,Nor Flash芯片驱动位于drivers/mtd/chips/子目录下。</span></p> <p><span style="font-size:14px;"><span style="color:#ff0000;"><strong>MTD原始设备层:</strong></span>用于描述MTD原始设备的数据结构是mtd_info,它定义了大量的关于MTD的数据和操作函数。</span><span style="font-size:14px;">其中<span style="color:#ff0000;"><strong>mtdcore.c</strong></span>: MTD原始设备接口相关实现<span style="color:#ff0000;"><strong>,mtdpart.c</strong></span> : MTD分区接口相关实现。</span></p> <p><span style="font-size:14px;"><strong><span style="color:#ff0000;">MTD设备层:</span></strong>基于MTD原始设备,linux系统可以定义出MTD的<strong><span style="color:#cc33cc;">块设备(主设备号31)</span></strong>和<strong><span style="color:#cc33cc;">字符设备(设备号90)</span></strong>。其中<span style="color:#ff0000;"><strong>mtdchar.c</strong></span> : MTD字符设备接口相关实现,<span style="color:#ff0000;"><strong>mtdblock.c</strong></span> : MTD块设备接口相关实现。</span></p> <p><span style="font-size:14px;"><strong><span style="color:#ff0000;">设备节点:</span></strong>通过mknod在/dev子目录下建立<span style="color:#cc33cc;"><strong>MTD块设备节点(主设备号为31)</strong></span>和<span style="color:#cc33cc;"><strong>MTD字符设备节点(主设备号为90)</strong></span>。通过访问此设备节点即可访问MTD字符设备和块设备 </span></p> <p><span style="font-size:18px;"><span style="background-color:rgb(51,255,51);">MTD数据结构:</span></span></p> <p><span style="font-size:14px;">1.Linux内核使用<span style="color:#ff0000;"><strong>mtd_info</strong></span>结构体表示MTD原始设备,这其中定义了大量关于MTD的数据和操作函数(后面将会看到),所有的mtd_info结构体存放在mtd_table结构体数据里。在/drivers/mtd/mtdcore.c里:</span></p> <p><span style="font-size:14px;"></span></p> <div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><b>[cpp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 167px; top: 1219px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_1" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_1" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div><div style="position: absolute; left: 167px; top: 1219px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_8" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_8" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=8&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-cpp"><li class="alt"><span><span class="keyword">struct</span><span> mtd_info *mtd_table[MAX_MTD_DEVICES]; </span></span></li></ol></div><pre class="cpp" name="code" style="display: none;">struct mtd_info *mtd_table[MAX_MTD_DEVICES];</pre>2.Linux内核使用<span style="color:#ff0000;"><strong>mtd_part</strong></span>结构体表示分区,其中mtd_info结构体成员用于描述该分区,大部分成员由其主分区mtd_part->master决定,各种函数也指向主分区的相应函数。 <p></p> <p><span style="font-size:14px;"></span></p> <div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><b>[cpp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 167px; top: 1348px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_2" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_2" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=2&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div><div style="position: absolute; left: 167px; top: 1348px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_9" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_9" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=9&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-cpp"><li class="alt"><span><span class="keyword">struct</span><span> mtd_part { </span></span></li><li class=""><span> <span class="keyword">struct</span><span> mtd_info mtd; </span><span class="comment">/* 分区信息, 大部分由master决定 */</span><span> </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> mtd_info *master; </span><span class="comment">/* 分区的主分区 */</span><span> </span></span></li><li class=""><span> uint64_t offset; <span class="comment">/* 分区的偏移地址 */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> index; </span><span class="comment">/* 分区号 (Linux3.0后不存在该字段) */</span><span> </span></span></li><li class=""><span> <span class="keyword">struct</span><span> list_head list; </span><span class="comment">/* 将mtd_part链成一个链表mtd_partitons */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> registered; </span></span></li><li class=""><span>}; </span></li></ol></div><pre class="cpp" name="code" style="display: none;">struct mtd_part { struct mtd_info mtd; /* 分区信息, 大部分由master决定 */ struct mtd_info *master; /* 分区的主分区 */ uint64_t offset; /* 分区的偏移地址 */ int index; /* 分区号 (Linux3.0后不存在该字段) */ struct list_head list; /* 将mtd_part链成一个链表mtd_partitons */ int registered; };</pre>mtd_info结构体主要成员,为了便于观察,将重要的数据放在前面,不大重要的编写在后面。 <p></p> <p><span style="font-size:14px;"></span></p> <div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><b>[cpp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 167px; top: 1581px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_3" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_3" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=3&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div><div style="position: absolute; left: 167px; top: 1581px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_10" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_10" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=10&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-cpp"><li class="alt"><span><span class="keyword">struct</span><span> mtd_info { </span></span></li><li class=""><span> u_char type; <span class="comment">/* MTD类型,包括MTD_NORFLASH,MTD_NANDFLASH等(可参考mtd-abi.h) */</span><span> </span></span></li><li class="alt"><span> uint32_t flags; <span class="comment">/* MTD属性标志,MTD_WRITEABLE,MTD_NO_ERASE等(可参考mtd-abi.h) */</span><span> </span></span></li><li class=""><span> uint64_t size; <span class="comment">/* mtd设备的大小 */</span><span> </span></span></li><li class="alt"><span> uint32_t erasesize; <span class="comment">/* MTD设备的擦除单元大小,对于NandFlash来说就是Block的大小 */</span><span> </span></span></li><li class=""><span> uint32_t writesize; <span class="comment">/* 写大小, 对于norFlash是字节,对nandFlash为一页 */</span><span> </span></span></li><li class="alt"><span> uint32_t oobsize; <span class="comment">/* OOB字节数 */</span><span> </span></span></li><li class=""><span> uint32_t oobavail; <span class="comment">/* 可用的OOB字节数 */</span><span> </span></span></li><li class="alt"><span> unsigned <span class="datatypes">int</span><span> erasesize_shift; </span><span class="comment">/* 默认为0,不重要 */</span><span> </span></span></li><li class=""><span> unsigned <span class="datatypes">int</span><span> writesize_shift; </span><span class="comment">/* 默认为0,不重要 */</span><span> </span></span></li><li class="alt"><span> unsigned <span class="datatypes">int</span><span> erasesize_mask; </span><span class="comment">/* 默认为1,不重要 */</span><span> </span></span></li><li class=""><span> unsigned <span class="datatypes">int</span><span> writesize_mask; </span><span class="comment">/* 默认为1,不重要 */</span><span> </span></span></li><li class="alt"><span> <span class="keyword">const</span><span> </span><span class="datatypes">char</span><span> *name; </span><span class="comment">/* 名字, 不重要*/</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> index; </span><span class="comment">/* 索引号,不重要 */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> numeraseregions; </span><span class="comment">/* 通常为1 */</span><span> </span></span></li><li class=""><span> <span class="keyword">struct</span><span> mtd_erase_region_info *eraseregions; </span><span class="comment">/* 可变擦除区域 */</span><span> </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="keyword">void</span><span> *priv; </span><span class="comment">/* 设备私有数据指针,对于NandFlash来说指nand_chip结构体 */</span><span> </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> module *owner; </span><span class="comment">/* 一般设置为THIS_MODULE */</span><span> </span></span></li><li class=""><span> </span></li><li class="alt"><span> <span class="comment">/* 擦除函数 */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*erase) (</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">struct</span><span> erase_info *instr); </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="comment">/* 读写flash函数 */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*read) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t from, </span><span class="datatypes">size_t</span><span> len, </span><span class="datatypes">size_t</span><span> *retlen, u_char *buf); </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*write) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t to, </span><span class="datatypes">size_t</span><span> len, </span><span class="datatypes">size_t</span><span> *retlen, </span><span class="keyword">const</span><span> u_char *buf); </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="comment">/* 带oob读写Flash函数 */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*read_oob) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t from, </span></span></li><li class=""><span> <span class="keyword">struct</span><span> mtd_oob_ops *ops); </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*write_oob) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t to, </span></span></li><li class=""><span> <span class="keyword">struct</span><span> mtd_oob_ops *ops); </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="datatypes">int</span><span> (*get_fact_prot_info) (</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">struct</span><span> otp_info *buf, </span><span class="datatypes">size_t</span><span> len); </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*read_fact_prot_reg) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t from, </span><span class="datatypes">size_t</span><span> len, </span><span class="datatypes">size_t</span><span> *retlen, u_char *buf); </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*get_user_prot_info) (</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">struct</span><span> otp_info *buf, </span><span class="datatypes">size_t</span><span> len); </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*read_user_prot_reg) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t from, </span><span class="datatypes">size_t</span><span> len, </span><span class="datatypes">size_t</span><span> *retlen, u_char *buf); </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*write_user_prot_reg) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t from, </span><span class="datatypes">size_t</span><span> len, </span><span class="datatypes">size_t</span><span> *retlen, u_char *buf); </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*lock_user_prot_reg) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t from, </span><span class="datatypes">size_t</span><span> len); </span></span></li><li class=""><span> </span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*writev) (</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">const</span><span> </span><span class="keyword">struct</span><span> kvec *vecs, unsigned </span><span class="datatypes">long</span><span> count, loff_t to, </span><span class="datatypes">size_t</span><span> *retlen); </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*panic_write) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t to, </span><span class="datatypes">size_t</span><span> len, </span><span class="datatypes">size_t</span><span> *retlen, </span><span class="keyword">const</span><span> u_char *buf); </span></span></li><li class="alt"><span> <span class="comment">/* Sync */</span><span> </span></span></li><li class=""><span> <span class="keyword">void</span><span> (*sync) (</span><span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="comment">/* Chip-supported device locking */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*lock) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t ofs, uint64_t len); </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*unlock) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t ofs, uint64_t len); </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="comment">/* 电源管理函数 */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*suspend) (</span><span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class=""><span> <span class="keyword">void</span><span> (*resume) (</span><span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="comment">/* 坏块管理函数 */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*block_isbad) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t ofs); </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*block_markbad) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t ofs); </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="keyword">void</span><span> (*unpoint) (</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t from, </span><span class="datatypes">size_t</span><span> len); </span></span></li><li class="alt"><span> unsigned <span class="datatypes">long</span><span> (*get_unmapped_area) (</span><span class="keyword">struct</span><span> mtd_info *mtd, </span></span></li><li class=""><span> unsigned <span class="datatypes">long</span><span> len, </span></span></li><li class="alt"><span> unsigned <span class="datatypes">long</span><span> offset, </span></span></li><li class=""><span> unsigned <span class="datatypes">long</span><span> flags); </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> backing_dev_info *backing_dev_info; </span></span></li><li class=""><span> <span class="keyword">struct</span><span> notifier_block reboot_notifier; </span><span class="comment">/* default mode before reboot */</span><span> </span></span></li><li class="alt"><span> </span></li><li class=""><span> <span class="comment">/* ECC status information */</span><span> </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> mtd_ecc_stats ecc_stats; </span></span></li><li class=""><span> <span class="datatypes">int</span><span> subpage_sft; </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> device dev; </span></span></li><li class=""><span> <span class="datatypes">int</span><span> usecount; </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*get_device) (</span><span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class=""><span> <span class="keyword">void</span><span> (*put_device) (</span><span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class="alt"><span>}; </span></li></ol></div><pre class="cpp" name="code" style="display: none;">struct mtd_info { u_char type; /* MTD类型,包括MTD_NORFLASH,MTD_NANDFLASH等(可参考mtd-abi.h) */ uint32_t flags; /* MTD属性标志,MTD_WRITEABLE,MTD_NO_ERASE等(可参考mtd-abi.h) */ uint64_t size; /* mtd设备的大小 */ uint32_t erasesize; /* MTD设备的擦除单元大小,对于NandFlash来说就是Block的大小 */ uint32_t writesize; /* 写大小, 对于norFlash是字节,对nandFlash为一页 */ uint32_t oobsize; /* OOB字节数 */ uint32_t oobavail; /* 可用的OOB字节数 */ unsigned int erasesize_shift; /* 默认为0,不重要 */ unsigned int writesize_shift; /* 默认为0,不重要 */ unsigned int erasesize_mask; /* 默认为1,不重要 */ unsigned int writesize_mask; /* 默认为1,不重要 */ const char *name; /* 名字, 不重要*/ int index; /* 索引号,不重要 */ int numeraseregions; /* 通常为1 */ struct mtd_erase_region_info *eraseregions; /* 可变擦除区域 */ void *priv; /* 设备私有数据指针,对于NandFlash来说指nand_chip结构体 */ struct module *owner; /* 一般设置为THIS_MODULE */ /* 擦除函数 */ int (*erase) (struct mtd_info *mtd, struct erase_info *instr); /* 读写flash函数 */ int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); /* 带oob读写Flash函数 */ int (*read_oob) (struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); int (*write_oob) (struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len); int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); /* Sync */ void (*sync) (struct mtd_info *mtd); /* Chip-supported device locking */ int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); /* 电源管理函数 */ int (*suspend) (struct mtd_info *mtd); void (*resume) (struct mtd_info *mtd); /* 坏块管理函数 */ int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len); unsigned long (*get_unmapped_area) (struct mtd_info *mtd, unsigned long len, unsigned long offset, unsigned long flags); struct backing_dev_info *backing_dev_info; struct notifier_block reboot_notifier; /* default mode before reboot */ /* ECC status information */ struct mtd_ecc_stats ecc_stats; int subpage_sft; struct device dev; int usecount; int (*get_device) (struct mtd_info *mtd); void (*put_device) (struct mtd_info *mtd); };</pre><span style="white-space:pre;"></span>mtd_info结构体中的read()、write()、read_oob()、write_oob()、erase()是MTD设备驱动要实现的主要函数,幸运的是Linux大牛已经帮我们实现了一套适合大部分FLASH设备的mtd_info成员函数。 <p></p> <p><span style="font-size:14px;"><span style="white-space:pre;"></span>如果MTD设备<span style="color:#ff0000;"><strong>只有一个分区</strong></span>,那么使用下面两个函数注册和注销MTD设备。</span></p> <p><span style="font-size:14px;"></span></p> <div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><b>[cpp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 167px; top: 3048px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_4" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_4" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=4&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div><div style="position: absolute; left: 167px; top: 3048px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_11" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_11" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=11&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-cpp"><li class="alt"><span><span class="datatypes">int</span><span> add_mtd_device(</span><span class="keyword">struct</span><span> mtd_info *mtd) </span></span></li><li class=""><span><span class="datatypes">int</span><span> del_mtd_device (</span><span class="keyword">struct</span><span> mtd_info *mtd) </span></span></li></ol></div><pre class="cpp" name="code" style="display: none;">int add_mtd_device(struct mtd_info *mtd) int del_mtd_device (struct mtd_info *mtd)</pre><span style="white-space:pre;"></span>如果MTD设备存在其他分区,那么使用下面两个函数注册和注销MTD设备。<br><div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><b>[cpp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 167px; top: 3173px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_5" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_5" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=5&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div><div style="position: absolute; left: 167px; top: 3173px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_12" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_12" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=12&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-cpp"><li class="alt"><span><span class="datatypes">int</span><span> add_mtd_partitions(</span><span class="keyword">struct</span><span> mtd_info *master,</span><span class="keyword">const</span><span> </span><span class="keyword">struct</span><span> mtd_partition *parts,</span><span class="datatypes">int</span><span> nbparts) </span></span></li><li class=""><span><span class="datatypes">int</span><span> del_mtd_partitions(</span><span class="keyword">struct</span><span> mtd_info *master) </span></span></li></ol></div><pre class="cpp" name="code" style="display: none;">int add_mtd_partitions(struct mtd_info *master,const struct mtd_partition *parts,int nbparts) int del_mtd_partitions(struct mtd_info *master)</pre>其中<span style="color:#ff0000;"><strong>mtd_partition</strong></span>结构体表示分区的信息 <p></p> <p></p> <div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><b>[cpp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 167px; top: 3298px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_6" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_6" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=6&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div><div style="position: absolute; left: 167px; top: 3298px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_13" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_13" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=13&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-cpp"><li class="alt"><span><span class="keyword">struct</span><span> mtd_partition { </span></span></li><li class=""><span> <span class="datatypes">char</span><span> *name; </span><span class="comment">/* 分区名,如TQ2440_Board_uboot、TQ2440_Board_kernel、TQ2440_Board_yaffs2 */</span><span> </span></span></li><li class="alt"><span> uint64_t size; <span class="comment">/* 分区大小 */</span><span> </span></span></li><li class=""><span> uint64_t offset; <span class="comment">/* 分区偏移值 */</span><span> </span></span></li><li class="alt"><span> uint32_t mask_flags; <span class="comment">/* 掩码标识,不重要 */</span><span> </span></span></li><li class=""><span> <span class="keyword">struct</span><span> nand_ecclayout *ecclayout; </span><span class="comment">/* OOB布局 */</span><span> </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> mtd_info **mtdp; </span><span class="comment">/* pointer to store the MTD object */</span><span> </span></span></li><li class=""><span>}; </span></li><li class="alt"><span>其中nand_ecclayout结构体: </span></li><li class=""><span><span class="keyword">struct</span><span> nand_ecclayout { </span></span></li><li class="alt"><span> __u32 eccbytes; <span class="comment">/* ECC字节数 */</span><span> </span></span></li><li class=""><span> __u32 eccpos[64]; <span class="comment">/* ECC校验码在OOB区域存放位置 */</span><span> </span></span></li><li class="alt"><span> __u32 oobavail; </span></li><li class=""><span> <span class="comment">/* 除了ECC校验码之外可用的OOB字节数 */</span><span> </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; </span></span></li><li class=""><span>}; </span></li></ol></div><pre class="cpp" style="font-size: 14px; display: none;" name="code">struct mtd_partition { char *name; /* 分区名,如TQ2440_Board_uboot、TQ2440_Board_kernel、TQ2440_Board_yaffs2 */ uint64_t size; /* 分区大小 */ uint64_t offset; /* 分区偏移值 */ uint32_t mask_flags; /* 掩码标识,不重要 */ struct nand_ecclayout *ecclayout; /* OOB布局 */ struct mtd_info **mtdp; /* pointer to store the MTD object */ }; 其中nand_ecclayout结构体: struct nand_ecclayout { __u32 eccbytes; /* ECC字节数 */ __u32 eccpos[64]; /* ECC校验码在OOB区域存放位置 */ __u32 oobavail; /* 除了ECC校验码之外可用的OOB字节数 */ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; };</pre><span style="font-size:14px;white-space:pre;"> </span><span style="font-size:14px;">关于nand_ecclayout结构体实例,更多可参考drivers/mtd/nand/nand_base.c下的nand_oob_8、nand_oob_16、nand_oob_64实例。</span><br><span style="font-size:18px;background-color:rgb(51,255,51);"><strong>MTD设备层:</strong></span> <p></p> <p><span style="font-size:14px;color:#ff0000;"><strong>mtd字符设备接口:</strong></span></p> <p><span style="font-size:14px;"><span style="white-space:pre;"></span>/drivers/mtd/mtdchar.c文件实现了MTD字符设备接口,通过它,可以直接访问Flash设备,与前面的字符驱动一样,通过file_operations结构体里面的open()、read()、write()、ioctl()可以读写Flash,通过一系列IOCTL 命令可以获取Flash 设备信息、擦除Flash、读写NAND 的OOB、获取OOB layout 及检查NAND 坏块等(MEMGETINFO、MEMERASE、MEMREADOOB、MEMWRITEOOB、MEMGETBADBLOCK IOCRL) </span></p> <p><span style="font-size:14px;color:#ff0000;"><strong>mtd块设备接口:</strong></span></p> <p><span style="font-size:14px;"><span style="white-space:pre;"></span><span style="font-size:14px;">/drivers/mtd/mtdblock.c文件实现了MTD块设备接口,主要原理是将Flash的erase block 中的数据在内存中建立映射,然后对其进行修改,最后擦除Flash 上的block,将内存中的映射块写入Flash 块。整个过程被称为read/modify/erase/rewrite 周期。 但是,这样做是不安全的,当下列操作序列发生时,read/modify/erase/poweroff,就会丢失这个block 块的数据。</span><br> MTD硬件驱动层:</span></p> <p><span style="font-size:14px;"><span style="white-space:pre;"></span>Linux内核再MTD层下实现了通用的NAND驱动(/driver/mtd/nand/nand_base.c),因此芯片级的NAND驱动不再需要实现mtd_info结构体中的read()、write()、read_oob()、write_oob()等成员函数。</span></p> <p><span style="font-size:14px;"><span style="white-space:pre;"></span>MTD使用<span style="color:#ff0000;"><strong>nand_chip</strong></span>来表示一个NAND FLASH芯片, 该结构体包含了关于Nand Flash的地址信息,读写方法,ECC模式,硬件控制等一系列底层机制。</span></p> <p><span style="font-size:14px;"></span></p> <div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><b>[cpp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 167px; top: 4192px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_7" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_7" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=7&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div><div style="position: absolute; left: 167px; top: 4192px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_14" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_14" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=14&width=16&height=16" wmode="transparent" width="16" height="16" align="middle"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-cpp"><li class="alt"><span><span class="keyword">struct</span><span> nand_chip { </span></span></li><li class=""><span> <span class="keyword">void</span><span> __iomem *IO_ADDR_R; </span><span class="comment">/* 读8位I/O线地址 */</span><span> </span></span></li><li class="alt"><span> <span class="keyword">void</span><span> __iomem *IO_ADDR_W; </span><span class="comment">/* 写8位I/O线地址 */</span><span> </span></span></li><li class=""><span> </span></li><li class="alt"><span> <span class="comment">/* 从芯片中读一个字节 */</span><span> </span></span></li><li class=""><span> uint8_t (*read_byte)(<span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class="alt"><span> <span class="comment">/* 从芯片中读一个字 */</span><span> </span></span></li><li class=""><span> u16 (*read_word)(<span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class="alt"><span> <span class="comment">/* 将缓冲区内容写入芯片 */</span><span> </span></span></li><li class=""><span> <span class="keyword">void</span><span> (*write_buf)(</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">const</span><span> uint8_t *buf, </span><span class="datatypes">int</span><span> len); </span></span></li><li class="alt"><span> <span class="comment">/* 读芯片读取内容至缓冲区/ */</span><span> </span></span></li><li class=""><span> <span class="keyword">void</span><span> (*read_buf)(</span><span class="keyword">struct</span><span> mtd_info *mtd, uint8_t *buf, </span><span class="datatypes">int</span><span> len); </span></span></li><li class="alt"><span> <span class="comment">/* 验证芯片和写入缓冲区中的数据 */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*verify_buf)(</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">const</span><span> uint8_t *buf, </span><span class="datatypes">int</span><span> len); </span></span></li><li class="alt"><span> <span class="comment">/* 选中芯片 */</span><span> </span></span></li><li class=""><span> <span class="keyword">void</span><span> (*select_chip)(</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="datatypes">int</span><span> chip); </span></span></li><li class="alt"><span> <span class="comment">/* 检测是否有坏块 */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*block_bad)(</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t ofs, </span><span class="datatypes">int</span><span> getchip); </span></span></li><li class="alt"><span> <span class="comment">/* 标记坏块 */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*block_markbad)(</span><span class="keyword">struct</span><span> mtd_info *mtd, loff_t ofs); </span></span></li><li class="alt"><span> <span class="comment">/* 命令、地址、数据控制函数 */</span><span> </span></span></li><li class=""><span> <span class="keyword">void</span><span> (*cmd_ctrl)(</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="datatypes">int</span><span> dat,unsigned </span><span class="datatypes">int</span><span> ctrl); </span></span></li><li class="alt"><span> <span class="comment">/* 设备是否就绪 */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*dev_ready)(</span><span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class="alt"><span> <span class="comment">/* 实现命令发送 */</span><span> </span></span></li><li class=""><span> <span class="keyword">void</span><span> (*cmdfunc)(</span><span class="keyword">struct</span><span> mtd_info *mtd, unsigned command, </span><span class="datatypes">int</span><span> column, </span><span class="datatypes">int</span><span> page_addr); </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*waitfunc)(</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">struct</span><span> nand_chip *</span><span class="keyword">this</span><span>); </span></span></li><li class=""><span> <span class="comment">/* 擦除命令的处理 */</span><span> </span></span></li><li class="alt"><span> <span class="keyword">void</span><span> (*erase_cmd)(</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="datatypes">int</span><span> page); </span></span></li><li class=""><span> <span class="comment">/* 扫描坏块 */</span><span> </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> (*scan_bbt)(</span><span class="keyword">struct</span><span> mtd_info *mtd); </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*errstat)(</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">struct</span><span> nand_chip *</span><span class="keyword">this</span><span>, </span><span class="datatypes">int</span><span> state, </span><span class="datatypes">int</span><span> status, </span><span class="datatypes">int</span><span> page); </span></span></li><li class="alt"><span> <span class="comment">/* 写一页 */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> (*write_page)(</span><span class="keyword">struct</span><span> mtd_info *mtd, </span><span class="keyword">struct</span><span> nand_chip *chip, </span></span></li><li class="alt"><span> <span class="keyword">const</span><span> uint8_t *buf, </span><span class="datatypes">int</span><span> page, </span><span class="datatypes">int</span><span> cached, </span><span class="datatypes">int</span><span> raw); </span></span></li><li class=""><span> </span></li><li class="alt"><span> <span class="datatypes">int</span><span> chip_delay; </span><span class="comment">/* 由板决定的延迟时间 */</span><span> </span></span></li><li class=""><span> <span class="comment">/* 与具体的NAND芯片相关的一些选项,如NAND_NO_AUTOINCR,NAND_BUSWIDTH_16等 */</span><span> </span></span></li><li class="alt"><span> unsigned <span class="datatypes">int</span><span> options; </span></span></li><li class=""><span> </span></li><li class="alt"><span> <span class="comment">/* 用位表示的NAND芯片的page大小,如某片NAND芯片</span> </span></li><li class=""><span><span class="comment"> * 的一个page有512个字节,那么page_shift就是9 </span> </span></li><li class="alt"><span><span class="comment"> */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> page_shift; </span></span></li><li class="alt"><span> <span class="comment">/* 用位表示的NAND芯片的每次可擦除的大小,如某片NAND芯片每次可</span> </span></li><li class=""><span><span class="comment"> * 擦除16K字节(通常就是一个block的大小),那么phys_erase_shift就是14</span> </span></li><li class="alt"><span><span class="comment"> */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> phys_erase_shift; </span></span></li><li class="alt"><span> <span class="comment">/* 用位表示的bad block table的大小,通常一个bbt占用一个block,</span> </span></li><li class=""><span><span class="comment"> * 所以bbt_erase_shift通常与phys_erase_shift相等</span> </span></li><li class="alt"><span><span class="comment"> */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> bbt_erase_shift; </span></span></li><li class="alt"><span> <span class="comment">/* 用位表示的NAND芯片的容量 */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> chip_shift; </span></span></li><li class="alt"><span> <span class="comment">/* NADN FLASH芯片的数量 */</span><span> </span></span></li><li class=""><span> <span class="datatypes">int</span><span> numchips; </span></span></li><li class="alt"><span> <span class="comment">/* NAND芯片的大小 */</span><span> </span></span></li><li class=""><span> uint64_t chipsize; </span></li><li class="alt"><span> <span class="datatypes">int</span><span> pagemask; </span></span></li><li class=""><span> <span class="datatypes">int</span><span> pagebuf; </span></span></li><li class="alt"><span> <span class="datatypes">int</span><span> subpagesize; </span></span></li><li class=""><span> uint8_t cellinfo; </span></li><li class="alt"><span> <span class="datatypes">int</span><span> badblockpos; </span></span></li><li class=""><span> nand_state_t state; </span></li><li class="alt"><span> uint8_t *oob_poi; </span></li><li class=""><span> <span class="keyword">struct</span><span> nand_hw_control *controller; </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> nand_ecclayout *ecclayout; </span><span class="comment">/* ECC布局 */</span><span> </span></span></li><li class=""><span> </span></li><li class="alt"><span> <span class="keyword">struct</span><span> nand_ecc_ctrl ecc; </span><span class="comment">/* ECC校验结构体,里面有大量的函数进行ECC校验 */</span><span> </span></span></li><li class=""><span> <span class="keyword">struct</span><span> nand_buffers *buffers; </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> nand_hw_control hwcontrol; </span></span></li><li class=""><span> <span class="keyword">struct</span><span> mtd_oob_ops ops; </span></span></li><li class="alt"><span> uint8_t *bbt; </span></li><li class=""><span> <span class="keyword">struct</span><span> nand_bbt_descr *bbt_td; </span></span></li><li class="alt"><span> <span class="keyword">struct</span><span> nand_bbt_descr *bbt_md; </span></span></li><li class=""><span> <span class="keyword">struct</span><span> nand_bbt_descr *badblock_pattern; </span></span></li><li class="alt"><span> <span class="keyword">void</span><span> *priv; </span></span></li><li class=""><span>}; </span></li></ol></div><pre class="cpp" name="code" style="display: none;">struct nand_chip { void __iomem *IO_ADDR_R; /* 读8位I/O线地址 */ void __iomem *IO_ADDR_W; /* 写8位I/O线地址 */ /* 从芯片中读一个字节 */ uint8_t (*read_byte)(struct mtd_info *mtd); /* 从芯片中读一个字 */ u16 (*read_word)(struct mtd_info *mtd); /* 将缓冲区内容写入芯片 */ void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); /* 读芯片读取内容至缓冲区/ */ void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); /* 验证芯片和写入缓冲区中的数据 */ int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); /* 选中芯片 */ void (*select_chip)(struct mtd_info *mtd, int chip); /* 检测是否有坏块 */ int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); /* 标记坏块 */ int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); /* 命令、地址、数据控制函数 */ void (*cmd_ctrl)(struct mtd_info *mtd, int dat,unsigned int ctrl); /* 设备是否就绪 */ int (*dev_ready)(struct mtd_info *mtd); /* 实现命令发送 */ void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); /* 擦除命令的处理 */ void (*erase_cmd)(struct mtd_info *mtd, int page); /* 扫描坏块 */ int (*scan_bbt)(struct mtd_info *mtd); int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); /* 写一页 */ int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int page, int cached, int raw); int chip_delay; /* 由板决定的延迟时间 */ /* 与具体的NAND芯片相关的一些选项,如NAND_NO_AUTOINCR,NAND_BUSWIDTH_16等 */ unsigned int options; /* 用位表示的NAND芯片的page大小,如某片NAND芯片 * 的一个page有512个字节,那么page_shift就是9 */ int page_shift; /* 用位表示的NAND芯片的每次可擦除的大小,如某片NAND芯片每次可 * 擦除16K字节(通常就是一个block的大小),那么phys_erase_shift就是14 */ int phys_erase_shift; /* 用位表示的bad block table的大小,通常一个bbt占用一个block, * 所以bbt_erase_shift通常与phys_erase_shift相等 */ int bbt_erase_shift; /* 用位表示的NAND芯片的容量 */ int chip_shift; /* NADN FLASH芯片的数量 */ int numchips; /* NAND芯片的大小 */ uint64_t chipsize; int pagemask; int pagebuf; int subpagesize; uint8_t cellinfo; int badblockpos; nand_state_t state; uint8_t *oob_poi; struct nand_hw_control *controller; struct nand_ecclayout *ecclayout; /* ECC布局 */ struct nand_ecc_ctrl ecc; /* ECC校验结构体,里面有大量的函数进行ECC校验 */ struct nand_buffers *buffers; struct nand_hw_control hwcontrol; struct mtd_oob_ops ops; uint8_t *bbt; struct nand_bbt_descr *bbt_td; struct nand_bbt_descr *bbt_md; struct nand_bbt_descr *badblock_pattern; void *priv; };</pre><span style="white-space:pre;"></span>最后,我们来用图表的形式来总结一下,MTD设备层、MTD原始设备层、FLASH硬件驱动层之间的联系。 <p></p> <p><span style="font-size:14px;"><img src="https://img-blog.csdn.net/20140319203528000?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbHdqMTAzODYyMDk1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""><br></span></p> <p><span style="font-size:14px;"><br></span></p>
Nand flash(二)Linux MTD系统剖析
猜你喜欢
转载自blog.csdn.net/jerrygou/article/details/80348182
今日推荐
周排行