日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

基于MTD的NAND驱动开发(二)

發(fā)布時(shí)間:2023/12/10 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于MTD的NAND驱动开发(二) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基于MTD的NAND驅(qū)動(dòng)開發(fā)(二)

基于MTD的NAND驅(qū)動(dòng)開發(fā)(三)

http://blog.csdn.net/leibniz_zsu/article/details/4977853

http://blog.csdn.net/leibniz_zsu/article/details/4977869

四、基于MTD的NAND 驅(qū)動(dòng)架構(gòu) ? 1 、platform_deviceplatform_driver 的定義和注冊(cè) 對(duì)于我們的NAND driver ,以下是一個(gè)典型的例子:

?static struct platform_driver caorr_nand_driver = {
???????????????. driver = {
????????????????????????????????. name = " caorr-nand" ,
????????????????????????????????. owner = THIS_MODULE,
????????????????} ,
????????????????. probe = caorr_nand_probe,
????????????????. remove = caorr_nand_remove,
?} ;

?static int __init caorr_nand_init( void )
?{
????????????????printk( "CAORR NAND Driver, (c) 2008-2009./n" ) ;
????????????????return platform_driver_register( & caorr_nand_driver) ;
?}

?static void __exit caorr_nand_exit( void )
?{
????????????????platform_driver_unregister( & caorr_nand_driver) ;
?}

?module_init( caorr_nand_init) ;
?module_exit( caorr_nand_exit) ;


與大多數(shù)嵌入式Linux 驅(qū)動(dòng)一樣,NAND 驅(qū)動(dòng)也是從module_init 宏開始。 caorr_nand_init 是驅(qū)動(dòng)初始化函數(shù),在此函數(shù)中注冊(cè)platform driver 結(jié)構(gòu)體,platform driver 結(jié)構(gòu)體中自然需要定義proberemove 函數(shù)。其實(shí)在大多數(shù)嵌入式Linux 驅(qū)動(dòng)中,這樣的套路基本已經(jīng)成了一個(gè)定式 至于module_init 有什么作用,caorr_nand_probe 又是何時(shí)調(diào)用的,以及這個(gè)driver 是怎么和NAND 設(shè)備聯(lián)系起來的,就不再多說了,這里只提三點(diǎn): A、 以上代碼只是向內(nèi)核注冊(cè)了NANDplatform_driver ,即caorr_nand_driver ,我們當(dāng)然還需要一個(gè)NANDplatform_device ,要不然caorr_nand_driverprobe 函數(shù)就永遠(yuǎn)不會(huì)被執(zhí)行,因?yàn)闆]有device 需要這個(gè)driver 。 B、Linux 內(nèi)核注冊(cè)NANDplatform_device 有兩種方式: 其一是直接定義一個(gè)NANDplatform_device 結(jié)構(gòu)體,然后調(diào)用platform_device_register 函數(shù)注冊(cè)。作為例子,我們可以這樣定義NANDplatform_device 結(jié)構(gòu)體:

?struct platform_device caorr_nand_device = {
????????? . name = "caorr-nand" ,
????????? . id = - 1,
????????? . num_resources = 0,
??????????. resource = NULL ,
??????????. dev = {
??????????????. platform_data = & caorr_platform_default_nand,
??????????}
?} ;
?platform_device_register( & caorr_nand_device) ;

其中num_resourcesresource 與具體的硬件相關(guān),主要包括一些寄存器地址范圍和中斷的定義。caorr_platform_default_nand 待會(huì)兒再說。需要注意的是,這個(gè)platform_devicename 的值必須與platform_driver->driver->name 的值完全一致,因?yàn)?span style="font-family:Calibri">platform_bus_typematch 函數(shù)是根據(jù)這兩者的name 值來進(jìn)行匹配的。

其二是用platform_device_alloc 函數(shù)動(dòng)態(tài)分配一個(gè)platform_device ,然后再用platform_device_add 函數(shù)把這個(gè)platform_device 加入到內(nèi)核中去。具體不再細(xì)說,Linux 內(nèi)核中有很多例子可以參考。 相對(duì)來說,第一種方式更加方便和直觀一點(diǎn),而第二種方式則更加靈活一點(diǎn)。 C、 在加載NAND 驅(qū)動(dòng)時(shí),我們還需要向MTD Core 提供一個(gè)信息,那就是NAND 的分區(qū)信息,caorr_platform_default_nand 主要就是起這個(gè)作用,更加詳細(xì)的容后再說。 2 、MTD 架構(gòu)的簡(jiǎn)單描述 ? MTD(memory technology device 存儲(chǔ)技術(shù)設(shè)備) 是用于訪問memory 設(shè)備(ROMflash )的Linux 的子系統(tǒng)。MTD 的主要目的是為了使新的memory 設(shè)備的驅(qū)動(dòng)更加簡(jiǎn)單,為此它在硬件和上層之間提供了一個(gè)抽象的接口。MTD 的所有源代碼在/drivers/mtd 子目錄下。MTD 設(shè)備可分為四層(從設(shè)備節(jié)點(diǎn)直到底層硬件驅(qū)動(dòng)),這四層從上到下依次是:設(shè)備節(jié)點(diǎn)、MTD 設(shè)備層、MTD 原始設(shè)備層和硬件驅(qū)動(dòng)層。

A、Flash硬件驅(qū)動(dòng)層:硬件驅(qū)動(dòng)層負(fù)責(zé)驅(qū)動(dòng)Flash硬件。 B、MTD原始設(shè)備:原始設(shè)備層有兩部分組成,一部分是MTD原始設(shè)備的通用代碼,另一部分是各個(gè)特定的Flash的數(shù)據(jù),例如分區(qū)。 用于描述MTD原始設(shè)備的數(shù)據(jù)結(jié)構(gòu)是mtd_info,這其中定義了大量的關(guān)于MTD的數(shù)據(jù)和操作函數(shù)。mtd_table(mtdcore.c)則是所有MTD原始設(shè)備的列表,mtd_part(mtd_part.c)是用于表示MTD原始設(shè)備分區(qū)的結(jié)構(gòu),其中包含了mtd_info,因?yàn)槊恳粋€(gè)分區(qū)都是被看成一個(gè)MTD原始設(shè)備加在mtd_table中的,mtd_part.mtd_info中的大部分?jǐn)?shù)據(jù)都從該分區(qū)的主分區(qū)mtd_part->master中獲得。 在drivers/mtd/maps/子目錄下存放的是特定的flash的數(shù)據(jù),每一個(gè)文件都描述了一塊板子上的flash。其中調(diào)用add_mtd_device()、del_mtd_device()建立/刪除 mtd_info結(jié)構(gòu)并將其加入/刪除mtd_table(或者調(diào)用add_mtd_partition()、del_mtd_partition() (mtdpart.c)建立/刪除mtd_part結(jié)構(gòu)并將mtd_part.mtd_info加入/刪除mtd_table 中)。 C、MTD設(shè)備層:基于MTD原始設(shè)備,linux系統(tǒng)可以定義出MTD的塊設(shè)備(主設(shè)備號(hào)31)和字符設(shè)備(設(shè)備號(hào)90)。MTD字符設(shè)備的定義在mtdchar.c中實(shí)現(xiàn),通過注冊(cè)一系列file operation函數(shù)(lseek、open、close、read、write)。MTD塊設(shè)備則是定義了一個(gè)描述MTD塊設(shè)備的結(jié)構(gòu) mtdblk_dev,并聲明了一個(gè)名為mtdblks的指針數(shù)組,這數(shù)組中的每一個(gè)mtdblk_dev和mtd_table中的每一個(gè) mtd_info一一對(duì)應(yīng)。 D、設(shè)備節(jié)點(diǎn):通過mknod在/dev子目錄下建立MTD字符設(shè)備節(jié)點(diǎn)(主設(shè)備號(hào)為90)和MTD塊設(shè)備節(jié)點(diǎn)(主設(shè)備號(hào)為31),通過訪問此設(shè)備節(jié)點(diǎn)即可訪問MTD字符設(shè)備和塊設(shè)備。 E、根文件系統(tǒng):在Bootloader中將JFFS(或JFFS2)的文件系統(tǒng)映像jffs.image(或jffs2.img)燒到flash的某一個(gè)分區(qū)中,在/arch/arm/mach-your/arch.c文件的 your_fixup函數(shù)中將該分區(qū)作為根文件系統(tǒng)掛載。 F、文件系統(tǒng):內(nèi)核啟動(dòng)后,通過mount 命令可以將flash中的其余分區(qū)作為文件系統(tǒng)掛載到mountpoint上。 以上是從網(wǎng)上找到的一些資料,我只是斷斷續(xù)續(xù)地看過一些code,沒有系統(tǒng)地研究過,所以這里只能講一下MTD原始設(shè)備層與FLASH硬件驅(qū)動(dòng)之間的交互。 一個(gè)MTD原始設(shè)備可以通過mtd_part分割成數(shù)個(gè)MTD原始設(shè)備注冊(cè)進(jìn)mtd_table,mtd_table中的每個(gè)MTD原始設(shè)備都可以被注冊(cè)成一個(gè)MTD設(shè)備,有兩個(gè)函數(shù)可以完成這個(gè)工作,即 add_mtd_device函數(shù)和add_mtd_partitions函數(shù)。 其中add_mtd_device函數(shù)是把整個(gè)NAND?FLASH注冊(cè)進(jìn)MTD Core,而add_mtd_partitions函數(shù)則是把NAND?FLASH的各個(gè)分區(qū)分別注冊(cè)進(jìn)MTD Core。 add_mtd_partitions函數(shù)的原型是:

int add_mtd_partitions( struct mtd_info * master,

??????????? ?const struct mtd_partition * parts, int nbparts) ;

其中master就是這個(gè)MTD原始設(shè)備,parts即NAND的分區(qū)信息,nbparts指有幾個(gè)分區(qū)。那么parts和nbparts怎么來?caorr_platform_default_nand 就是起這個(gè)作用了。

?static struct mtd_partition caorr_platform_default_nand[ ] = {
?? ?[ 0] = {
???????????????. name = "Boot Strap" ,
???????????????. offset = 0,
???????????????. size = 0x40000,
????} ,
? ??[ 1] = {
???????????????. name = "Bootloader" ,
???????????????. offset = MTDPART_OFS_APPEND,
???????????????. size = 0x40000,
? ??} ,
? ??[ 2] = {
???????????????. name = "Partition Table" ,
???????????????. offset = MTDPART_OFS_APPEND,
???????????????. size = 0x40000,
?? ?} ,
? ??[ 3] = {
???????????????. name = "Linux Kernel" ,
???????????????. offset = MTDPART_OFS_APPEND,
???????????????. size = 0x500000,
?? ?} ,
?? ?[ 4] = {
???????????????. name = "Rootfs" ,
???????????????. offset = MTDPART_OFS_APPEND,
???????????????. size = MTDPART_SIZ_FULL,
?? ?} ,
?} ;

其中offset是分區(qū)開始的偏移地址,在后4個(gè)分區(qū)我們?cè)O(shè)為 MTDPART_OFS_APPEND,表示緊接著上一個(gè)分區(qū),MTD Core會(huì)自動(dòng)計(jì)算和處理分區(qū)地址;size是分區(qū)的大小,在最后一個(gè)分區(qū)我們?cè)O(shè)為MTDPART_SIZ_FULL,表示這個(gè)NADN剩下的所有部分。 這樣配置NAND的分區(qū)并不是唯一的,需要視具體的系統(tǒng)而定,我們可以在kernel中這樣顯式的指定,也可以使用bootloader傳給內(nèi)核的參數(shù)進(jìn)行配置。 另外,MTD對(duì)NAND芯片的讀寫主要分三部分: A、struct mtd_info中的讀寫函數(shù),如read,write_oob等,這是MTD原始設(shè)備層與FLASH硬件層之間的接口; B、struct nand_ecc_ctrl中的讀寫函數(shù),如read_page_raw,write_page等,主要用來做一些與ecc有關(guān)的操作; C、struct nand_chip中的讀寫函數(shù),如read_buf,cmdfunc等,與具體的NAND controller相關(guān),就是這部分函數(shù)與硬件交互,通常需要我們自己來實(shí)現(xiàn)。(注:這里提到的read,write_oob,cmdfunc等,其實(shí)都是些函數(shù)指針,所以這里所說的函數(shù),是指這些函數(shù)指針?biāo)赶虻暮瘮?shù),以后本文將不再另做說明。) 值得一提的是,struct nand_chip中的讀寫函數(shù)雖然與具體的NAND controller相關(guān),但是MTD也為我們提供了default的讀寫函數(shù),如果你的NAND controller比較通用(使用PIO模式),對(duì)NAND芯片的讀寫與MTD提供的這些函數(shù)一致,就不必自己實(shí)現(xiàn)這些函數(shù)了。 這三部分讀寫函數(shù)是相互配合著完成對(duì)NAND芯片的讀寫的。首先,MTD上層需要讀寫NAND芯片時(shí),會(huì)調(diào)用struct mtd_info中的讀寫函數(shù),接著struct mtd_info中的讀寫函數(shù)就會(huì)調(diào)用struct nand_chip或struct nand_ecc_ctrl中的讀寫函數(shù),最后,若調(diào)用的是struct nand_ecc_ctrl中的讀寫函數(shù),那么它又會(huì)接著調(diào)用struct nand_chip中的讀寫函數(shù)。如下圖所示:

以讀NAND芯片為例,講解一下這三部分讀寫函數(shù)的工作過程。 首先,MTD上層會(huì)調(diào)用struct mtd_info中的讀page函數(shù),即nand_read函數(shù)。 接著nand_read函數(shù)會(huì)調(diào)用struct nand_chip中cmdfunc函數(shù),這個(gè)cmdfunc函數(shù)與具體的NAND controller相關(guān),它的作用是使NAND controller向NAND 芯片發(fā)出讀命令,NAND芯片收到命令后,就會(huì)做好準(zhǔn)備等待NAND controller下一步的讀取。 接著nand_read函數(shù)又會(huì)調(diào)用struct nand_ecc_ctrl中的read_page函數(shù),而read_page函數(shù)又會(huì)調(diào)用struct nand_chip中read_buf函數(shù),從而真正把NAND芯片中的數(shù)據(jù)讀取到buffer中(所以這個(gè)read_buf的意思其實(shí)應(yīng)該是read into buffer,另外,這個(gè)buffer是struct mtd_info中的nand_read函數(shù)傳下來的)。 read_buf函數(shù)返回后,read_page函數(shù)就會(huì)對(duì)buffer中的數(shù)據(jù)做一些處理,比如校驗(yàn)ecc,以及若數(shù)據(jù)有錯(cuò),就根據(jù)ecc對(duì)數(shù)據(jù)修正之類的,最后read_page函數(shù)返回到nand_read函數(shù)中。 對(duì)NAND芯片的其它操作,如寫,擦除等,都與讀操作類似。

?

總結(jié)

以上是生活随笔為你收集整理的基于MTD的NAND驱动开发(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。