基于ARM的芯片多數(shù)為復雜的片上系統(tǒng)。這種復雜系統(tǒng)里的多數(shù)硬件模塊都是可配置的。需要由軟件來設置其需要的工作狀態(tài)。因此在用戶的應用程序之前,需要由專門的一段代碼來完成對系統(tǒng)的初始化。由于這類代碼直接面對處理器內(nèi)核和硬件控制器進行編程,一般都是用匯編語言。
啟動代碼是芯片復位后進入C語言的main()函數(shù)前執(zhí)行的一段代碼,主要是為運行C語言程序提供基本運行環(huán)境,如初始化存儲器系統(tǒng)等。ARM公司只設計內(nèi)核,不自己生產(chǎn)芯片,只是把內(nèi)核授權(quán)給其它廠商,其它廠商購買了授權(quán)且加入自己的外設后生產(chǎn)出各具特色的芯片。這樣就促進了基于ARM處理器核的芯片多元化,但也使得每一種芯片的啟動代碼差別很大,不易編寫出統(tǒng)一的啟動代碼。ADS(針對ARM處理器核的C語言編譯器)的策略是不提供完整的啟動代碼,啟動代碼不足部分或者由廠商提供,或者自己編寫。
ARM的啟動代碼類似于電腦中的BIOS,它從系統(tǒng)上電開始接管CPU,依次需要負責初始化 CPU在各種模式下的堆棧空間、設定CPU的內(nèi)存映射、對系統(tǒng)的各種控制寄存器做初始化、對CPU的外部存儲器進行初始化、設定各外圍設備的基地址、創(chuàng)建正確的中斷向量表、為C代碼執(zhí)行創(chuàng)建ZI(零創(chuàng)建)區(qū),然后進入到C代碼。 在C代碼中繼續(xù)對時鐘、RS232端口進行初始化,然后打開系統(tǒng)中斷允許位。最后進入到應用代碼中執(zhí)行,執(zhí)行期間響應各種不同的中斷信號并調(diào)用預先設置好的中斷服務程序處理這些中斷。
一般ARM的啟動代碼中通用的內(nèi)容包括:
中斷向量表
初始化存儲器系統(tǒng)
初始化堆棧
初始化有特殊要求的端口,設備
初始化用戶程序執(zhí)行環(huán)境
改變處理器模式
呼叫主應用程序
以stm32的啟動文件為例,stm32的啟動文件一般都是包含在具體單片機型號的匯編文件中(.s文件),下圖為啟動文件的簡述(description)
和我們預想的差不多,該啟動文件主要包含了初始化主堆棧指針(MSP)、初始化程序指針(PC)、初始化中斷向量表、配置系統(tǒng)時鐘和外部Sram(可選)、跳轉(zhuǎn)到main函數(shù)
第一部分配置堆和棧的大小(Stack_size Heap_size)
Stack_Size EQU 0x400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
AREA STACK, NOINIT, READWRITE, ALIGN=3 ;定義棧,可初始為0,8字節(jié)對齊 (堆代碼類似相同功能)
Stack_Mem SPACE Stack_Size ;分配0x400個連續(xù)字節(jié),并初始化為0 (堆代碼類似相同功能)
__initial_sp ;匯編代碼地址標號 (堆代碼類似相同功能)
PRESERVE8 ;指定當前文件堆棧8字節(jié)對齊
THUMB ;告訴匯編器下面是32為的Thumb指令,如果需要匯編器將插入位以保證對齊
第二部分定義中斷向量表
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
AREA RESET, DATA, READONLY ;定義復位向量段,只讀
EXPORT __Vectors ;定義一個可以在其他文件中使用的全局標號。此處表示中斷地址
__Vectors DCD __initial_sp ; 給__initial_sp分配4字節(jié)32位的地址0x0
DCD Reset_Handler ; 給標號Reset Handler分配地址為0x00000004
DCD NMI_Handler ; 給標號NMI Handler分配地址0x00000008
DCD HardFault_Handler ; Hard Fault Handler
DCD ……
__Vectors_End
第三部分Reset_Handler 及假異常處理程序的定義
AREA |.text|, CODE, READONLY ;代碼段定義為只讀
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit //把SystemInit 的地址加載到寄存器R0。
BLX R0 //程序跳轉(zhuǎn)到R0 中的地址執(zhí)行程序
LDR R0, =__main //把_main 的地址加載到寄存器R0
BX R0 //程序跳轉(zhuǎn)到R0 中的地址執(zhí)行程序,執(zhí)行完畢之后就去到我們熟知的C 世界。
ENDP //表示子程序的結(jié)束





