S3C6410之uboot回爐再造(1)start.S - SVC模式設置


  雖然已經寫了幾篇關於uboot移植的、但是覺得整體對uboot的理解還是只停留在copy的層面。

  狠下心來,從代碼進行uboot的分析,並從新移植一次uboot。

  這次更側重於記錄代碼分析心得。

  使用uboot的版本仍為2010.3版本。

 

  這里有一個很是詳盡的start.S分析網站,分析過程借鑒了網站的方法,但也有一些不同的地方

http://www.crifan.com/files/doc/docbook/uboot_starts_analysis/release/html/uboot_starts_analysis.html

  總的不同有如下

  在網站的分析中,基於代碼為arm920t,即ARM9系列芯片,ARM9系列芯片的初始化過程為:

 

1、設置CPU模式
2、關閉看門狗
3、關閉中斷
4、設置堆棧sp指針
5、清除bss段
6、異常中斷處理

 

  然后我現在選擇的修改模板是arm1176,即ARM11系列芯片,ARM11系列芯片的初始化過程為:

1、設置CPU模式
// -- 關閉看門狗
// -- 關閉中斷
2、初始化MMU  // ++
3、設置堆棧sp指針
4、清除bss段
5、異常中斷處理

  兩種芯片的start.S的區別一目了然。

 

  接着開始分析代碼了。

 

 

  一切的開始:start.S  (文件路徑為/cpu/arm1176/start.S)

  為了方便跳轉閱讀,啟用行號。

  為避免誤導,在此說明:

  此時我使用的是未經修改的uboot2010版本的start.S,在這篇分析中不會對它進行任何修改。

  在隨后的blog中才對start.S進行修改並闡述理由,修改處必有類似 git diff 的說明

  1、頭文件

 1 /*
 2  * ……
 3  */
 4 
 5 #include <config.h>
 6 #include <version.h>
 7 #ifdef CONFIG_ENABLE_MMU
 8 #include <asm/proc/domain.h>
 9 #endif
10 #include <asm/arch/s3c6410.h>
11 
12 #if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)
13 #define CONFIG_SYS_PHY_UBOOT_BASE    CONFIG_SYS_UBOOT_BASE
14 #endif

  頭文件部分不必贅述,但是這里有一個不得不說的地方

13 #define CONFIG_SYS_PHY_UBOOT_BASE    CONFIG_SYS_UBOOT_BASE

  為了解析這個定義,找到了 /include/configs/smdk6400.h

/* NAND U-Boot load and start address */
#define CONFIG_SYS_UBOOT_BASE        (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000)

  繼續跳轉搜索 CONFIG_SYS_MAPPED_RAM_BASE:

#ifdef CONFIG_ENABLE_MMU
#define CONFIG_SYS_MAPPED_RAM_BASE    0xc0000000
#define CONFIG_BOOTCOMMAND    "nand read 0xc0018000 0x60000 0x1c0000;" \
                "bootm 0xc0018000"
#else
#define CONFIG_SYS_MAPPED_RAM_BASE    CONFIG_SYS_SDRAM_BASE
#define CONFIG_BOOTCOMMAND    "nand read 0x50018000 0x60000 0x1c0000;" \
                "bootm 0x50018000"
#endif

  很顯然了,在MMU工作的狀態下:

#define CONFIG_SYS_MAPPED_RAM_BASE    0xc0000000

  MMU工作就是開發板播到從NAND flash啟動的狀態。

 

  而在MMU未工作的狀態下:

#define CONFIG_SYS_MAPPED_RAM_BASE    CONFIG_SYS_SDRAM_BASE
....
#define CONFIG_SYS_SDRAM_BASE  0x50000000

  從這里,可以理解在使用dnw下載的時候,Download Address為

#define CONFIG_SYS_UBOOT_BASE        (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000)
// 0x5000000 + 0x07e00000 = 0x57e00000

  uboot是bootloader的一種,要更為准確地描述這兩種狀態可以說為

  1、啟動加載(Boot loading)模式,即自主"(Autonomous)模式;

  2、下載(Downloading)模式。

  更為詳細的描述可以參詳

http://blog.csdn.net/r91987/article/details/6695007

  

  接下來進入正文分析了

 1 /*
 2  *************************************************************************
 3  *
 4  * Jump vector table as in table 3.1 in [1]
 5  *
 6  *************************************************************************
 7  */
 8 
 9 .globl _start
10 _start: b    reset      //跳轉到reset處執行,即下一段代碼的44行
                  //但此時不必急着看reset的執行代碼,可以繼續順序往下
11 #ifndef CONFIG_NAND_SPL   //定義NAND_SPL時
12     ldr    pc, _undefined_instruction  //ldr = Load Register 
13     ldr    pc, _software_interrupt    //軟件中斷
14     ldr    pc, _prefetch_abort      //預取指中止
15     ldr    pc, _data_abort         //數據中止
16     ldr    pc, _not_used          //保留
17     ldr    pc, _irq             //IRQ中斷
18     ldr    pc, _fiq             //FIQ中斷
19           //這里的七種異常就是ARM的七種異常處理類型,對應的聲明在 20 - 33行
20 _undefined_instruction:    //.word = 32bit , 這里可以理解為 _undef.. = &undef..
21     .word undefined_instruction //這里將地址放入 _undef.. ,而_undef的地址又放入pc
22 _software_interrupt:     //雙層取址,所以最終送入pc的數據為 undefined_instruction
23     .word software_interrupt //以下含義相同
24 _prefetch_abort:       
25     .word prefetch_abort   //pc 是 ARM 的指令寄存器
26 _data_abort:     //將這些異常送入 pc ,意為讓 ARM 運行這些指令的初始化代碼(后文可見)
27     .word data_abort
28 _not_used:
29     .word not_used
30 _irq:
31     .word irq
32 _fiq:
33     .word fiq
34 _pad:
35     .word 0x12345678 /* now 16*4=64 */
36 #else
37     . = _start + 64
38 #endif
39 
40 .global _end_vect
41 _end_vect:
42     .balignl 16,0xdeadbeef  // .balignl 為對其指令,意為讓以下的代碼按16位對其
                   //不足為則補上0xdeadbeef
                   //很有意思的dead beef,為數不多的能用16進制表示的單詞

  接下來為正式的啟動指令了

1 /*
 2  *************************************************************************
 3  *
 4  * Startup Code (reset vector)
 5  *
 6  * do important init only if we don't start from memory!
 7  * setup Memory and board specific bits prior to relocation.
 8  * relocate armboot to ram
 9  * setup stack
10  *
11  *************************************************************************
12  */
13 
14 _TEXT_BASE:
15     .word    TEXT_BASE  //這里是 .text 的 base ,即代碼段的基址
16 
17 /*
18  * Below variable is very important because we use MMU in U-Boot.
19  * Without it, we cannot run code correctly before MMU is ON.
20  * by scsuh.
21  */
22 _TEXT_PHY_BASE:      //上面的注釋很清晰了
23     .word    CONFIG_SYS_PHY_UBOOT_BASE
24 
25 .globl _armboot_start  //此處聲明了 _armboot_start 指向 _start
26 _armboot_start:      
27     .word _start
28 
29 /*
30  * These are defined in the board-specific linker script.
31  */
32 .globl _bss_start    //此處的標號其實最終指向的是鏈接腳本文件(.lds)中的定義
33 _bss_start:
34     .word __bss_start
35 
36 .globl _bss_end     //同上
37 _bss_end:
38     .word _end
39 
40 /*
41  * the actual reset code
42  */
43 
44 reset:        //這里就是start之后跳轉的地方了
45     /*
46      * set the cpu to SVC32 mode
47      */      //SVC模式也成為管理模式,是操作系統的一種保護模式
48     mrs    r0, cpsr      //mrs為讀寄存器指令 
49     bic    r0, r0, #0x3f   //清除r0的低7位
50     orr    r0, r0, #0xd3   //將r0置為0b1101_0011,我們只看低5位
51     msr    cpsr, r0      //查CPSR處理器模式位知SVC模式位就是0b1_0011

  至此,CPU的SVC模式設置成功了。

  最后補充一個內容,.lds文件是編譯腳本文件,展開可以看成ld script。

  這里的 ld 對應於編譯器的 arm-linux-ld。

  有關於.lds文件的說明,可以參閱

http://blog.csdn.net/pottichu/article/details/4261289

  在后面的篇幅中,也會涉及.lds文件的修改。

 


免責聲明!

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



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