本文中CONFIG_COMMANDS & CFG_CMD_NAND) (CFG_NAND_LEGACY)有錯。
loadb 20000000 //(1)
nand erase 0x100000 0x200000 //(2)
nand write 0x20000000 0x100000 0x200000 -//(3)
nand read 0x20000000 0x100000 0x200000 -//(4)
tftp 0x80200000(記憶體位址) uImage
過程 從伺服器 到記憶體 從記憶體在到Nand flash
為什麼呢 因為 nandflash 的擦出 讀寫不獨立 萬一一邊擦好了 可網路斷了 那就麻煩了 呵呵 通過記憶體中轉 好主意阿 速度起碼快把 呵呵
(1) 從串口下載到SDRAM的0x20000000處
(2) 從1M處開始擦寫Nand Flash,擦寫2M大小的空間
(3) 將SDRAM中的0x20000000處開始的內容,燒寫到Nand Flash的0x100000處開始的2M空間內
(4) 將Nand Flash的0x100000處開始的2M空間內容,拷貝到SDRAM中0x20000000處開始的地方
Nand flash晶片工作原理
------------------------------------
Nand flash晶片型號為Samsung K9F1208U0B,資料存放區容量為64MB,採用塊頁式儲存管理。8個I/O
引腳充當資料、地址、命令的複用連接埠。
晶片內部儲存布局及儲存操作特點:
一片Nand flash為一個裝置(device), 其資料存放區分層為:
1 (Device) = 4096 (Blocks)
1 (Block) -= 32 (Pages/Rows) 頁與行是相同的意思,叫法不一樣
1 (Page) = 528 (Bytes) = 資料區塊大小(512Bytes) + OOB 塊大小(16Bytes)
在每一頁中,最後16個位元組(又稱OOB)用於Nand Flash命令執行完後設定狀態用,剩餘512個位元組又
分為前半部分和後半部分。可以通過Nand Flash命令00h/01h/50h分別對前半部、後半部、OOB進行定位通過
Nand Flash內建的指標指向各自的首地址。
儲存操作特點:
1. 擦除操作的最小單位是塊。
2. Nand Flash晶片每一位(bit)只能從1變為0,而不能從0變為1,所以在對其進行寫入操作之前要一定將相應塊擦除(擦除即是將相應塊得位全部變為1).
3. OOB部分的第六位元組(即517位元組)標誌是否是壞塊,如果不是壞塊該值為FF,否則為壞塊。
4. 除OOB第六位元組外,通常至少把OOB的前3個位元組存放Nand Flash硬體ECC碼
------------------------------------
下面對nand flash的初始化代碼nand_init()進行分析:
1. 如果定義(CONFIG_COMMANDS & CFG_CMD_NAND)沒定義(CFG_NAND_LEGACY) 則start_armboot()調用driver/nand/nand.c中的nand_init(),否則如果定義(CONFIG_COMMANDS & CFG_CMD_NAND)並且有定義了CFG_NAND_LEGACY,則調用自己定義的nand_init()。在我當前的情景中是使用 driver/nand/nand.c中的nand_init()。
2.nand_init()調用本檔案中的nand_init_chip()對nand進行初始化。
3.nand_init_chip()首先調用board_nand_init()。
4.board_nand_init()是需要自己添加的函數,這個函數的主要功能是對struct nand_chip結構體的函數指標賦值,讓它們指向自己為nand驅動編寫的一些函數,對未賦值的指標,uboot會在後面為其賦上通用nand驅動函數指標。
5.nand_init_chip()接著調用nand_scan().
6.nand_scan()定義在drivers/nand/nand_base.c檔案中。它首先對struct nand_chip結構體中在board_nand_init()函數中未賦值的指標賦上通用nand驅動函數指標。
7. 通用nand驅動函數nand_select_chip()賦值給struct nand_chip結構體的函數指標用於開啟或關閉nand晶片,0為開啟,1為關閉。在這個函數中會調用nand_chip結構體中的 hwcontrol函數指標,這個指標指向的函數是需要自己編寫的。這個函數指標在board_nand_init()函數中被賦值。主要作用是向 nand flash發送一些nand flash開啟與關閉命令。
8.nand_scan()剩餘部分初始化nand_chip和mtd_info結構體。
9.nand_scan()最後在返回時調用drivers/nand/nand_bbt.c檔案中的nand_default_bbt()。
10.nand_default_bby()選擇一個壞塊描述表,返回時調用本檔案中的nand_scan_bbt()。
11.nand_scan_bbt()尋找建立一個壞塊描述表。
12.最後返回到nand_init(),這樣nand驅動的初始化完成了。
下面對命令nand read addr ofs size的執行流程進行分析:
1.nand read addr ofs size命令的作用是從nand flash地址的位移量ofs處讀取長度為size位元組的資料存放區到記憶體位址addr處。
2.common/main.c檔案中的main_loop()主要執行read_line()讀取命令列。
3.read_line()讀取到命令列後會調用common/main.c檔案中的run_command()。
4.run_command() 調用common/command.c檔案中的find_cmd()在.u_boot_cmd段中尋找該命令的cmd_tbl_t結構,找到後返回該結 構。該命令的結構是通過定義在include/command.h中的宏定義U_BOOT_CMD登記進.u_boot_cmd段中的。
5.run_command()找到該命令的cmd_tbl_t結構後則執行該命令對應的函數。對於本情景是nand命令對應的函數do_nand()。
6.do_nand() 有兩個版本,一個是定義了CFG_NAND_LEGACY。另一個是未定義CFG_NAND_LEGACY。這兩個版本都定義在 common/cmd_nand.c檔案中。對於本情景使用未定義CFG_NAND_LEGACY的do_nand()函數。要使用do_nand()還 必須定義宏CONFIG_COMMANDS&CFG_CMD_NAND。(若未定義CFG_NAND_LEGACY則在這個情景中的 do_nand()函數調用的函數都定義在drivers/nand_legacy/nand_legacy.c檔案中)。
7.對於我們的情景do_nand()會調用定義在include/nand.h檔案中的nand_read()。
8.nand_read()則調用本nand晶片對應的nand_info_t結構的read指標。而read指標在nand_scan()中被指向了同檔案(drivers/nand/nand_base.c)中的nand_read()函數。
9.nand_read()函數最終會調用nand_chip結構中的cmdfunc指標,通過這個指標指向的函數向nand flash晶片發送命令。最終完成整個命令的執行。