ARM啟動過程分析

2021-07-01 18:54:06 字數 3466 閱讀 5134

啟動**:所謂的啟動**,就是在啟動的時候執行的一段**,主要任務是初始化處理器模式,設定堆疊,初始化變數等等。由於以上的操作均與處理器架構和系統配置密切相關,所有一般由彙編來編寫。啟動**一般分為兩部分,一是與arm7核心相關的部分,包括處理器各異常向量的配置,各處理器模式的堆疊設定,如果有必要,複製向量到ram,以便remap之後處理器能正確處理異常,初始化資料(rw和zi),最後跳轉到main函式。二是與處理器外設相關的部分,該部分和廠商的聯絡比較大。雖然都採用的是arm7的核心,但是不同廠家整合了不同的片上外設,需要不同的初始化,其中比較重要的是初始化wdt,初始化各子系統的時鐘,有必要的話,進行remap。這一部分與一般控制器的初始化類似,因此,本文不作詳細描述。

片上flash起始於0x00100000,共64kb, 片上ram起始於0x00200000,共16kb。

復位之後,程式從0位址開始執行,此時flash被對映到0位址,因此從flash上取指並開始執行,顯然,此時還是在0x00100000位址,如果使用remap命令,將會把ram對映到0位址,同樣,這時0位址的內容也只是ram的映象。

flash可以保證在最差情況時以30mhz進行單週期訪問,而ram可以保證在最大速度時的單週期訪問。

一.處理器異常

建立異常向量表,由於復位位於0位址,也需要一條跳轉指令,具體**如下:

area start, code, readonly

entry

b reset_handler

b undefined_handler

b swi_handler

b prefetch_handler

b abort_handler

b reserved

b irq_handler

b fiq_handler

二.處理器模式

arm處理器可以工作於多種模式,不同模式有各自的堆疊空間,以下設定各模式及其堆疊。

預定義一些引數:

mode_usr equ 0x10

mode_sys equ 0x1f

mode_svc equ 0x13

mode_abt equ 0x17

mode_und equ 0x1b

mode_irq equ 0x12

mode_fiq equ 0x11

i_bit equ 0x80

f_bit equ 0x40

t_bit equ 0x20

stack_limit equ 0x000ffff0

fiq_stack equ stack_limit

irq_stack equ fiq_stack - 512-12

svc_stack equ irq_stack - 512

sys_stack equ svc_stack - 384

ldr r0, #mode_irq:or:i_bit:or:f_bit

msr cpsr_c, r0

mov r13, =irq_stack

…………(初始化各模式的堆疊都一樣)

三.初始化變數

編譯完成之後,聯結器會生成三個基本的段,分別是ro, rw, zi段。並會在image中順序放置。顯然,rw, zi在執行開始時並不位於指定的rw位置,因此必須初始化

ldr  r0, = |image$$ro$$limit|

ldr r1, = |image$$rw$$base|

ldr r2, = |image$$zi$$base|

1

cmp r1, r2

ldrlo r3, [r0], #4

strlo r3, [r1], #4

blo %b1

mov  r3, #0

ldr r1, =|image$$zi$$limit|

2

cmp r2, r1

strlo r3, [r2], #4

blo %b2

四.複製異常向量

由於**位於ram執行時,有明顯的速度優勢,而且變數可以動態分配,因此可以通過remap將ram對映到0位址,使得出現異常時arm從ram中取得向量。

import |imagero

base|

import |imagero

limit|

import |imagerw

base|

import |imagerw

limit|

import |imagezi

base|

import |imagezi

limit|

copy_vect_to_ram

ldr r0,=|imagero

base|

ldr r1,=sysinit

ldr r2,=0x200000 ; ram start

0 cmp r0,r1

ldrlo r3,[r0],#4

strlo r3,[r2],#4

blo %b0

這段程式將sysinit之前的**,也就是異常處理函式,全部複製到ram中, 這就意味著不能將rw設定為0x200000,這樣會使得向量被沖掉.

四,在ram中執行

如果有必要,且**足夠小,可以將**置於ram中執行,由於ram中本身沒有**,就需要將**複製到ram中:

copy_begin

ldr r0,=0x200000

ldr r1,=reset ; =|imagero

base|

cmp r1,r0 ;

blo copy_end ;

adr r0,reset

adr r2,copy_end

sub r0,r2,r0

add r1,r1,r0

ldr r3,=|imagero

limit|

3 cmp r1,r3

ldrlo r4,[r2],#4

strlo r4,[r1],#4

blo %b3

ldr pc,=copy_end

copy_end

程式首先取得reset的連線位址,判斷程式是否時是在ram中執行,方法是與ram起始位址比較,如果小於,那麼就跳過**複製.

在複製**的時候需要注意,在這段程式結束之前的**沒有必要複製,因為這些**都已經執行過了,所以,先取得copy_end,作為複製起始位址,然後計算其相對reset的偏移,然後以ro的值加上這個偏移,就是複製目的地的起始位址,然後開始複製.

五,開始主程式

以上步驟完成,就可以跳轉到main執行

import main

ldr pc,=main

b .六,器件初始化

主程式首先要進行器件的初始化,一般應該先初始化wdt,因為預設情況下,wdt是開啟的,然後是各裝置的時鐘分配,最後應該remap。

ARM啟動過程

從開機,即對處理器傳送乙個 reset 訊號後,arm 處理器就進入中斷模式,從中斷向量 reset 處理,即位址0x00000000 處開始執行。但是,我們看到,整個系統在實體地址 0 處是沒有儲存器件的。實際上是,對與大多數的arm處理器來講,有乙個硬體對映的機制。對與這個處理器來說,開始時,預...

ARM 啟動過程

從開機,即對處理器傳送乙個 reset 訊號後,arm 處理器就進入中斷模式,從中斷向量 reset 處理,即位址0x00000000 處開始執行。但是,我們看到,整個系統在實體地址 0 處是沒有儲存器件的。實際上是,對與大多數的arm處理器來講,有乙個硬體對映的機制。對與這個處理器來說,開始時,預...

ARM 啟動過程

從開機,即對處理器傳送乙個 reset 訊號後,arm 處理器就進入中斷模式,從中斷向量 reset 處理,即位址0x00000000 處開始執行。但是,我們看到,整個系統在實體地址 0 處是沒有儲存器件的。實際上是,對與大多數的arm處理器來講,有乙個硬體對映的機制。對與這個處理器來說,開始時,預...