上節S3C2440移植uboot之支持NAND啓動修改了代碼支持了NAND啓動。這節我們分析uboo使其支持NORFLASH的操作。
1.分析啓動錯誤
上一節啓動uboot出現如下所示,我們搜索下錯誤代碼Flash:
上面的Flash: *** failed ***
是屬於uboot第二階段函數board_init_r()裏的代碼, 代碼如下所示(位於arch/arm/lib/board.c):
/*第二階段*/
void board_init_r(gd_t *id, ulong dest_addr) //gd uboot重定位地址
{
... ...
puts("Flash: "); //打印flash:
flash_size = flash_init(); //初始化nor_flash
if (flash_size > 0)
{
... ...
print_size(flash_size, "\n"); //打印nor_flash的大小
}
else
{
puts(failed); //打印數組failed[]="*** failed ***\n";
hang(); //進入while中,並打印: ### ERROR ### Please RESET the board ###
}
#if defined(CONFIG_CMD_NAND)
puts("NAND: "); //打印NAND:
nand_init(); //初始化nand_flah
... ...
}
從上面代碼看出, board_init_r()會來初始化nor,由於新的uboot不支持nor,所以flash_init()初始失敗,然後打印一串錯誤代碼後,等待復位.
由於2440在nand啓動時,會自動裝載nand的前4k內容,所以不支持norflash,因爲nor的前4k內容被nand佔用.
2.修改代碼
所以修改上面代碼,避免nand啓動一直卡住,將:
else
{
puts(failed); //打印數組failed[]="*** failed ***\n";
hang(); //進入while中,並打印: ### ERROR ### Please RESET the board ###
}
改爲:
else
{
puts("0 KB\r\n"); //打印0 KB
}
在u-boot-2012.04.01\drivers\mtd\cfi_flash.c文件中增加定義
#define _DEBUG 1
#define DEBUG //調試模式
打印如下調試信息
然後使用nor啓動新的uboot,打印出調試信息:
打印出norflash的廠家ID=0xC2,設備ID=0x2249,顯然uboot匹配讀出的ID沒有成功.
搜索JEDEC PROBE字段,找到位於board_init_r()->flash_init()->flash_detect_legacy():
如上圖所示,該函數會進入board_init_r()->flash_init()->flash_detect_legacy()->jedec_flash_match(),裏面會通過兩個ID來匹配jedec_table[].
3.在匹配數組中添加我們的NORFLASH
接下來向jedec_table[]裏添加norflash:MT29LV160DB(位於drivers/mtd/jedec_flash.c)
參考手冊如下
修改後代碼如下:
/*MX29LV160DB*/
{
.mfr_id = (u16)MX_MANUFACT, //廠家ID0x00C200C2 (讀nor,便是0xc2)
.dev_id = 0x2249, //設備ID
.name = "MXIC MX29LV160DB",
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA /* 數組[1]表示是16位nor,解鎖地址爲:0x555,0x2AA */
},
.DevSize = SIZE_2MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 4, //4種不同的扇區規格
.regions = {
ERASEINFO(16*1024, 1),
ERASEINFO(8*1024, 2),
ERASEINFO(32*1024, 1),
ERASEINFO(64*1024, 31),
}
},
重新燒寫看打印信息,出現這麼一段ERROR:
ERROR:too many flash sectors
說flash的扇區太多了,搜索找到位於drivers/mtd/jedec_flash.c中:
顯然是CONFIG_SYS_MAX_FLASH_SECT宏小於我們flash的扇區,所以打印ERROR。
所以修改CONFIG_SYS_MAX_FLASH_SECT宏定義(位於include/configs/smdk2440.h),並去掉之前定義的DEBUG調試宏(位於include/common.h)
4.然後重新燒寫
輸入flinfo命令(flash info),就能查看flash的信息了:
然後通過uboot命令,檢測nor的讀寫是否正確:
查看內容
往內存寫數據
5.解決棧設置錯誤的問題
拷貝的數據和源數據內容不同,可能是我們的棧設置有問題。
(關於內存分佈可以看這個圖)內存分佈
由於之前重定位,清除bss之後棧一直指向30000000的位置,每調用一個函數棧應該會變化。由於我們的設置問題,導致棧一直卡在30000000的位置,所以拷貝數據後再比較源數據和目的數據就會出錯。
修改start.s啓動文件
call_board_init_f:
/*注意這裏 ,把聲明放文件開頭編譯會報錯。只能放這裏*/
.globl base_sp
base_sp:
.long 0
ldr r0,=0x00000000
bl board_init_f
/*unsigned int id 的值存在r0中,正好給board_init_r使用*/
ldr r1, =_TEXT_BASE
/*重新設置棧到之前的位置 指向原來addr_sp += 128;*/
ldr sp,base_sp
/*調用第二階段代碼*/
bl board_init_r
在board.c中將之前的棧的地址傳回來
重新燒寫
重新嘗試拷貝數據沒有問題。
現在我們的NORFLASH就支持了NOR的操作。