關(guān)于啟動(dòng)代碼2440init.s(一)
; NAME: 2440INIT.S
; DESC: C start up codes
;
;
;
; NAME: 2440INIT.S
; DESC: C start up codes
;
;
;
; HISTORY:
; 2002.02.25:kwtark: ver 0.0
; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode
; 2003.03.14:DonGo: Modified for 2440.
; 2009 06.24:Tinko Modified
;=========================================
;匯編不能使用include包含頭文件,所有用Get
;匯編也不認(rèn)識(shí)*.h 文件,所有只能用*.inc
;REFRESH寄存器[22]bit : 0- auto refresh; 1 - self refresh
BIT_SELFREFRESH EQU (1<<22) ;用于節(jié)電模式中,SDRAM自動(dòng)刷新
;處理器模式常量: CPSR寄存器的后5位決定目前處理器模式 M[4:0]
USERMODE
FIQMODE
IRQMODE
SVCMODE
ABORTMODE
UNDEFMODE
MODEMASK
NOINT
;定義處理器各模式下堆棧地址常量
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~
FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~
;arm處理器有兩種工作狀態(tài) 1.arm:32位 這種工作狀態(tài)下執(zhí)行字對準(zhǔn)的arm指令 2.Thumb:16位 這種工作狀
;態(tài)執(zhí)行半字對準(zhǔn)的Thumb指令
;因?yàn)樘幚砥鞣譃?6位 32位兩種工作狀態(tài) 程序的編譯器也是分16位和32兩種編譯方式 所以下面的程序用
;于根據(jù)處理器工作狀態(tài)確定編譯器編譯方式
;code16偽指令指示匯編編譯器后面的指令為16位的thumb指令
;code32偽指令指示匯編編譯器后面的指令為32位的arm指令
;
;Arm上電時(shí)處于ARM狀態(tài),故無論指令為ARM集或Thumb集,都先強(qiáng)制成ARM集,待init.s初始化完成后
;再根據(jù)用戶的編譯配置轉(zhuǎn)換成相應(yīng)的指令模式。為此,定義變量THUMBCODE作為指示,跳轉(zhuǎn)到main之前
;根據(jù)其值切換指令模式
;
;這段是為了統(tǒng)一目前的處理器工作狀態(tài)和軟件編譯方式(16位編譯環(huán)境使用tasm.exe編譯
;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.
THUMBCODE SETL {TRUE}
THUMBCODE SETL {FALSE}
;=======================================================================================
;下面這個(gè)宏是用于第一次查表過程的實(shí)現(xiàn)中斷向量的重定向,如果你比較細(xì)心的話就是發(fā)現(xiàn)
;在_ISR_STARTADDRESS=0x33FF_FF00里定義的第一級(jí)中斷向量表是采用型如Handle***的方式的.
;而在程序的ENTRY處(程序開始處)采用的是b Handler***的方式.
;在這里Handler***就是通過HANDLER這個(gè)宏和Handle***建立聯(lián)系的.
;這種方式的優(yōu)點(diǎn)就是正真定義的向量數(shù)據(jù)在內(nèi)存空間里,而不是在ENTRY處的ROM(FLASH)空間里,
;這樣,我們就可以在程序里靈活的改動(dòng)向量的數(shù)據(jù)了.
;========================================================================================
;;這段程序用于把中斷服務(wù)程序的首地址裝載到pc中,有人稱之為“加載程序”。
;本初始化程序定義了一個(gè)數(shù)據(jù)區(qū)(在文件最后),34個(gè)字空間,存放相應(yīng)中斷服務(wù)程序的首地址。每個(gè)字
;空間都有一個(gè)標(biāo)號(hào),以Handle***命名。
;在向量中斷模式下使用“加載程序”來執(zhí)行中斷服務(wù)程序。
;這里就必須講一下向量中斷模式和非向量中斷模式的概念
;向量中斷模式是當(dāng)cpu讀取位于0x18處的IRQ中斷指令的時(shí)候,系統(tǒng)自動(dòng)讀取對應(yīng)于該中斷源確定地址上的;
;指令取代0x18處的指令,通過跳轉(zhuǎn)指令系統(tǒng)就直接跳轉(zhuǎn)到對應(yīng)地址
;函數(shù)中 節(jié)省了中斷處理時(shí)間提高了中斷處理速度標(biāo) 例如 ADC中斷的向量地址為0xC0,則在0xC0處放如下
;代碼:ldr PC,=HandlerADC 當(dāng)ADC中斷產(chǎn)生的時(shí)候系統(tǒng)會(huì)
;自動(dòng)跳轉(zhuǎn)到HandlerADC函數(shù)中
;非向量中斷模式處理方式是一種傳統(tǒng)的中斷處理方法,當(dāng)系統(tǒng)產(chǎn)生中斷的時(shí)候,系統(tǒng)將interrupt
;pending寄存器中對應(yīng)標(biāo)志位置位 然后跳轉(zhuǎn)到位于0x18處的統(tǒng)一中斷
;函數(shù)中 該函數(shù)通過讀取interrupt pending寄存器中對應(yīng)標(biāo)志位 來判斷中斷源 并根據(jù)優(yōu)先級(jí)關(guān)系再跳到
;對應(yīng)中斷源的處理代碼中
;
;H|------|
; |/ / / |
; |------|<----sp
;L|
; |
;
$HandlerLabel HANDLER $HandleLabel(入口地址)
$HandlerLabel
;=========================================================================================
;在這里用IMPORT偽指令(和c語言的extren一樣)引入|Image$$RO$$Base|,|Image$$RO$$Limit|...
;這些變量是通過ADS的工程設(shè)置里面設(shè)定的RO Base和RW Base設(shè)定的,
;最終由編譯腳本和連接程序?qū)氤绦?
;那為什么要引入這玩意呢,最簡單的用處是可以根據(jù)它們拷貝自已
;==========================================================================================
;Image$$RO$$Base等比較古怪的變量是編譯器生成的。RO, RW, ZI這三個(gè)段都保存在Flash中,但RW,ZI在Flash中
;的地址肯定不是程序運(yùn)行時(shí)變量所存儲(chǔ)的位置,因此我們的程序在初始化時(shí)應(yīng)該把Flash中的RW,ZI拷貝到RAM的對應(yīng)位置。
;一般情況下,我們可以利用編譯器替我們實(shí)現(xiàn)這個(gè)操作。比如我們跳轉(zhuǎn)到main()時(shí),使用 b
;和Main之間插入一段匯編代碼,來替我們完成RW,ZI段的初始化。 如果我們使用b
;編譯器會(huì)生成如下變量告訴我們RO,RW,ZI三個(gè)段應(yīng)該位于什么位置,但是它并沒有告訴我們RW,ZI在Flash中存儲(chǔ)在什么位置,
;實(shí)際上RW,ZI在Flash中的位置就緊接著RO存儲(chǔ)。我們知道了Image$$RO$$Base,Image$$RO$$Limit,那么Image$$RO$$Limit就
;是RW(ROM data)的開始。
;這里引入一些在其它文件中實(shí)現(xiàn)在函數(shù),包括為我們所熟知的main函數(shù)
(上面都是宏,下篇文章程序真正開始)
評(píng)論