STM32F系列ARM Cortex-M3核微控制器基礎之儲存系統一
NVIC所處的區域叫做系統控制空間(SCS)。
線索二:CM3匯流排 I-Code匯流排:I-Code匯流排是一條基於AHB-Lite匯流排協議的32位匯流排,負責在0x0000 0000-0x1FFF FFFF之間的取指操作。取指以字的長度執行,即使是對於16位指令也是如此,因此 CPU核心可以一次取出兩條16位Thumb指令。 D-Code匯流排:D-Code匯流排是一條基於AHB-Lite匯流排協議的32位匯流排,負責在0x0000 0000-0x1FFF FFFF之間的資料訪問操作。儘管CM3支援非對齊訪問,但是總線上不會有非對齊的地址(處理器的匯流排介面會把非對齊的資料傳送都轉換成對齊的資料傳送)。
系統匯流排:系統匯流排是一條基於AHB-Lite匯流排協議的32位匯流排,負責在0x2000 0000-0xDFFF FFFF和0xE010 0000-0xFFFF FFFF之間的所有資料傳送(取值和資料訪問)。和D-Code匯流排一樣,所有的資料傳送都是對齊的。
外部私有外設匯流排:外部私有外設匯流排是一條基於APB匯流排協議的32位匯流排,負責在0xE004 0000-0xE00F FFFF之間的私有外設訪問。但是,由於APB儲存空間的一部分已經被TPIU、ETM以及ROM表用掉了,就只剩下0xE004 2000-0xE00F F000這個區間用於配接附加的私有外設。 除錯訪問埠匯流排:除錯訪問埠匯流排是一條基於增強型APB規格的32位匯流排,它專門用於掛接除錯介面(如SWJ-DP和SW-DP)。
問題一:系統上電後發生了什麼?
復位序列:在離開復位狀態後, CM3 做的第一件事就是讀取下列兩個 32 位整數的值:從地址 0x0000,0000 處取出 MSP 的初始值, 從地址 0x0000,0004 處取出 PC 的初始值——這個值是復位向量,LSB 必須是 1。然後從這個值所對應的地址處取指。這與傳統的 ARM 架構不同——其實也和絕大多數的其它微控制器不同。傳統的ARM 架構總是從 0 地址開始執行第一條指令。它們的 0 地址處總是一條跳轉指令。在 CM3中, 0 地址處提供 MSP 的初始值,然後就是向量表(向量表在以後還可以被移至其它位置)。向量表中的數值是 32 位的地址,而不是跳轉指令。向量表的第一個條目指向復位後應執行的第一條指令。
因為 CM3 使用的是向下生長的滿棧,所以 MSP 的初始值必須是堆疊記憶體的末地址加 1。堆疊區域在 0x20007C00‐0x20007FFF,MSP 的初始值就必須是0x20008000。CM3 是在 Thumb態下執行,所以向量表中的每個數值都必須把 LSB 置 1(也就是奇數)。圖中使用 0x101 來表達地址 0x100。當 0x100 處的指令得到執行後,就正式開始了程式的執行。在此之前初始化 MSP 是必需的,因為可能第 1 條指令還沒執行就會被 NMI 或是其它 fault 打斷。 MSP 初始化好後就已經為它們的服務例程準備好了堆疊。
我們從一個實際例程的反彙編程式碼來看看上述情況:
這段程式碼是復位handler
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
這裡Reset handler = 0x0800 01D4,我們去檢視0x0000 0000處的情況:
0x00000000 0760 DCW 0x0760
0x00000002 2000 DCW 0x2000
0x00000004 01D5 DCW 0x01D5
0x00000006 0800 DCW 0x0800
記憶體0x0000 0004和0x0000 0006存放的是復位向量0x0800 01D5。由於CM3 是在 Thumb態下執行,所以向量表中的每個數值都必須把 LSB 置 1(也就是奇數),所以這裡的復位向量值比Reset Handler加了1。而0x0000 0000和0x0000 0002處存放的是0x2000 0760就是MSP的初始值。