uboot移植第三天——代碼分析(3)

uboot中start.S相關代碼分析

重定位

——即把falsh中的代碼複製到ram(sdram)中,本開發板複製到sdram中。
不管我們開發板是以什麼方式啓動(nor/nand)啓動,都需要進行重定位
因爲:
當nor啓動時,因爲nor的特性,只能讀不能寫,因此需要從定位,
當nand啓動時,nand啓動只把前4k代碼複製到片內內存,uboot打印4k,因此需要重定位。相應繼續執行4K以後的代碼,就必須重定位,然後跳到重定位後的地址執行。

代碼分析

relocate:               /* relocate U-Boot to RAM       */
    adr r0, _start      /* r0 <- current position of code   */
    ldr r1, _TEXT_BASE      /* test if we run from flash or RAM */
    cmp     r0, r1                  /* don't reloc during debug         */
    beq     stack_setup

    ldr r2, _armboot_start
    ldr r3, _bss_start
    sub r2, r3, r2      /* r2 <- size of armboot            */
    add r2, r0, r2      /* r2 <- source end address         */

copy_loop:
    ldmia   r0!, {r3-r10}       /* copy from source address [r0]    */
    stmia   r1!, {r3-r10}       /* copy to   target address [r1]    */
    cmp r0, r2          /* until source end addreee [r2]    */
    ble copy_loop

/*這段代碼是在start.S最開頭*/
.globl _start
_start: b       reset

解析:
1、ADR僞指令— 小範圍的地址讀取
ADR僞指令將基於PC相對偏移的地址值或基於寄存器相對偏移的地址值讀取到寄
存器中。
在彙編編譯器編譯源程序時,ADR僞指令被編譯器替換成一條合適的指令。通
常,編譯器用一條ADD指令或SUB指令來實現該ADR僞指令的功能,若不能用一
條指令實現,則產生錯誤,編譯失敗。

  1. adr r0, _start的意思其實很簡單,就是將_start(這個是代碼最開始執行的)的地址賦值給r0.但是具體實現的方式就有點複雜了,對於用adr指令實現的話,說明_start這個地址,相對當前PC的偏移,應該是很小的,意思就是向前一段後者向後一段去找,肯定能找到_start這個標號地址的,此處,自己通過看代碼也可以看到_start,就是在當前指令的前面,距離很近,編譯後,對應彙編代碼,也可以猜得出,應該是上面所說的,用sub來實現,即當前PC減去某個值,得到_start的值(在從Nor Flash啓動時,對應的代碼,也是在Nor Flash中,對應的物理地址是0x0,如果直接從鏈接地址運行時,該值就是鏈接地址),此時是0x0。
  2. cmp r0, r1 因此r0不等r1,beq不成立,所以不跳到stack_setup執行。
  3. ldr r2, _armboot_start //_armboot_start這個標號中的值_start賦給r2,實際就是鏈接地址
    ldr r3, _bss_start //根據鏈接腳本可知這是代碼段的結束地址,bss段的起始地址
    sub r2, r3, r2 /計算出uboot的大小 /
    add r2, r0, r2 /重定位的結束地址 /
  4. copy_loop:
    ldmia r0!, {r3-r10} /* copy from source address [r0] */
    stmia r1!, {r3-r10} /* copy to target address [r1] */
    cmp r0, r2 /* until source end addreee [r2] */
    ble copy_loop
    這就是循環的進行代碼得複製
發佈了38 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章