啟動**:所謂的啟動**,就是在啟動的時候執行的一段**,主要任務是初始化處理器模式,設定堆疊,初始化變數等等。由於以上的操作均與處理器架構和系統配置密切相關,所有一般由彙編來編寫。啟動**一般分為兩部分,一是與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處理器來講,有乙個硬體對映的機制。對與這個處理器來說,開始時,預...