根據朱有鵬老師課堂Uboot 2013.10版本移植到S5pv210開發板上第一階段

前期準備:

1.uboot下載地址 ftp://ftp.denx.de/pub/u-boot/

2.參照物開發板的選擇

我們開發板使用的CPUS5PV210,所以要找uboot中針對S5PV210或者S5PC110進行移植的作爲參考。根據規律,我們應該參考include/configs/s5p_goni.h,對應的boarduboot/board/samsung/goni這個目錄。

3.刪除無關文件和文件夾,其實不刪除也可以,但是刪除更好。

4.建立SI工程並預解析

 



 

(1)參照物開發板爲:55p_goni make s5p_goni_config

(2)配置對應的cpuboard文件夾分別爲:

cpu: u-boot-2013.10\arch\arm\cpu\armv7

board: u-boot-2013.10\board\samsung\goni

 

開始移植

1.添加交叉編譯工具鏈

  在主Makefile CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

2.配置,編譯,測試

(1)編譯過程:

make distclean

make s5p_goni_config

make

(2)結果:得到u-boot.bin即可

3.推薦linux下腳本燒入

 移植原來的版本的uboot中的sd_fusing文件夾到官方uboot版本中,使用這個文件夾中的sd_fusing.sh腳本來進行燒錄

4.燒入後,串口現象;

(1)串口接串口2,串口有輸出。但是這個串口輸出不是uboot輸出的,而是內部iROM中的BL0運行時輸出的。

(2)輸出錯誤信息分析:

第一個SD checksum Error:是第一順序啓動設備SD0iNand)啓動時校驗和失敗打印 出來的;

第二個SD checksum Error:是第二順序啓動設備SD2(外部SD卡)啓動時校驗和失敗 打印出來的;

剩下的是串口啓動和usb啓動的東西,可以不管。

總結:從兩個SD checksum Error,可以看出:外部SD卡校驗和失敗了。

分析:SD卡燒錄出錯了,導致SD卡校驗和會失敗。發現是mkbl1程序和start.S中前16個字節校驗和的處理上面不匹配造成的,解決方法是在start.S最前面加上16個字節的佔位。

 

5.上述問題的解決方法:

參考之前的start.S發現有16字節佔位。直接複製粘貼到本版本的start.S的相應位置。

\u-boot-2013.10\arch\arm\cpu\armv7\start.S  



重新編譯燒錄運行,發現結果只顯示一個SD checksum Error。這一個就是內部SD0通道inand啓動校驗和失敗打印出來的。剩下的沒有了說明外部SD卡校驗和成功了,只SD卡上的uboot是錯誤的,沒有串口輸出內容,所以沒有輸出了。

 

3.繼續分析start.S


(1)#define CONFIG_SYS_TEXT_BASE 0x34800000  可以看出我們的uboot連接地址是在0x34800000位置

(2)cpu_init_cp15這個函數功能是設置MMUcache等。這個版本的uboot中未使用虛擬地址,因此MMU在這裏直接關掉。

(3)cpu_init_crit,這個函數裏只有一句跳轉指令,短跳轉到lowlevel_init函數。

Lowleve_init 分析:

lowlevel_init函數在board/samsung/goni目錄下,主要作用是時鐘設置、串口設置、復位狀態判斷···這個函數是S5PC100S5PC110兩個CPU共用的。

經過瀏覽,發現lowlevel_init函數中做的有意義的事情有:關看門狗、調用uart_asm_init來初始化串口、並沒有做時鐘初始化(下面有時鐘初始化的函數,但是實際沒調用。如果uboot中沒有初始化時鐘,那麼時鐘就是iROM中初始化的那種配置)

 

7.添加開發板制鎖和串口打印字符"O"

(1)我們爲了調試uboot的第一階段,就要看到現象。爲了看到現象,我們向lowlevel_init函數中添加2個代碼,一個是開發板制鎖,在watchdog

// 我們添加的開發板供電制鎖的代碼

ldr r0, =0xE010E81C

ldr r1, =0x301

str r1, [r0]

一個是串口打印"O"在串口初始化最後

// 串口2輸出字符'O'

ldr r1, =0x4f4f4f4f

ldr r2, =0xE2900820

str r1, [r2] @'O'

 

(2)這兩段代碼可以直接從ARM裸機全集課程中的代碼中來。其實也可以從三星移植版本的uboot中來,但是因爲三星移植版本中用到了很多寄存器定義,涉及到頭文件的, 所以移植過來不方便。

(3)實踐添加。

實踐結果及分析

(1)實驗結果是:沒看到開發板制鎖,串口也沒有輸出任何東西。實驗失敗。

(2)結論:因爲開發板制鎖沒有成功,所以我們判定,在開發板制鎖代碼運行之前uboot 就已經掛掉了。下面就是去跟蹤代碼運行,然後判定問題點再去解決

 

8.添加LED點亮代碼跟蹤程序運行

(1)在基礎代碼階段,串口還沒有運行,串口調試工具還無法使用時,使用LED點亮的方式來調試程序就是一個有力的手段。

(2)有些情況下可以用Jlink等調試工具來調試這種基礎代碼。

(3)從程序的基本運行路徑端出發,隔一段給他添加一個LED點亮代碼,然後運行時根據現象來觀察,判定哪裏執行了哪裏沒執行。從而去定位問題。

(4)從以前的裸機代碼中組織出一個標準的LED點亮然後延時一段的一個標準代碼段:

ldr r0, =0x11111111

ldr r1, =0xE0200240

str r0, [r1]

ldr r0, =((1<<3) | (0<<4) | (1<<5)) // 1是滅,0是亮

ldr r1, =0xE0200244

str r0, [r1]

ldr r2, =9000000 //延時函數

ldr r3, =0x0

delay_loop:

sub r2, r2, #1

cmp r2, r3

bne delay_loop

(5)之前做實驗時發現一個現象:我們的uboot運行時按住電源開關時所有4LED都是亮的。所以我們做實驗時給LED點亮是看不到現象的,所以我們的代碼關鍵是要熄滅某些LED來判斷。

(6)我們將熄滅LED的函數在start.S中隔一段的關鍵部位放上1個,然後運行時通過觀察LED的點亮熄滅狀態,就知道程序運行到哪裏了。

(7)經過判斷我們發現:start.S中工作一切正常,但是函數一旦放到lowlevel_init.S中就完全不工作了。通過分析得出結論:b lowlevel_init這句代碼出了問題。

 

9.解決問題

(1)問題分析:跳轉代碼出了問題。分析問題出在代碼的連接上。

(2)三星S5PV210要求BL1大小爲8KB,因此uboot第一階段代碼必須在整個uboot鏡像的前8KB內,否則跳轉不到。

(3)對比三星移植版本的ubootu-boot.lds和官方版本uboot的連接腳本u-boot.lds(注意這兩個版本的uboot的連接腳本的位置是不同的),就發現lowlevel_init.S的代碼段沒有被放在前面。

(4)u-boot.ldsstart.o後面添加board/samsung/goni/lowlevel_init.o (.text*),這個就保證了lowlevel_init函數被連接到前面8kb中去。

 

 

(5)報錯,lowlevel_init重複定義了。

修改board/samsung/goni/Makefile解決編譯問題

(1)問題分析:爲什麼會重複定義。因爲lowlevel_init這個函數被連接時連接了2次。一次是board/samsung/goni這個目錄下生成libgoni.o時連接了1次,第2次是連接腳本最終在連接生成u-boot時又連接了一次,所以重複定義了。

(2)這個錯誤如何解決?思路是在libgoni.o中不要讓他連接進lowlevel_init,讓他只在最終連接u-boot時用1次,就可以避免重複定義。

(3)參考當前版本的ubootstart.S文件的處理技巧,解決了這個問題。

實踐驗證。

結果是開發板制鎖和串口輸出'O'都成功了

 

DDR初始化

分析下一步移植路線

(1)cpu_init_crit函數成功初始化串口、時鐘後,轉入_main函數,函數在arch/arm/lib/crt0.S文件中。

(2)crt0.S中首先設置棧,將sp指向DDR中的棧地址;然後調用board_init_f函數進行板級初始化。函數在arch/arm/lib/board.c中。

(3)在這個版本的uboot中,把以前uboot的第二階段start_armboot函數分成了2部分:board_init_fboard_init_r。所以在這裏就和以前版本的uboot接軌上了,推測board_init_f中肯定是做了板級初始化,board_init_r中進入了uboot的命令行。

(4)分析到這裏,在uboot2013.10版本中思路已經很清晰了:uboot的第二階段就在crt0.

(5)分析到這裏,下一步工作方向就確定了。我們要先在cpu_init_crit函數中添加DDR初始化,然後在start.Sbl _main之前添加uboot的重定位,然後將bl _main改成ldr pc, __main(__main: .word _main)長跳轉。然後在crt0.Sboard_init_f後刪除那些重定位代碼,至此uboot的第二階段就應該能啓動起來了。後續的移植就是第二階段了。



該版本沒有DDR初始化代碼需要從三星官方移植

動手移植

(1)添加cpu_init.S文件到uboot2013.10中。注意,這裏的代碼必須保證在前8kb內,所以必須和lowlevel_init.S文件一樣的鏈接處理。主要是在board/samsung/goni/Makefile中和arch/arm/cpu/u-boot.lds文件中做修改添加。

(2)Lds


Makefile中:


(2)添加頭文件s5pc110.hinclude目錄下。

(3)cpu_init.S文件代碼進行修整,把一些無用的代碼去掉,把一些相關的條件編譯人工處理一下。

(4)SourceInsigt工程中添加入這兩個文件。然後重新解析一遍。然後對新添加的代碼進行分析修整,把裏面一些明顯的宏定義缺失給補上。

(5)DDR配置參數,從三星版本的smdkv210single.h中複製到s5p_goni.h

lowleve_init.S中,調用mem_ctrl_asm_init 然後在後面打印“K


(6)s5pc110.h中進行修整。

(7)結果:看到了"OK"標誌,說明DDR添加實驗成功

DDR初始化:1複製三星的cpu_init.S到和lowleve_init.S在同一文件下,並進行修改刪除,再makefile中作爲依賴添加上;再在鏈接腳本u-boot.lds中鏈接到前面。2將所需要的配置宏定義從本來的.h文件中複製到本版本的配置頭文件.h中。3cpu_init.S所需要的板級宏定義的頭文件s5pc110.h複製到相對位置一樣的文件夾中,並進行修改刪除。4lowleve_init.S中,調用mem_ctrl_asm_init 然後在後面打印“K

 

重定位

 

 bl cpu_init_critb lowlevel_init @ go setup pll,mux,memory裏面只有這一句)也可以說在b lowlevle後開始重定位相關代碼。

/重定位開始

 

/* get ready to call C functions設置棧 */

ldr sp, _TEXT_BASE /* setup temp stack pointer */

sub sp, sp, #12

mov fp, #0 /* no previous frame, so fp=0 */

 

/* when we already run in ram, we don't need to relocate U-Boot.

 * and actually, memory controller must be configured before U-Boot

 * is running in ram.檢查需不需要重定位

 */

ldr r0, =0xff000fff

bic r1, pc, r0 /* r0 <- current base addr of code */

ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */

bic r2, r2, r0 /* r0 <- current base addr of code */

cmp     r1, r2                  /* compare r0, r1                  */

beq     after_copy /* r0 == r1 then skip flash copy  */

若相等則不需要重定位直接跳到after_copy

 

/* If BL1 was copied from SD/MMC CH2 *判斷通道2 sd卡啓動*/

ldr r0, =0xD0037488

ldr r1, [r0]

ldr r2, =0xEB200000

cmp r1, r2

beq     mmcsd_boot

 

mmcsd_boot:

bl movi_bl2_copy /*跳轉重定位函數copy,在movi.c

 

after_copy:

clear_bss:

ldr r0, _bss_start /* find start of bss segment        */

ldr r1, _bss_end /* stop here                        */

mov r2, #0x00000000 /* clear                            */

/*bss段,注意鏈接地址,需要移植修改*/

/*

 * These are defined in the board-specific linker script.

 */

.globl _bss_start

_bss_start:

.word __bss_start

 

.globl _bss_end

_bss_end:

.word _end

 

 

clbss_l:

str r2, [r0] /* clear loop...                    */

add r0, r0, #4

cmp r0, r1

ble clbss_l

 

//bl _main 第一階段和第二階段的過度,分析得_mian函數爲uboot第二階段,做長跳轉

 

ldr pc, __main

 

 __main:

.word _main

 

需要移植movi_bl2_cop函數,

所在的文件movi.c複製到\u-boot-2013.10\board\samsung\goni,lowleve.S同樣的操作在Makefikeu-boot.lds,刪除不需要的函數,再確保宏定義可用,在s5p_goni配置頭文件中添加修改。

複製所需要的頭文件到相應位置movi.h

 

後續:將_main(在crt0.S)中的有關重定位的代碼刪掉

編譯中出現問題解決

(1)movi.h中宏定義出錯,最後在s5p_goni.h中添加了CONFIG_EVT1這個宏解決了

(2)連接錯誤:u-boot contains relocations other thanR_ARM_RELATIVE

uboot下用grep "R_ARM_RELATIVE" -nR *搜索,發現Makefile中有一個檢查重定位的規則,屏蔽掉這個規則後編譯連接成功。

 

結果驗證及下階段展望

(1)看到了uboot啓動打印出來的一系列信息,但是uboot沒有進入命令行。

(2)這說明uboot中的DDR初始化和重定位功能都已經完美實現,後面就是第二階段的繼續移植了。

 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章