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