TQ2440啟動代碼分析(一)
;===============================================================
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)
ldr r0,=$HandleLabel;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
;IMPORT指令類似于C語言的extern關鍵字,下面這些古怪的變量是由編譯器生成的
IMPORT |Image$$RO$$Base| ; Base of ROM code,即代碼開始的地方
IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)
IMPORT |Image$$RW$$Base| ; Base of RAM to initialise,RAM起始地址
IMPORT |Image$$ZI$$Base| ; Base and limit of area初始化的起始地址
IMPORT |Image$$ZI$$Limit| ; to zero initialise初始化的結束地址
;===============================================================
107 ;在這里用IMPORT偽指令(和c語言的extren一樣)引入外部變量MMU的快速總線
108 ;模式和異步總線模式兩個變量
109 ;===============================================================
IMPORT MMU_SetAsyncBusMode
IMPORT MMU_SetFastBusMode ;
IMPORT Main ; The main entry of mon program
IMPORT RdNF2SDRAM ; Copy Image from Nand Flash to SDRAM
初始化程序中必須指明入口地址,因為處理器復位(仿真時,裝載image)后PC 要找到入口開始執(zhí)行代碼,當各種異常或是中斷產生的時候也要找到各個異常的入口開始執(zhí)行代
碼。從這里開始就是真正的代碼入口了!
AREA Init,CODE,READONLY;聲明一個名為Init的代碼段,
ENTRY 程序的入口點,(調試用)
;ENTRY只是定義一個普通的入口點,且在程序中可以多處定義,如果要使用它作為整
個映像文件的唯一入口點,還需要設置鏈接器中的相關選項。
EXPORT __ENTRY
__ENTRY
ResetEntry ;復位后的入口
;1)The code, which converts to Big-endian, should be in little endian code.
;2)The following little endian code will be compiled in Big-Endian mode.
; The code byte order should be changed as the memory bus width.
;3)The pseudo instruction,DCD can not be used here because the linker generates error.
ASSERT :DEF:ENDIAN_CHANGE
[ ENDIAN_CHANGE
ASSERT :DEF:ENTRY_BUS_WIDTH
;如果沒有定義ENTRY_BUS_WIDTH就報錯
[ ENTRY_BUS_WIDTH=32
b ChangeBigEndian ;DCD 0xea000007
]
[ ENTRY_BUS_WIDTH=16
andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00
]
[ ENTRY_BUS_WIDTH=8
streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
]
|
b ResetHandler;復位異常,開發(fā)板上電或復位時進入0x00
]
中斷向量表一般位于啟動代碼的開始部分,它是用戶程序與啟動代碼之間以及啟動代碼
的各部分之間聯(lián)系的紐帶。它由一個一個的跳轉函數(shù)組成,它就象一個普通的散轉函數(shù),只
不過散轉的過程中有硬件機制參與,當系統(tǒng)發(fā)生異常時,ARM 處理器會通過硬件機制強制
將PC 指針指向中斷向量表中對應的異常跳轉函數(shù)存儲的地址,然后程序會跳轉到相應的中
斷服務程序去執(zhí)行。
b HandlerUndef ;handler for Undefined mode 未定義異常,遇到無法識別的指令時0x04
b HandlerSWI ;handler for SWI interrupt,軟中斷異常0x08
b HandlerPabort ;handler for PAbort指令預取錯誤時進入0x0c
b HandlerDabort ;handler for DAbort數(shù)據(jù)訪問不能完成時進入0x10
b . ;reserved, 保留 0x14
b HandlerIRQ ;handler for IRQ interrupt發(fā)生IRQ 中斷時進入0x18
b HandlerFIQ ;handler for FIQ interrupt發(fā)生FIQ 中斷時進入0x1c
;@0x20
b EnterPWDN ; Must be @0x20.
158 ;===============================================================
159 ;下面是改變大小端的程序,這里采用直接定義機器碼的方式,至說為什么這么做
160 ;就得問三星了反正我們程序里這段代碼也不會去執(zhí)行,不用去管它
161 ;===============================================================
ChangeBigEndian
;@0x24
[ ENTRY_BUS_WIDTH=32
DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0
DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80; //Big-endian
DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0
]
[ ENTRY_BUS_WIDTH=16
DCD 0x0f10ee11
DCD 0x0080e380
DCD 0x0f10ee01
]
[ ENTRY_BUS_WIDTH=8
DCD 0x100f11ee
DCD 0x800080e3
DCD 0x100f01ee
]
DCD 0xffffffff ;swinv 0xffffff is similar with NOP and run well in both endian mode.
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler
;如第前面所說,這里采用HANDLER宏去建立Hander***和Handle***之間的聯(lián)系
HandlerFIQ HANDLER HandleFIQ
Ha ndlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
評論