歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> U-Boot移植過程中的運行地址和裝載地址的區別

U-Boot移植過程中的運行地址和裝載地址的區別

日期:2017/3/1 10:12:05   编辑:Linux編程
uboot移植涉及到底層硬件的設置,因此需要掌握UART、系統時鐘頻率、NOR FLASH、NAND FLASH、SDRAM、網卡、存儲控制器等硬件的功能及配置,這些都可以參照相應開發板的芯片手冊來完成,沒有什麼大的問題。在移植過程中,一直困擾我的是PIC(代碼無關性)問題,即運行地址和加載地址的區別,看過網上很多關於這兩者的介紹,感覺懂一點,卻一直不知所然。在參考大量的文獻下,算是得了一點心得。
首先來了解下運行地址及加載地址的區別
運行地址:也叫鏈接地址,是程序定位的絕對地址,即在編譯連接時確定的地址。如果程序中有位置相關指令,程序在運行時,程序必須在運行地址上。
加載地址:程序放置的位置。
運行地址和加載地址的值有時相等,有時卻不相等,所以這給初學者帶來很大的困擾。為了弄清楚這個問題,還得從NOR FLASH,NAND FLASH,S3C2440內部4KB RAM的映射說起。

左邊表示從NOR FLASH啟動時的映射,右邊表示從NAND FLASH啟動時的映射。
這裡只討論從NOR FLASH啟動的情況,從圖中可以看出NOR FLASH映射到了0X00000000的起始位置,假如UBOOT的代碼存放在NOR FLASH上,即裝載地址為0X00000000。再來看看UBOOT的鏈接地址,代碼在board/smdk2410/U-Boot.lds裡。

連接腳本文件lds中沒有設置LMA,只是設置了VMA。VMA的設置是通過頂層目錄下的config.mk文件中的LDFLAGS實現的

在board/smdk2410/config.mk定義了TEXT_BASE = 0x33F80000(SDRAM),即程序的運行地址

查看u-boot.map文件,代碼的連接地址是從0x33F80000開始的。

167 .text 0x33f80000 0x232c8
168 cpu/arm920t/start.o(.text)
169 .text 0x33f80000 0x4a0 cpu/arm920t/start.o
170 0x33f80048 _bss_start
171 0x33f8004c _bss_end
172 0x33f80044 _armboot_start
173 0x33f80000 _start
174 board/samsung/fs2410/lowlevel_init.o(.text)
175 .text 0x33f804a0 0x64 board/samsung/fs2410/lowlevel_init.o
176 0x33f804a4 lowlevel_init
177 board/samsung/fs2410/nand_read.o(.text)
178 .text 0x33f80504 0xe8 board/samsung/fs2410/nand_read.o
179 0x33f80504 wait_idle
180 0x33f80518 nand_read_ll

此時裝載地址和運行地址明顯不一樣,為什麼程序還能運行呢?這裡就涉及到PIC----代碼無關設計方面的知識了。在匯編語言中,像bl、b、adr(adr屬於偽指令,一般被編譯器解釋成sub指令)指令屬於位置無關指令,不管程序裝載在哪個位置上,bl、b、adr指令都能正確的運行,其原因是bl、b、adr指令的地址域是基於PC的相對偏移尋址,相當於[pc+offset]。當ARM啟動時,ARM自動取0x00000000位置上的指令,此時PC=0x00000000。
基於PC偏移量的指令都能正確的執行。所以uboot第一階段指令都能執行的原因在於此。
但我們回顧一下u-boot的啟動過程中的第一階段有將u-boot代碼復制到SDRAM中,並跳到SDRAM中去運行,因為SDRAM映射到了BANK6,其地址為0x30000000,此時uboot代碼的地址范圍從 TEXT_BASE----TEXT_BASE+size(u-boot),程序是如何跳轉的呢?跳轉到SDRAM為何還能運行呢?這裡就需要看下cpu/arm920t/start.S中的relocate標號。
relocate: 把norflash中的代碼復制到_TEXT_BASE處,在board/smdk2410/config.mk定義了TEXT_BASE = 0x33F80000,這個地址屬於BANK6的范圍。也就是把代碼復制到從_TEXT_BASE地址開始的SDRAM中,當然在復制之前是要初始化SDRAM的,要不然SDRAM沒法使用。至此,代碼已復制到SDRAM中,那麼就要跳到SDRAM中去運行,跳轉之前要做stack設置,清BSS,這些就不說了。下面來說如何跳轉的,請看下面這條指令。
ldrpc, _start_armboot
ldr偽指令中目的寄存器如果是pc,則ldr是與位置相關的指令,u-boot.map文件可以看出,_start_armboot=0x33f80044, 即pc=0x33f80004。這樣uboot就跳到SDRAM上去運行了,且這條指令剛好處在其運行地址處,所以程序就能正確的運行。
Copyright © Linux教程網 All Rights Reserved