移植uboot第四步:设置NAND启动
寫在前面:
我的博客已遷移至自建服務器:博客傳送門,CSDN博客暫時停止,如有機器學習方面的興趣,歡迎來看一看。
此外目前我在gitHub上準備一些李航的《統計學習方法》的實現算法,目標將書內算法全部手打實現,歡迎參觀并打星。GitHib傳送門
正文
移植的uboot使用NOR啟動,不支持NAND,這次就是修改代碼以支持NAND。
之前uboot的Makefile里面有-pie,前面寫到了,這是為了生成位置無關碼,代碼可以copy到任何地方。因為代碼段里面是有變量的,程序去讀取變量的時候要知道變量的存放地址,你移到別的地方,變量的存儲位置肯定會變。位置無關就是額外在一塊內存區域中存放變量的地址信息,當移動代碼的時候,要去讀取這塊區域,重新修改變量的讀取地址。
1.去掉“pie選項”。
設置NAND啟動的時候,cpu會自動從NAND里面讀取4k代碼到片內內存,所以設置pie的話,代碼的體積會比較大,不利于復制到片內內存,重定位之前的代碼應該少于4k。
現在不清楚這個pie在哪,所以命令:grep "\-pie" * -R,返回
看起來第二個比較像,所以打開第二個文件:
vi arch/arm/config.mk找到LDFLAGS_u-boot += -pie,前面加上#注釋掉,保存退出。這樣應該把pie選項去掉了,實際等make完以后,看看鏈接文件就能知道了。
2.添加NAND代碼。之前寫過NAND的代碼,直接將文件init放到\board\samsung\smdk2440
將這個文件添加到SI工程里。找到start.S,一路往下看,設置時鐘之后是板子片內各種資源的初始化,我把NAND的代碼放到時鐘和資源初始化中間。
a.要做一些修改,因為調用了C函數,要設置棧,下面板子資源初始化也調用了C,直接將它的棧設置拿過來
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) bic sp, sp, #7 /* 8-byte alignment for ABI compliance */然后跳轉到nand_init初始化nand。uboot里面有很多nand_init重名函數,將其修改為nand_init_ll。其他不用修改。
b.調用copy_code_to_sdram的時候有三個參數,第一個是0不變,第二個是代碼的初始位置。之前寫了_start,但是這是一條偽匯編指令,如果_start這個值很復雜,編譯的時候可能把這個值放到別的合適的位置,就可能不在4k以內了,cpu復制4k到片內內存以后,可能就沒有復制_start這個值,程序執行的時候就懵逼了,要代碼重定位,找不到第二個參數了。所以為了保證在4k內,人為寫一個值(猜測這樣子這條代碼就不算偽匯編,保存的地址就可以保證在4K內)。實際上
兩種寫法意思是一樣的,只是擔心出問題。所以改為
ldr r1, _TEXT_BASE
_TEXT_BASE有定義:
_TEXT_BASE:.word CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_TEXT_BASE 0x0把CONFIG_SYS_TEXT_BASE 值改為0x33f00000
因為內存一共64M,就是34000000,在內存的頂部是uboot的存放空間,這里給uboot留了1M的空間,讓代碼copy進去。64M-1M=0x33f00000。
copy_code_to_sdram的第三個參數是copy的長度,查看start.S可以看到
_bss_start_ofs:.word __bss_start - _start__bss_段是存放初始值為0的變量,bss段的文件是不會存在在bin文件里面的,所以__bss_start - _start就是二進制文件的長度。copy的長度就寫為_bss_start_ofs。
copy_code_to_sdram文件內部查看以后發現不需要修改
clear_bss需要修改一些值。
源文件的bss段的結束地址定義為__bss_end,在這個uboot中為__bss_end__,修改即可。
因此匯編中的代碼段改為,同時去掉原先的clear_bss
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) bic sp, sp, #7 /* 8-byte alignment for ABI compliance */bl nand_init_llmov r0, #0//ldr r1, =_startldr r1, _TEXT_BASEldr r2, _bss_start_ofs;bl copy_code_to_sdrambl clear_bss同時clear_bss改為
void clear_bss (void) {extern int __bss_start, __bss_end__;int *p = &__bss_start;for (; p < &__bss_end__; p++)*p = 0; }c.去掉自帶的重定位代碼。
進入board_init_f函數,找到relocate_code(addr_sp, id, addr);注釋掉。
因為后面的代碼是在SDRAM,bl是相對跳轉指令,使用
這樣一下就從片內內存跳到SDRAM中了。
d.下面是調用第二階段的代碼。
/* 調用第二階段代碼 */bl board_init_r有兩個參數gd_t *gd, ulong dest_addr。ID和目的地址。目的地址就是程序的鏈接地址。
ldr r1, _TEXT_BASEID可以觀察到在board_init_f中有獲得,直接添加返回值為id。返回值存在r0,就省得我們再做別的事了。
e.差不多改完了,把init文件添加進uboot,
vi board/samsung/smdk2440/Makefile在COBJS := smdk2410.o這句話后面加上init.o
保存退出。
f.修改鏈接腳本,把Start.o init之類的文件放到代碼的最前頭,這樣能保證需要的代碼都在4k里。
vi arch/arm/cpu/u-boot.lds. = 0x00000000;. = ALIGN(4);.text :{__image_copy_start = .;CPUDIR/start.o (.text)*(.text)}將board/samsung/smdk2440/libsmdk2440.o (.text)添加進去變成:
. = ALIGN(4);.text :{__image_copy_start = .;CPUDIR/start.o (.text)board/samsung/smdk2440/libsmdk2440.o (.text)*(.text)}g:編譯,有一些錯誤,比如之前增加了board_init_f的返回值,原先是沒有的,改一下就行了。
h.燒到NAND,啟動,成功
總結
以上是生活随笔為你收集整理的移植uboot第四步:设置NAND启动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 移植uboot第三步:修改时钟
- 下一篇: 移植uboot第五步:支持NORFlas