<2012 12 06>[轉] U-boot研究與移植心得


參考了mobilefzb和趙春江兩位大牛的,也研究了2010.06版本的2011.06版本兩個經典版本,也對比了TQ(我買的板是天嵌的)自己寫的U-BOOT,學到了不少,也發現了很多東西,以下便記錄以下自己的心得吧,以便以后可以自己參考下。

 
U-BOOT的兩個階段啟動過程:(2010.06經典版來說)
第一階段start.S的路徑位於arch\arm\cpu\arm920t\這段匯編代碼一般被稱作第一階段初始化代碼。主要作用是初始化運行環境;初始化內存;重新放置UBOOT代碼到內存中;跳入到內存中執行第二段初始化代碼
1、        關閉開門狗,屏蔽所有中斷
2、        設置分頻比
3、         bl      cpu_init_crit()      關MMU,初始化內存
      bl      lowlevel_init()       配置內存,修改內存刷新率參數等
4、         relocate           判斷當前代碼是在NORFLASH還是RAM
     copy_loop 循環            將FLASH代碼復制至RAM中
5、         stack_setup    棧設置
     clear_bss _bss_start 到_bss_end之間的數據清0
6、         ldr     pc , start_armboot      跳轉到第二階段
//=====================================================================
第二階段board.c的路徑位於arch/arm/lib/board.c,這段代碼為U-BOOT的第二階段初始化代碼。主要作用是初始化兩個重要數據結構,對SDRAM的內存分配設置,對各種需要用到的外設進行初始化,最后循環跳入main_loop()函數
二階段start_armboot分為board_init_f 和 board_init_r兩部分
 
先執行的 board_init_f部分:
1、為gd數據結構分配地址,並清零
2、執行init_fnc_ptr函數指針數組中的各個初始化函數,如下
    board_early_init_f    ,  timer_init       , env_init       init_baudrate serial_init     
    console_init_f       display_banner           dram_init
3、A 、分配SDRAM高64KB為TLB,用於U-BOOT
   B 、分配SDRAM下一單元為U-BOOT代碼段,數據段,BSS段
    (這里插一句,原來BSS段是用來存放未初始化的全局變量與靜態變量)
     C 、接着開辟malloc空間,存bd , gd , 3個字大小的異常堆空間
4 、將relocate的地址值賦給gd結構體相應變量(2011.06版本的,用於返回start.S)
 
后執行的 board_init_r部分:
1、對gd , bd 數據結構賦值初始化
2、各種外設初始化:
    初始化 NORFLASH,     NANDFLASH,       初始化 ONENAND FLASH
    初始化環境變量       初始化 PCI     設置 IP 地址    
     初始化各類外設 :IIC LCD 、鍵盤、 USB        
    初始化控制台      建立 IRQ 中斷堆棧      初始化以太網
    初始化跳轉表(定義了 U-Boot 中基本的常用函數庫)。。這不算外設
3、一個死循環執行   main_loop()函數
 
/************************************
兩個版本的U-BOOT啟動對比:
************************************/
其實在總體上都差不多,只不過相對於經典版(2010.06版),新版之后都變惡心了
主要有這樣的區別:
1、原版本第一階段的第5步棧設置被放到第4步relorate前(這個沒什么)
2、原版第二階段的 board_init_f被放到第一階段第4步relorate前,就是說執行完 stack_setup 棧設置后變進入了第二階段的部分初始化,然后通過 4 、將relorate的地址值賦給gd結構體相應變量(2011.06版本的,用於返回start.S) 又返回來第一階段。。。感覺新版改后很亂,很沒條理(開源的每年改,就是煩呀,哈哈)
 
 
//=================================================
以下列出兩個階段可能要用到的函數的路徑,方便以后找:(按2011.06版本)
一階段:
lowlevel_init 函數,它是在 board/samsung/smdk2410 目錄下的 lowlevel_init.s 文件中定義
 
二階段:
gd 是一個保存在 ARM r8 寄存器中的 gd_t 結構體的指針,它是在 /include/asm 目錄下的 global_data.h 文件內被定義的
bd 結構體的數據原型為 bd_t 數據結構,它表示的是 板級信息 結構體,它是在 /include/asm 目錄下的 u-boot.h 文件中定義的。
init_fnc_ptr函數指針數組中的各個初始化函數:
board_early_init_f 函數在 board/samsung/smdk2410 目錄下的 smdk2410.c 文件內 timer_init 函數在 arch/arm/cpu/arm920t/s3c24x0 目錄下的 timer.c 文件內
env_init 函數在 common 目錄下的 env_flash.c 文件內
init_baudrate 函數在 arch/arm/lib 目錄下的 board.c 文件內
serial_init 函數在 drivers/serial 目錄下的 serial_s3c24x0.c 文件內,在 include/configs/smdk2410.h 中定義了 CONFIG_S3C24X0_SERIAL
console_init_f 函數在 common 目錄下的 console.c 文件內
display_banner 函數在 arch/arm/lib 目錄下的 board.c 文件內
dram_init 函數在 board/samsung/smdk2410 目錄下的 smdk2410.c 文件內
各種外設的初始化
flash_init 函數是在 drivers/mtd 目錄下的 cfi_flash.c 文件內(因為 include/configs/smdk2410.h 中定義了 CONFIG_FLASH_CFI_DRIVER
nand_init 函數是在 divers/mtd/nand 目錄下的 nand.c 文件內定義的
env_relocate 函數是在 common 目錄下的 env_common.c 文件中定義的
stdio_init () common 目錄下的 stdio.c 文件中定義的
jumptable_init () common 目錄下的 exports.c 文件中定義的
console_init_r () 是在 common 目錄下的 console.c 文件中定義的
interrupt_init ()  enable_interrupts () 都是在 arch/arm/lib 目錄下的 interrupts.c 文件中定義
eth_initialize() 函數是在 net 目錄下的 eth.c 文件的第 209 行至第 298 行定義的
main_loop() common 目錄下的 main.c 文件內定義的
 
//===================================================================
天嵌與自己移植的U-BOOT的差別分析和領悟
先列出天嵌公司里研發人員寫的     我們自己移植(小移植)的最大不同:
對比了一下,發現最大的不同在於 common/main.c 文件中,即在兩階段啟動過程基本一樣
不同點:(行數按天嵌版本的)
abortboot() 函數(在 main_loop() 中被調用)
  Ln239: printf ( “ Press Space key to Download Mode ! ” ) ;
  Ln303 : 在檢測是否  a key press  , 加入了顯示 LOGO 程序: embedsky_tq_logo();
main_loop() 函數
  Ln 381: LCD 初始化程序
  Ln481 : 分支選擇   下載  OR  加載 模式 if (  BootFrmNORFLASH()  )
                         run_command (“ menu ”,0 );
                                                               else
                                                              {
                                                                                           Printf (“ Booting Linux \n ”);
                           run_command (“ boot_zImage ”,0 );
}
解析一下:
前面幾點都是關於 LCD LOGO 顯示的不多說(因為自己移植是沒弄到 LCD 的移植)
說一下 main_loop() 函數 Ln481 : 分支選擇   下載  OR  加載 模式
首先, run_command  這個是執行命令函數,一看名字就知道,也是在 /common/main.c 中定義的
說說最重要的 menu boot_zImage
1、    If NORFLASH 進行啟動 ,則為下載模式,則執行 menu() 這個函數,在 /common/cmd_menu.c 中定義
        打開 cmd_menu.c 文件會發現,里面都是一些串口選項列表,我們打開 2440 電源發現的下載列表都是從  main_menu_usage() 函數中打印出來的,而選擇的項又通過 menu_shell() 通過控制台執行各種我們的選項,每個選項的如何執行過程都列得很清楚,感覺就像跑裸機時,自己按照 fzb 的串口控制台弄出來一樣
 
    2、     Else  NANDFLASH 進行啟動      則為加載模式,進行 LINUX 系統的配置和啟動。
        lib_arm /boot_zImage.c  文件:里的 boot_zImage( ) 函數
        函數執行的內容大概如下:
       1  copy   kernel image
       2 setup linux   parameters
       3 get   machine   type
       4 GO   -> call-linux
 
對比后的一些感悟:
雖說自己也跟着移植過 U-BOOT ,也能建立自己的板級支持包,能實現基本的串口控制台, NAND OR NOR FLASH DM9000 網絡, JFFS2 文件系統等基本功能,但比起天嵌這個,能下載       加載 模式,還是有很多不足
所以說,自己移植只是感覺其中的方法,領悟之后還是在天嵌的基礎上再加進一步移植吧,感覺沒必要從頭到尾都自己搞一遍,方法懂了,框架熟悉了就好
 
 
//===================================================================
移植過程的一個簡單舉例:
因為移植很多都是基於 smdk2410 來改的,首先要對 2410 2440 的區別有一定了解,再者就是自己在裸機上是編寫過改外設的驅動的,這樣移植起來就比較舒服,不會說什么都跟着做,感覺很虛,學不到東西。
就舉讓 U-BOOT 支持 NANDFLASH 的讀寫
 1、  先是在總的宏定義頭文件中加上你外設所需的宏定義
總的宏定義路徑為  /include /configs / XX.h/ ( 最后這個 .h 文件一般是以板的名稱命名 )
        添加宏定義,如: #define   CONFIG_NAND_BASE   0      
                             。。。                           等等
        那怎么知道添加什么宏定義呢?一般來說看對外設初始化函數,和 U-BOOT 二階段啟動函數要用到哪些就定義哪些。。。
 2、  改相應的初始化函數 : board_nand_init 函數和 s3c2440_hwcontrol 函數
因為 U-BOOT 里初始化函數基本基於 2410 的,而 2440 NAND 配置參數和它不同,需要改部分地方
3、   添加初始化函數到第二階段 board_init_r處,一般來說基本外設都已添加了,看你是否定義宏來讓其編譯這函數
 
移植一些規律總結:
其實多移植幾次就會發現,UBOOT的移植修改還是遵循着一定的規律。即是先在配置頭文件中打開相關宏定義支持,在到板級初始化(一般是第二階段初始化過程)代碼中添加需要支持功能的初始化函數。
如果初始化函數對應的板版本不兼容或不存在,就要自己編寫了。
 
//===================================================================
最后,說說U-BOOT的編譯
說到編譯,建議去看《從庖丁解牛說 uboot 如何編譯》,說得很好。
 
而說到編譯的執行過程,建議看看
詳細分析make uboot 最后的編譯鏈接的具體執行過程
 
最后談談編譯不通過的問題,如果是內部自己程序出錯,可以通過提示信息查出
如果是出現ERROR一百多個,或者什么arm-linux-ld的問題,那應該是編譯器版本不兼容問題,建議換換新的版本或更舊的版本再試試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM