U-boot移植之二:預備知識

本文旨在闡述一些移植之前應該掌握的基本知識,參考:

http://home.eeworld.com.cn/my/space.php?uid=135723&do=blog&id=25347

 

1.       首先,U-Boot1.3.4還沒有支持s3c2440,移植仍是用2410的文件稍作修改而成的。

2.       2440和2410的區別:

2440和2410的區別主要是2440的主頻更高,增加了攝像頭接口和AC‘97音頻接口;寄存器方面,除了新增模 塊的寄存器外,移植所

 

要注意的是NAND FlASH控制器的寄存器有較大的變化、芯片的時鐘頻率控制寄存器(芯片PLL的寄存器)有一定的變化。其他寄存器

 

基本是兼容的。

3.  你開發板的boot方式是什麼,開發板上電以後是怎麼執行的。

一般來說三星的開發板有三種啓動方式:nand、nor、ram。

具體用那一種方式來啓動決定於CPU的0M[0:1]這兩個引腳,具體請參考S3C2440的datasheet

 

nand:對於2440來說,CPU是不給nand-flash分配地址空間的,nand-flash只相當於CPU的一個外設,S3C2440做了一個從nand-flash

 

啓動的機制。開發板一上電,CPU就自動複製

      nand-flash裏面的前4K-Bytes內容到S3C2440內部集成的SDRAM,然後把4K內容所在         的RAM映射到S3C2440的0地址,從

 

0地址開始執行。這4K的內容主要負責下面這些工         作:初始化中斷矢量、設定CPU的工作模式爲SVC32模式、屏蔽看門狗、屏

 

蔽中斷、          初始化時鐘、把整個u-boot重定向到外部SDRAM、跳到主要的C函數入口。

nor:  早期的時候利用nor-flash啓動的方式比較多,就是把u-boot燒寫到nor-flash裏面,       直接把nor-flash映射到S3C2440

 

的0地址,上電從0地址開始執行。

ram:  直接把u-boot放到外部SDRAM上跑,這一般debug時候用到。

4.  u-boot程序的入口地址問題

    要理解程序的入口地址,自然想到的是連接文件,首先看看開發板相對於某個開發板的連接文件"/board/你的開發板/u-

 

boot.lds",看一個2410的例子:

ENTRY(_start)

SECTIONS

{

       . = 0x00000000;

 

       . = ALIGN(4);

       .text      :

       {

         cpu/arm920t/start.o    (.text)

         *(.text)

       }

 

       . = ALIGN(4);

       .rodata : { *(.rodata) }

 

       . = ALIGN(4);

       .data : { *(.data) }

 

       . = ALIGN(4);

       .got : { *(.got) }

 

       __u_boot_cmd_start = .;

       .u_boot_cmd : { *(.u_boot_cmd) }

       __u_boot_cmd_end = .;

 

       . = ALIGN(4);

       __bss_start = .;

       .bss : { *(.bss) }

       _end = .;

}

(1) 從ENTRY(_start)可以看出u-boot的入口函數是_start,這個沒錯

(2) 從. = 0x00000000也許可以看出_start的地址是0x00000000,事實並不是這樣的,這裏的0x00000000沒效,在連接的時候最終會

 

被TETX_BASE所代替的,具體請參考u-boot根目錄下的config.mk.

(3) 網上很多說法是 _start=TEXT_BASE,我想這種說法也是正確的,但沒有說具體原因。

本人的理解是這樣的,TEXT_BASE表示text段的起始地址,而從

.text      :

{

  cpu/arm920t/start.o    (.text)

  *(.text)

}

看,放在text段的第一個文件就是start.c編譯後的內容,而start.c中的第一個函數就是

_start,所以 _start應該是放在text段的起始位置,因此說_start=TEXT_BASE也不爲過。

5.  一直不明白的U-BOOT是怎樣從4Ksteppingstone跳到RAM中執行的,現在終於明白了。關鍵在於:

              ldr   pc, _start_armboot

_start_armboot:    .word start_armboot

這兩條語句,ldr       pc, _start_armboot指令把_start_armboot這個標籤的地方存放的內容(也即是start_armboot)移到PC寄存

 

器裏面,start_armboot是一個函數地址,在編譯的時候給分配了一個絕對地址,所以上面語句實際上是完成了一個絕對地址的跳轉

 

。而我一直不明白的爲什麼在start.S裏面有很多BL,B跳轉語句都沒有跳出4Ksteppingstone,原因是他們都是相對於PC的便宜的跳轉

 

,而不是絕對地址的跳轉。還有要補充一下LDR,MOV,LDR僞指令的區別。

LDR      R0,0x12345678   //把地址0x12345678存放的內容放到R0裏面

MOV    R0,#x                   //把立即數x放到R0裏面,x必須是一個8 bits的數移到偶數次得到的數。

LDR      R0,=0x12345678        //把立即數0x12345678放到R0裏面

6.  在移植u-boot-1.3.3以上版本的時候要注意:

       在u-boot1.3.3及以上版本Makefile有一定的變化,使得對於24x0處理器從nand啓動的遇到問題。也就是網上有人說的:無法

 

運行過lowlevel_init。其實這個問題是由於編譯器將我們自己添加的用於nandboot的子函數nand_read_ll放到了4K之後造成的(到

 

這不理解的話,請仔細看看24x0處理器nandboot原理)。我是在運行失敗後,利用mini2440的4個LED調試發現u-boot根本沒有完成自

 

我拷貝,然後看了uboot根目錄下的System.map文件就可知道原因。

解決辦法其實很簡單:

將__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))

改爲__LIBS := $(subst $(obj),,$(LIBBOARD)) $(subst $(obj),,$(LIBS))

7.   然後說一下跳轉指令。ARM有兩種跳轉方式。

(1)mov pc <跳轉地址〉

 這種向程序計數器PC直接寫跳轉地址,能在4GB連續空間內任意跳轉。

(2)通過B BL BLX BX可以完成在當前指令向前或者向後32MB的地址空間的跳轉(爲什麼是32MB呢?寄存器是32位的,此時的值是24

 

位有符號數,所以32MB)。

B是最簡單的跳轉指令。要注意的是,跳轉指令的實際值不是絕對地址,而是相對地址——是相對當前PC值的一個偏移量,它的值由

 

彙編器計算得出。

BL非常常用。它在跳轉之前會在寄存器LR(R14)中保存PC的當前內容。BL的經典用法如下:

       bl NEXT  ; 跳轉到NEXT

       ……

    NEXT

       ……

       mov pc, lr   ; 從子程序返回。

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