關於塊裝置與nand flash的初步小結
塊裝置驅動的框架:
呼叫過程自上而下為:應用程式讀寫檔案—>虛擬檔案系統(ext3, yaffs2, jffs2)—>由ll_rw_block函式轉換成扇區的讀寫—>塊裝置驅動程式—>讀寫硬體
塊裝置驅動程式提供一個佇列,將讀操作和寫操作放入佇列內,並且在佇列中優化讀寫順序使得讀寫佔用時間減小(這就是為什麼有時候讀的資料可能並不是真正從磁碟上讀來的而是cache中),裝置驅動另外必要的功能就是要註冊裝置。原理上字元裝置也同樣可以對字盤讀寫,只是少了塊裝置驅動那樣的電梯排程演算法。
塊裝置驅動中重要的資料結構:
struct gendisk:可使用函式alloc_disk分配;
一個簡單的塊裝置驅動需要給以下結構體內的值進行賦值:
struct gendisk {
/* major, first_minor and minors are input parameters only,
* don't use directly. Use disk_devt() and disk_max_parts().
*/
…………
struct request_queue *queue;//使用blk_init_queue函式設定佇列,佇列中包括讀寫的操作
int major; /* major number of driver *///使用register_blkdev註冊到一個主裝置號
int first_minor;
int minors; /* maximum number of minors, =1 for
* disks that can't be partitioned. */
char disk_name[DISK_NAME_LEN];/* name of major driver */
struct block_device_operations *fops;
struct hd_struct part0;//使用set_capacity函式設定有多少個扇區
…………
};
最後註冊gendisk,使用函式:add_disk函式。
對以上相關的結構體進行反註冊的函式有:unregister_blkdev(major, "blockdisk");del_gendisk(block_disk);put_disk(block_disk);blk_cleanup_queue(block_queue);
關於除錯塊裝置的相關命令:
mkdosfs:第一次使用一塊塊裝置需要對其進行格式化;fdisk對一個塊裝置進行分割槽。
nand flash的驅動相關:
nand flash硬體:
如果所示:
其中:
I/O0 ~ I/O7:用於輸入地址/資料/命令,輸出資料;
WP#:Write Protect,防寫;
WE#:Write Enable,寫使能, 在寫取資料之前,要先使WE#有效;
ALE:Address Latch Enable,地址鎖存使能,在輸入地址之前,要先在模式暫存器中,設定ALE使能;
CLE:Command Latch Enable,命令鎖存使能,在輸入命令之前,要先在模式暫存器中,設定CLE使能;PS:當ALE和CLE都不使能的時候表示當前傳輸的是資料;
CE#:Chip Enable,片選使能,在操作Nand Flash之前,要先選中此晶片,才能操作;
RE#:Read Enable,讀使能,在讀取資料之前,要先使CE#有效;
R/B#:Ready/Busy Output,就緒/忙,主要用於在傳送完程式設計/擦除命令後,檢測這些操作是否完成,忙,表示程式設計/擦除操作仍在進行中,就緒表示操作完成;
S3C2440中NFCONF中三個比較重要的引數:
TACLS、TWRPH0、TWRPH1:S3C的資料手冊如下:
如上圖可猜測:
TACLS為CLE/ALE使能至nFRE/nFWE使能之間的時間段;TACLS設值範圍0-3,持續時間的公式為TACLS*HCLK
TWRPH0為nFRE/nFWE使能的時間段;TWRPH0設值範圍0-7,持續時間的公式為(TWRPH0+1)*HCLK
TWRPH1為nFRE/nFWE不使能至CLE/ALE不使能的時間段;TWRPH1設值範圍0-7,持續時間的公式為(TWRPH1+1)*HCLK
查閱NAND FLASH的資料手冊:
觀察時序圖以及下圖可以發現:
TACLS:對應於nand flash手冊中時序圖(tCLS-tWP)和(tALS-tWP)這兩個值中的較小的那個。12ns-12ns=0。所以TACLS可設定為0。
TWRPH0:對應於nand flash手冊中時序圖tWP和tRP這兩個值中的較小的那個。(tRP也是12ns,未截圖)。12ns。假設HCLK為100Mhz,根據公式(TWRPH0+1)*HCLK=12ns,可算得TWRPH0=1.2=2。
TWRPH1:對應於nand flash手冊中時序圖tCLH和tALH這兩個值中的較小的那個。同上。
關於S3C中對NAND FLASH操作的暫存器:
nfconf ;0x4E000000
nfcont ;
nfcmd ;
nfaddr ;
nfdata ;
nfeccd0 ;
nfeccd1 ;
nfeccd ;
nfstat ;
nfestat0;
nfestat1;
nfmecc0 ;
nfmecc1 ;
nfsecc ;
nfsblk ;
nfeblk ;
關於NAND FLASH驅動的基本框架:
基本的結構體:
struct nand_chip、struct mtd_info、struct mtd_partition
nand_chip結構體中需要滿足的結構體成員:
select_chip //為片選NAND FLASH的操作函式
cmd_ctrl//為傳送命令或者地址的操作函式(把資料放入CMD暫存器還是ADD暫存器)
IO_ADDR_R //為讀資料的暫存器
IO_ADDR_W//為寫資料的暫存器
dev_ready//為檢測nand flash是否忙的函式
ecc.mode//為是否ECC校驗的標誌位如NAND_ECC_SOFT或者NAND_ECC_NONE等
mtd_info結構體中需要滿足的結構體成員:
owner //THIS_MODULE;
priv = s3c_nand;//指向nand_chip的結構體,用於nand_scan識別nand flash用。
識別之後註冊分割槽add_mtd_partitions函式。(反註冊函式del_mtd_partitions)。
PS:過程中需要使能NAND FLASH控制器的時鐘,使用函式clk_get、clk_enable。
以上完成了nand flash塊裝置的初始化,其中呼叫的函式中肯定呼叫了一開始說的那些函式,底層裝置的初始化都會一步步呼叫到上層的函式,因為初始化完成之後就可以用應用程式對其訪問。
NOR FLASH:
上圖可得其資料位有16位,地址位有22位除去兩位NC為22位,2^20=1024*1024,由資料位為16位可得,總共容量有2Mb(這樣我們也大概清楚為什麼nand不用這樣的匯流排定址了,因為容量太大線太多了)。
關於為什麼是LADDR1接A0而不是LADDR0接,是因為S3C2440每個地址的容量為一個位元組而非此NOR中兩個位元組,為了讓這樣一倍的差距對應起來,如果ARM程式中匯流排的地址為0x2而對應NOR中的地址就是0x1,如果匯流排地址為0x3那麼NOR中還是0x1,因為0x2、0x3兩個地址的值都位於地址為0x1的16位寄存值中。
nor程式設計系統框架:
結構體:map_info、s3c_nor_parts
函式:
simple_map_init、do_map_probe、add_mtd_partitions
參考文章:
http://blog.csdn.net/juana1/article/details/6577556
http://funexploit.readthedocs.org/en/latest/sources/embeddedsystem.html