uboot整個移植過程我們可以分為三個階段: 一,移植可以從Nor flash啟動的uboot 這個階段是移植一個最簡單的uboot,可以燒在Nor flash內運行. 二,移植支援Nand flash驅動的uboot 加入Nand flash驅動的支援,可以在uboot命令列下操作Nand flash.但還未能從Nand flash啟動,只能在Nor flash內運行. 三,移植可以從Nor flash啟動的uboot 可以燒錄在Nand flash,並設定從Nand flash啟動運行uboot.分三個階段進行移植,可以對整個uboot的移植過程及原理更加清晰明了,同時降低了發現問題時解決問題的困難度和解決範圍. 首先介紹移植可以從Nor flash啟動的uboot. 這個階段相對簡單一點,是移植一個最簡單的uboot,可以燒在Nor flash內運行.不需要修改太多的東西。步驟如下:測試一下預設的smdk2410_config配置能否在你的板子上正常運行 1.編譯uboot1.1.4
#make smdk2410_config #make ARCH=arm
|
註:編譯針對arm的平台時,uboot預設使用arm-linux-gcc編譯,若交叉編譯器名字不一樣,需要自行在Makefile裡修改。 會出現兩個錯誤.錯誤資訊一: cc1: Invalid option `abi=apcs-gnu' make[1]: *** [hello_world.o] Error 1 make[1]: Leaving directory `/root/u-boot-1.1.4/examples' make: *** [examples] Error 2 解決辦法: 出錯的檔案是/cpu/arm920t/下的config.mk: 將 PLATform_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) 改成: PLATform_CPPFLAGS +=$(call cc-option,-mapcs-32,$(call cc-option,-mabi=apcs-gnu,)) 錯誤資訊二: make[1]: *** No rule to make target `hello_world.srec', needed by `all'. Stop. make[1]: Leaving directory `/work/src/u-boot-1.1.4/examples' 解決方案: 開啟 examples/Makefile
把example檔案夾下的Makefile中的 第126行 %.srec: % 改成 %.srec: %.o 第129行的
%.bin: % 改成 %.bin: %.o 2.若編譯成功,則會在uboot源碼下產生u-boot.bin檔案。將這個檔案燒錄到nor flash。 注意: 預設u-boot的smdk2410_config是不支援nandflash的,只能在nor flash內運行,所以只能燒錄到nor flash內運行。如果燒錄到nandflash下是不能啟動並執行。 3.參考開發板資料,設定好跳線,從nor flash啟動。 啟動資訊如下:
U-Boot 1.1.4 (Dec 30 2007 - 23:25:02) U-Boot code: 33F80000 -> 33F9696C BSS: -> 33F9AC58 RAM Configuration: Bank #0: 30000000 64 MB *** Warning - bad CRC, using default environment Flash: 512 kB In: serial Out: serial Err: serial
|
發現有3個問題: 1) 啟動時開發板蜂鳴器一直在響。 懷疑是我的開發板蜂鳴器對應的GPIO口和smdk2410的GPIO口地址不對應,從而導致啟動時誤賦了值,一直在響。 2) Warning - bad CRC, using default environment 這個問題是因為第一次使用uboot時沒有設定過變數,設定儲存一下就不會在出現了。 3) Flash: 512 kB 我的板子Nor flash是1MB的,而這裡顯示512KB 4.下面進行uboot源碼修改 這裡主要根據開發板硬體的實際情況,基於smdk2410的源碼進行修改(主要是設定檔include/configs/smdk2410.h),並解決如上碰到的問題1和3。若對硬體板子的情況不是太瞭解,可以參考2410的datasheet以及開發板供應商提供的硬體資料。 從我開發板uboot第一次啟動的情況來看,問題不是太大。 首先修改include/configs/smdk2410.h。裡麵包含了很多對目標板設定的宏。smdk2410.h的內容和要修改的地方如下:
#define CONFIG_BOOTDELAY 3 /*#define CONFIG_BOOTARGS "root=ramfs devfs=mount console=ttySA0,9600" */ #define CONFIG_ETHADDR 08:00:3e:26:0a:5b #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 192.168.1.103 #define CONFIG_SERVERIP 192.168.1.102 #define CONFIG_BOOTFILE "uImage" #define CONFIG_BOOTCOMMAND "tftp 30000000 uImage\; bootm 30000000" //這是bootdelay後啟動並執行命令 //這些宏對應與uboot的變數,即在uboot命令列下執行printenv列印出的變數。可以在這裡設定(定義為預設值),也可以在uboot啟動後通過setenv命令設定。
#define CFG_PROMPT "ARMSYS2410 # " /* Monitor Command Prompt */ #define CFG_LOAD_ADDR 0x33000000 /* default load address */ #define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ #define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */ #define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
|
解決問題3: 將 #define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */ #if 0 #define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */ #endif 改為: #define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */ #if 0 #define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */ #endif 注意如下兩個地方: #ifdef CONFIG_AMD_LV800 #define PHYS_FLASH_SIZE 0x00100000 /* 1MB */ 這裡解決了u-boot啟動時的問題3即Nor Flash大小為512 kB ,是因為沒有選擇正確的Nor flash型號。 #define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */ #define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */ 宏CFG_ENV_ADDR定義了存放uboot變數的地址,換算一下為1MB-64KB=960KB地方,而實際uboot編譯出來的大小僅為120KB左右,由此可以得出,即使從新燒錄了新編譯的uboot到Nor flash內,也不會影響先前設定使用的uboot變數。 #endif註:可以在u-boot的README裡查到這些部分宏的作用 5.解決蜂鳴器一直響問題 查看ARMSYS2410-B底板電路圖,在Reset Singal模組裡可以看到蜂鳴器(BUZZER)控制口串連到TOUT1引腳,並且低電平響。如下: 由s3c2410 Datasheet知道TOUT1複用了GPB1口。因此,只要在uboot啟動時給GPBDAT寄存器適當賦值,關閉BUZZER就可以了。修改smdk2410.c #vi board/smdk2410/smdk2410.c 找到board_init()函數 在gpio->GPBUP = 0x000007FF;下面 添加如下內容:
/*******stop beep******/ gpio->GPBDAT &= ~0x00000002; //Open BUZZER delay (5000000); //BUZZER Delay Time gpio->GPBDAT |= 0x00000002;
|
6.重新編譯 #make clean #make ARCH=arm 7.燒錄u-boot.bin到nor flash 啟動資訊: U-Boot 1.1.4 (Jan 3 2008 - 23:11:07)U-Boot code: 33F80000 -> 33F96DC4 BSS: -> 33F9B0E8 RAM Configuration: Bank #0: 30000000 64 MB Flash: 1 MB In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 ARMSYS2410 # uboot移植記錄之二 移植可以從Nor flash啟動的uboot請參考uboot移植系列的《uboot移植記錄之一》 http://blog.chinaunix.net/u2/60011/showart.php?id=1005057 下面介紹移植支援Nand flash驅動的uboot. 加入Nand flash驅動的支援,可以在uboot命令列下操作Nand flash.但還未能從Nand flash啟動,只能在Nor flash內運行.支援從Nandflash啟動會在下節介紹。 下面描述詳細步驟: 1. 開啟Nandflash驅動支援 要使uboot支援nand驅動,需要在smdk2410.h中將CFG_CMD_NAND部分注釋取消,開啟nandflash功能。 修改如下: /* include/configs/smdk2410.h */ #define CONFIG_COMMANDS \ (CONFIG_CMD_DFL | \ CFG_CMD_CACHE | \ CFG_CMD_NAND | \ /*CFG_CMD_EEPROM |*/ \ /*CFG_CMD_I2C |*/ \ /*CFG_CMD_USB |*/ \ CFG_CMD_REGINFO | \ CFG_CMD_DATE | \ CFG_CMD_ELF) 2. 添加nand_init()函數 Uboot對SMDK2410板的NAND Flash初始化部分沒有寫 即在lib_arm/board.c中的start_armboot函數中有這麼一句: #if (CONFIG_COMMANDS & CFG_CMD_NAND) puts ("NAND:"); nand_init(); /* go init the NAND */ #endif 因為前面開啟了CFG_CMD_NAND這個宏,uboot編譯時間會去查詢nand_init()這個函數。而在board/smdk2410目錄下任何源檔案中都沒有定義nand_init這個函數。所以需要我們補充這個函數以及這個函數涉及的底層操作。這裡我們可以參考VCMA9板的nand_init函數,VCMA9板是一款用S3C2410的板子,因此這部分操作和SMDK2410 Demo Board很相似。大部分代碼可以照搬。 分析VCM9板的nand_init()函數,發現需要拷貝如下內容: 首先將board/mpl/vcma9/vcma9.h中下面代碼拷貝到common/cmd_nand.c中do_nand函數前面。 /* dongas - support nand driver */ #if (CONFIG_COMMANDS & CFG_CMD_NAND) typedef enum { NFCE_LOW, NFCE_HIGH } NFCE_STATE; static inline void NF_Conf(u16 conf) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCONF = conf; } static inline void NF_Cmd(u8 cmd) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCMD = cmd; } static inline void NF_CmdW(u8 cmd) { NF_Cmd(cmd); udelay(1); } static inline void NF_Addr(u8 addr) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFADDR = addr; } static inline void NF_SetCE(NFCE_STATE s) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); switch (s) { case NFCE_LOW: nand->NFCONF &= ~(111); break; case NFCE_HIGH: nand->NFCONF |= (111); break; } } static inline void NF_WaitRB(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); while (!(nand->NFSTAT & (10))); } static inline void NF_Write(u8 data) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFDATA = data; } static inline u8 NF_Read(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); return(nand->NFDATA); } static inline void NF_Init_ECC(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCONF |= (112); } static inline u32 NF_Read_ECC(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); return(nand->NFECC); } #endif /* dongas - support nand driver - end */ 再接著將board/mpl/vcma9/vcma9.c中下面代碼拷貝到common/cmd_nand.c中來。 /* dongas - support nand driver */ /* * NAND flash initialization. */ #if (CONFIG_COMMANDS & CFG_CMD_NAND) extern ulong nand_probe(ulong physadr); static inline void NF_Reset(void) { int i; NF_SetCE(NFCE_LOW); NF_Cmd(0xFF); /* reset command */ for(i = 0; i 10; i++); /* tWB = 100ns. */ NF_WaitRB(); /* wait 200~500us; */ NF_SetCE(NFCE_HIGH); } static inline void NF_Init(void) { #if 0 /* a little bit too optimistic */ #define TACLS 0 #define TWRPH0 3 #define TWRPH1 0 #else #define TACLS 0 #define TWRPH0 4 #define TWRPH1 2 #endif NF_Conf((115)|(014)|(013)|(112)|(111)|(TACLS8)|(TWRPH04)|(TWRPH10)); /*nand->NFCONF = (1 /* 1 1 1 1, 1 xxx, r xxx, r xxx */ /* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */ NF_Reset(); } void nand_init(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); NF_Init(); #ifdef DEBUG printf("NAND flash probing at 0x%.8lX\n", (ulong)nand); #endif printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20); } #endif /* dongas - support nand driver - end */ 另外還要在cmd_nand.c前面加上#include ,否則編譯時間會出現ERROR: "S3C2410_NAND" Undeclared錯誤! 最後將include/configs/VCMA.9中下面代碼拷貝到include/configs/smdk2410.h中來。 /* dongas - support nand driver */ /*----------------------------------------------------------------------- * NAND flash settings */ #if (CONFIG_COMMANDS & CFG_CMD_NAND) #define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define SECTORSIZE 512 #define ADDR_COLUMN 1 #define ADDR_PAGE 2 #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 #define NAND_MAX_CHIPS 1 #define NAND_WAIT_READY(nand) NF_WaitRB() #define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH) #define NAND_ENABLE_CE(nand) NF_SetCE(NFCE_LOW) #define WRITE_NAND_COMMAND(d, adr) NF_Cmd(d) #define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d) #define WRITE_NAND_ADDRESS(d, adr) NF_Addr(d) #define WRITE_NAND(d, adr) NF_Write(d) #define READ_NAND(adr) NF_Read() /* the following functions are NOP's because S3C24X0 handles this in hardware */ #define NAND_CTL_CLRALE(nandptr) #define NAND_CTL_SETALE(nandptr) #define NAND_CTL_CLRCLE(nandptr) #define NAND_CTL_SETCLE(nandptr) #define CONFIG_MTD_NAND_VERIFY_WRITE 1 #define CONFIG_MTD_NAND_ECC_JFFS2 1 #endif /* CONFIG_COMMANDS & CFG_CMD_NAND */ /* dongas - support nand driver - end */ 3. 重新編譯uboot #make ARCH=arm 4. 測試加入Nand驅動支援的uboot 下面我們測試一下新編譯的帶Nand驅動支援的uboot是否有用。由於之前我們已經編譯了NOR版本的uboot並燒錄在nor flash中,這時我們無需重新燒錄新編譯的uboot到Nor Flash了。可以直接使用Nor裡的uboot提供的串口傳輸功能,將新編譯好的uboot(帶nand驅動支援)通過串口傳輸到sdram中測試,相比重新燒錄,這種方法高效率快捷得多。 傳輸的方法有兩種: 1) 使用loadb指令載入uboot.bin loadb指令使用kermit協議從串口下載二進位檔案到開發板的記憶體中,預設下載到0x33000000。當然你可以改在別的地址。 例如:loadb 30000000就是下載到0x30000000。 首先在uboot命令列模式下執行loadb指令 # loadb ## Ready for binary (kermit) download to 0x33000000 at 115200 bps... 然後選擇超級終端菜單上:傳送〉傳送檔案,檔案名稱選擇編譯好的U-Boot.bin,協議選擇Kermit發送,可以看到發送進度。 註:這裡使用secure CRT好象不行,沒發現其支援kermit協議,只能使用windows內建的超級終端或minicom 發送結束出現提示: ## Total Size = 0x00019a14 = 104980 Bytes ## Start Addr = 0x33000000 傳輸完後可以測試一下新編譯的uboot是否有用: ARMSYS2410 # go 30000000 註:go指令可以直接執行指定記憶體位址上的程式,例如剛下載到0x30000000的支援NAND驅動的uboot。 2)其實這裡也可以使用tftp協議將uboot下載到指定地址如0x30000000處,再用go指令執行。效果一樣,相比上一種這種方法更快捷,前提是網路 功能可用。當然,因為我的板子使用的是CS8900網卡,預設smdk2410就是支援的,所以直接可以使用。(tftp的用法請參考相關資料) #tftpboot 30000000 u-boot.bin #go 30000000 執行go指令啟動sdram中的uboot後,若出現了“NAND: 64MB”這一行,那麼恭喜你,基本上可以確定你的Nand驅動移植已經成功了。 我的啟動資訊如下: ARMSYS2410 # go 30000000 ## Starting application at 0x30000000 ... U-Boot 1.1.4 (Jan 9 2008 - 00:08:10) U-Boot code: 33F80000 -> 33F9A04C BSS: -> 33F9E3E8 RAM Configuration: Bank #0: 30000000 64 MB Flash: 1 MB NAND: 64 MB ------------- 多了這一行! Happying! In: serial Out: serial Err: serial Hit any key to stop autoboot: 0 ARMSYS2410 nand# 確認一下,輸入help,發現比先前NOR版本的U-Boot多了一組nand命令! #help mw - memory write (fill) nand - NAND sub-system --------- 新增加的Nand命令 nboot - boot from NAND device …… help nand可以看到更詳細的命令說明: ARMSYS2410 nand# help nand nand info - show available NAND devices nand device [dev] - show or set current device nand read[.jffs2[s]] addr off size nand write[.jffs2] addr off size - read/write `size' bytes starting at offset `off' to/from memory address `addr' nand erase [clean] [off size] - erase `size' bytes from offset `off 利用這些命令可以對Nandflash進行讀寫操作! 輸入nand info可以查看NandFlash型片的資訊: ARMSYS2410 # nand info Device 0: Samsung unknown 64Mb at 0x4e000000 (64 MB, 16 kB sector) 說明我們的Nand驅動移植成功了。(這裡Nand型號顯示為unknown沒關係,預設的也可以使用) 是因為uboot的nand列表裡沒有K9S1208 64MB,可以自己添加, 加入NAND快閃記憶體晶片型號 在/include/linux/mtd/ nand_ids.h中對如下結構體賦值進行修改: static struct nand_flash_dev nand_flash_ids[] = { ...... {"Samsung K9F1208U0B", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000, 0}, ....... } 這樣對於該款NAND快閃記憶體晶片的操作才能正確執行。當然不添加也沒關係,使用預設參數操作NAND也可以。 測試成功後我們將新編好的帶Nand驅動支援的uboot燒錄到Nor中。 這裡也不需要使用工具燒錄,用uboot提供的cp命令就可以將自身拷貝到Nor flash了。強大吧,呵呵~ 比sjflash燒快多了,uboot既然提供了這麼多好的功能,如果不用就太可惜啦!:) 1) 先看看NOR Flash的情況: ARMSYS2410 nand# flinfo Bank # 1: AMD: 1x Amd29LV800BB (8Mbit) Size: 1 MB in 19 Sectors Sector Start Addresses: 00000000 (RO) 00004000 (RO) 00006000 (RO) 00008000 (RO) 00010000 (RO) 00020000 00030000 00040000 00050000 00060000 00070000 00080000 00090000 000A0000 000B0000 000C0000 000D0000 000E0000 000F0000 (RO) 一共有19個sector,其中前5個總計128kb的sector有U-Boot程式,是防寫保護的(RO)。要燒寫首先要去掉防寫保護: 註:flinfo命令的作用是顯示當前flash(nor)的資訊 2) 去掉前5個sector的防寫保護,大小為128KB,足夠容納我們的uboot了。 ARMSYS2410 # protect off 0 1ffff Un-Protected 5 sectors 3) 再查看一下: ARMSYS2410 nand# flinfo Bank # 1: AMD: 1x Amd29LV800BB (8Mbit) Size%