首先決定看ARM模板的啓動文件,光這個啓動文件就不簡單啊,由於ARM彙編不瞭解,看見一個彙編詞都是翻閱手冊,不懂的就上網或者看書查找,爭取明瞭。編程
首先就是啓動代碼的做用,它包含了異常向量入口,還有初始化了堆棧。啓動代碼的開始時定義了一些堆棧的大小。函數
FIQ_STACK_LEGTH EQU 0 IRQ_STACK_LEGTH EQU 9*8 ;每層嵌套須要9個字堆棧,容許8層嵌套 ABT_STACK_LEGTH EQU 0 UND_STACK_LEGTH EQU 0
NoInt EQU 0x80 USR32Mode EQU 0x10 SVC32Mode EQU 0x13 SYS32Mode EQU 0x1f IRQ32Mode EQU 0x12 FIQ32Mode EQU 0x11
;引入的外部標號在這聲明 IMPORT FIQ_Exception ;快速中斷異常處理程序 IMPORT __main ;C語言主程序入口 IMPORT TargetResetInit ;目標板基本初始化 IMPORT StackUsr IMPORT bottom_of_heap IMPORT SoftwareInterrupt ;給外部使用的標號在這聲明 EXPORT Reset EXPORT __rt_div0 EXPORT __user_initial_stackheap
此僞指令指示編譯器當前的符號不是在本源文件中定義的,而是其餘源文件中定義的,在本源文件中可能引用該符號。fetch
EXPORTthis
聲明一個符號能夠被其餘文件中引用,至關於聲明瞭一個全局變量。加密
接下來就是ARM首先執行的代碼了.spa
CODE32 AREA vectors,CODE,READONLY ENTRY ;中斷向量表 Reset LDR PC, ResetAddr LDR PC, UndefinedAddr LDR PC, SWI_Addr LDR PC, PrefetchAddr LDR PC, DataAbortAddr DCD 0xb9205f80 LDR PC, [PC, #-0xff0] LDR PC, FIQ_Addr ResetAddr DCD ResetInit UndefinedAddr DCD Undefined SWI_Addr DCD SoftwareInterrupt PrefetchAddr DCD PrefetchAbort DataAbortAddr DCD DataAbort Nouse DCD 0 IRQ_Addr DCD 0 FIQ_Addr DCD FIQ_Handler
AREA僞指令用於定義一個代碼段和數據段。這是由於ARM彙編程序設計採用分段式設計,一個ARM源程序至少須要一個代碼段,大的程序能夠包含多個代碼段及數據段。設計
CODE和READONLY代表下面的爲代碼段且只讀。code
LDR爲大範圍的地址讀取僞指令。LDR僞指令用於加載32位的當即數或一個地址值到指定寄存器。內存
DCD用於分配一段字內存單元,並用僞指令中的expr初始化。DCD僞指令分配的內存須要字對齊,通常可用來定義數據表格或其餘常數。get
看完上面的代碼後,我有幾個疑問。
疑問1:既然是加載異常地址到PC,爲何不一下就把地址值賦給PC,而非要先LDR後DCD呢。
搜索資料後得出答案:
由於LDR指令只能跳轉到當前PC 4KB範圍內,而B指令能跳轉到32M範圍,像上面所寫LDR PC,"XXXX"這條指令不遠處用「XXXX」DCD定義一個字,而這個字裏存放最終異常服務程序的地址,這樣能夠實現4GB範圍跳轉。而LDR僞指令經過設置指令緩衝池才能實現全範圍跳轉。
疑問2:
DCD 0xb9205f80
這句話忽然出如今這裏是什麼意思?
答案:是爲了讓異常響亮跳轉那8句機器碼和爲0.爲何這樣,暫時不知道。
接下來是一些異常的處理
;未定義指令 Undefined B Undefined ;取指令停止 PrefetchAbort B PrefetchAbort ;取數據停止 DataAbort B DataAbort ;快速中斷 FIQ_Handler STMFD SP!, {R0-R3, LR} BL FIQ_Exception LDMFD SP!, {R0-R3, LR} SUBS PC, LR, #4
接着是初始化堆棧,這是MCU復位後首先進行的工做。
InitStack MOV R0, LR ;設置中斷模式堆棧 MSR CPSR_c, #0xd2 LDR SP, StackIrq ;設置快速中斷模式堆棧 MSR CPSR_c, #0xd1 LDR SP, StackFiq ;設置停止模式堆棧 MSR CPSR_c, #0xd7 LDR SP, StackAbt ;設置未定義模式堆棧 MSR CPSR_c, #0xdb LDR SP, StackUnd ;設置系統模式堆棧 MSR CPSR_c, #0xdf LDR SP, =StackUsr MOV PC, R0
ResetInit BL InitStack ;初始化堆棧 BL TargetResetInit ;目標板基本初始化 B __main ;跳轉到c語言入口
__user_initial_stackheap LDR r0,=bottom_of_heap MOV pc,lr
__rt_div0 B __rt_div0
StackIrq DCD IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4 StackFiq DCD FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4 StackAbt DCD AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4 StackUnd DCD UndtStackSpace + (UND_STACK_LEGTH - 1)* 4
IF :DEF: EN_CRP IF . >= 0x1fc INFO 1,"\nThe data at 0x000001fc must be 0x87654321.\nPlease delete some source before this line." ENDIF CrpData WHILE . < 0x1fc NOP WEND CrpData1 DCD 0x87654321 ;/* 當此數爲0x87654321時,用戶程序被保護 */
;/* 分配堆棧空間 */ AREA MyStacks, DATA, NOINIT, ALIGN=2 IrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;中斷模式堆棧空間 FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;快速中斷模式堆棧空間 AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;停止義模式堆棧空間 UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;未定義模式堆棧 END