GNU ARM匯編--(十八)u-boot-采用nand_spl方式的啟動方法
%_config::unconfig
@$(MKCONFIG) -A $(@:_config=)
奇怪的就是在下面一點點有:
#########################################################################
## ARM1176 Systems
#########################################################################
smdk6400_noUSB_config
smdk6400_config :unconfig
@mkdir -p $(obj)include $(obj)board/samsung/smdk6400
@mkdir -p $(obj)nand_spl/board/samsung/smdk6400
@echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
@if [ -z "$(findstring smdk6400_noUSB_config,$@)" ]; then
echo "RAM_TEXT = 0x57e00000" >> $(obj)board/samsung/smdk6400/config.tmp;
else
echo "RAM_TEXT = 0xc7e00000" >> $(obj)board/samsung/smdk6400/config.tmp;
fi
@$(MKCONFIG) smdk6400 arm arm1176 smdk6400 samsung s3c64xx
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
當時看到這個覺得奇怪,在新版本的uboot中其他板子的配置都用%_config的目標,你丫的smdk6400憑什么單獨搞一個目標出來,好奇的去看下nand_spl目錄,并且make smdk6400_config和make看了下配置的過程和編譯的過程,當時初步搞清楚了這是個神馬情況:
在nand_spl目錄下有個nand_boot.c,從這個文件名看上去倒是與從nand啟動有關(guān)的,說到nand啟動方式我要插一句:因為我是在裝有ubuntu的破本子下進行GNU ARM匯編系列的學(xué)習(xí)的,因為是本子,所以沒有并口,沒有串口,只有搞個usb轉(zhuǎn)串口來用,用不起jlink這樣高級的玩意兒,因為是個破本子,win跑的不爽,干脆就跑linux了.所以我的板子里的nor flash我是一點都不敢動的,只能用nand flash,因此對nand flash啟動的過程還是比較熟悉的.那為什么s3c2440從nand flash啟動必須要用到內(nèi)部那4K大小的sram,按照datasheet的解釋是這樣的:從nand啟動時,一定要設(shè)置OM[0:1]這個撥碼開關(guān),將內(nèi)部的4K大小的sram映射到0x00000000處,因為arm啟動的時候都是從0x00000000開始的.而samsung的設(shè)計是在這種情況下nand中前4K大小的數(shù)據(jù)會由硬件load到sram中,這樣依靠這4Ksram就可以從nand啟動了.那為什么必須要這個4K的sram才可以做到nand啟動了,根據(jù)一些前輩的說法和自己的理解,主要原因有二:第一nand flash的操作是需要控制器的,而soc在啟動時,一條指令都沒來的及執(zhí)行,如何初始化控制器,控制器都沒有初始化,那么又如何拿的到nand flash上面的指令;第二nand flash本身只能頁讀,cpu從nand無法取到一條32bit的指令,另外對于跳轉(zhuǎn)指令,nand flash就傻眼了,nand flash沒辦法這樣隨機讀.
說是插一句話,不經(jīng)意插了一段,另起一段:
在nand_spl/board/samsung/smdk6400文件下有config.mk,Makefile和u-boot.lds三個文件,看看這三個文件再加上uboot根目錄下的makefile文件就可以大概明白nand_spl這種方式是如何實現(xiàn)的了:
在uboot根目錄下的makefile中有:
$(obj)u-boot-nand.bin:nand_spl $(obj)u-boot.bin
cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin
是將兩個bin檔用這種方式合并成一個bin檔!!!
老實說,在做自己的bootloader的時候我也有這種想法,沒想到在自己動手移植uboot的時候就發(fā)現(xiàn)新的uboot也采用了這種方式,有點小得意,^_^
更具體點說,就是在nand_spl目錄下的u-boot-spl.bin做了以下事情:
1.設(shè)置cpu為svc模式
2.關(guān)閉開門狗和中斷
3.初始化系統(tǒng)時鐘
4.禁用MMU和Cache
5.初始化sdram控制器
6.設(shè)置sp,跳到剛才提到的nand_boot.c里面的nand_boot函數(shù),這個函數(shù)初始化nand的控制器,并將4K之后的u-boot.bin image從nand中l(wèi)oad到sdram中,然后跳轉(zhuǎn)到u-boot.bin image的開始處繼續(xù)后續(xù)的工作
為了實現(xiàn)這個u-boot-spl-16k.bin,可以照下列的步驟實施:
1.在uboot根目錄下的makefile中新增一個目標:
######################################################################
#TQ2440 by Baikal
######################################################################
TQ2440_config: unconfig
@echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
#echo "RAM_TEXT = 0x33000000" > $(obj)board/samsung/TQ2400/config.tmp;
@$(MKCONFIG) TQ2440 arm arm920t - samsung s3c24x0
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
2.在nand_spl/board/samsung下新建文件夾TQ2440,可以將smdk6400目錄下的三個文件復(fù)制過來再慢慢修改,最大的修改就是makefile的改動:
start.S用的是arch/arm/cpu/arm920t/start.S
lowlevel_init.S用的是board/samsung/smdk2410/lowlevel_init.S
nand_boot.c用的是nand_spl/nand_boot.c
s3c2440_nand.c用的是drivers/mtd/nand/s3c2440_nand.c
3.移植s3c2440_nand的代碼
4.根據(jù)具體情況在start.S中將部分代碼用#ifdef CONFIG_NAND_SPL或者#ifndef CONFIG_NAND_SPL包起來
5.最后的編譯鏈接過程是鏈接出一個u-boot-spl文件,從u-boot-spl文件中剝離出二進制數(shù)據(jù)文件u-boot-spl.bin,實際上這個bin檔才1.2k左右,將其填充到4K大小
如果對bootloader有一定理解,并且熟悉編譯鏈接和makefile等腳本的話,單單這個工作量不大,忘記了還要熟悉nand flash的控制.
最后,說一下我在這個過程中遇到一個耽誤了我好久的一個問題,忘記在跳nand_boot.c也要設(shè)置sp.因為只能通過led來調(diào)試,看到的現(xiàn)象讓我錯誤的以為是我的nand flash驅(qū)動沒調(diào)對.最后才恍然明了.當時看那幾個led也是看的煩躁了....
just go on,戒躁
評論