預備知識:
DCD指令:用於分配一片連續的字存儲單元(32bit),並將表達式的值初始化給該字存儲單元,類似於C中定義數組並初始化。比如: DCD 0 的意思是:分配一個字存儲單元,並將該單元初始化為0。
分析:
在STM32的啟動文件中可以看到有如下代碼:
EXPORT __Vectors
__Vectors
DCD __initial_sp ; Top of Stack
DCD Reset_Handler
DCD NMIException
DCD HardFaultException
DCD MemManageException
DCD BusFaultException
DCD UsageFaultException
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVCHandler
DCD DebugMonitor
DCD 0 ; Reserved
DCD OSPendSV
……
這一段是分配STM32的中斷向量表。從DCD后面表達式的名稱可以看出第一個字存儲單元分配給了棧頂,其值為__initial_sp。第二個字分配給了復位地址,其值為Reset_Handler,后面接着分配給其他異常或中斷。
這里的Reset_Handler,NMIException等,其實是一個地址值,也就是中斷處理函數的入口地址。在函數實現時,由編譯器分配一個地址值。
那么這里就有兩個問題。
第一個是為什么是這樣的分配順序?
第二個是DCD后面表達式的值,即各個中斷函數的地址值如Reset_Handler,NMIException是如何分配的?
第一個問題的答案好找,我們參考《STM32參考手冊》:
可以看到,啟動文件中的向量表的分配的順序是按照固定的規則來的。
第二個問題。隨意打開一份編譯過的工程,工程配置如下:
我們可以看到.map文件有這樣一段:
同時使用J-Link打開.hex文件可以看到
從hex檔,我們可以看到Flash的起始區域0x8000000的內容為
0x20000660
0x0800027D
0x08000281
0x08000283
……
剛好可以和map文件對應,也剛好可以和啟動文件的向量表對應。
按照Cortex-M3權威指南,在復位后,有如下動作:
我這里是選擇從flash啟動,根據寄存器映射,Address從0x00000000映射到0x08000000。所以hex檔的內容剛好滿足復位序列的設定。
由此從啟動文件到.map文件再到.hex文檔,再到CM3復位啟動的脈絡就理清了。