STM32啟動過程解讀與跟蹤驗證

Sun_Shine_999發表於2018-04-20

本文轉載自:https://blog.csdn.net/he_ning/article/details/35226125

近段時間由於在做ucos-iii的移植,所以就順便了解下STM32的啟動過程。經過查閱各種官方文獻和對程式碼進行單步跟蹤,詳細地敘述了STM32加電啟動的具體過程。對於關鍵性的語句都指明瞭出處。下面將學習成果分享給大家,由於筆者知識有限,不當之處敬請指出。

為了更好的說明問題,先來看STM32的記憶體對映(以STM32L1xx為例)

由於固定的記憶體對映,程式碼區(code area)從0x00000000開始,通過指令匯流排(ICode Bus)和資料匯流排(DCode Bus)訪問。資料區(SRAM)從0x20000000開始,通過系統匯流排(System Bus)訪問。Cortex™-M3 CPU總是通過指令匯流排(ICode Bus)取得復位向量,這就意味著啟動空間(boot space)只能處於程式碼區(code area),典型的就是Flash。STM32系列使用了一種特殊的機制,能夠從程式碼區以外的區域啟動(如,內部的SRAM)。(《cortex-m3程式設計指南》)

這就意味著,STM32系列可以有3種啟動模式,由BOOT1與BOOT0的設定決定選擇Flash、System memory還是SRAM作為啟動空間(boot space)。
這裡寫圖片描述
STM32把從0x00000000到0x0005FFFF的區域作為啟動空間(boot space)的別名區
這裡寫圖片描述

從上面兩個表中可以看出:

當從主快閃記憶體(Main Flash memory)啟動時,啟動空間別名區對映到Flash。
當從系統記憶體(System memory)啟動時,啟動空間別名區對映到System memory。
當從內部SRAM(Embedded SRAM)啟動時,啟動空間別名區對映到SRAM。

注:預設是這樣的對映關係,但上述的對映關係啟動後可以由軟體修改(通過修改SYSCFG啟動器的MEM_MODE
這裡寫圖片描述

這樣,Flash、System memory和SRAM分別可以從別名區和原始地址處訪問。

Flash:訪問地址為0x00000000或0x08000000

System memory:訪問地址為0x00000000或0x1FF00000

SRAM:啟動時地址為0x00000000或0x20000000(STM32Fxx的參考手冊上說,啟動後只能在0x20000000開始訪問,即啟動後這個對映消失,需要重定位中斷向量表,這是特例)

System memory內建了ST提供的boot loader,可以通過該boot loader下載程式到Flash中。

使用者程式實際只能儲存在Flash中,且能在Flash和SRAM中執行(因為cortex-m3核採用哈佛結構,程式碼可直接在Flash執行,馮•諾依曼結構則必須將程式碼拷貝至RAM執行)。
Flash就像是電腦的硬碟,用於儲存程式碼。
System memory就像是電腦的ROM,裡面的程式有晶片廠商寫好,使用者不可改寫。

SRAM就像是電腦的記憶體,裡面的資料都是動態的,掉電就丟失的,用於建立堆疊等。

對於使用者程式碼來說,只需要考慮從Flash啟動和從SRAM啟動兩種情況。

瞭解上述對映關係之後,就可以討論中斷向量表了。

Cortex-m3核的中斷向量表是不變的(中斷向量表每一項為4個位元組,中斷向量表的第一項:棧頂,中斷向量表的第二項:復位向量……,中斷向量表每項內容可以看官方的啟動檔案,或者檢視相關的手冊),只需要使用者設定表頭的地址。

預設情況下,從Flash啟動,中斷向量表從Flash的起始地址(0x08000000)開始存放(疑問:表頭之後的四位元組開始存放,表頭應該存放sp地址?)。同時對映到0x00000000處。向量表偏移暫存器(VTOR)的值為0x00000000(實際對映到0x08000000)。

若從SRAM啟動,中斷向量表還是存放在Flash中(Flash才能固化儲存,SRAM只能加電才有效),只不過拷貝到SRAM的首地址0x20000000處。此時向量表偏移暫存器(VTOR)的值也是0x00000000(實際對映到0x20000000)。而啟動過程結束後,這個特殊的對映不復存在了(據參考手冊推測的),所以,需要修改向量表偏移暫存器(VTOR)的值為0x20000000以後的值(其中TBLOFF位域要是0x200的倍數,這個是字對齊的要求(見《cortex-m3程式設計手冊》),由於STM32的中斷向量一共有68+16=84個,應該把這個數增加到下一個2的整數倍即128,然後換算成地址範圍128*4=512,就得到了0x200),以便處理中斷。

因此,無論用哪種模式啟動,復位時棧頂指標總能在0x00000000(或0x08000000)處找到,而復位向量總能在0x00000004(或0x08000004)處找到。

又根據《cortex-m3程式設計手冊》,復位時,CPU從0x00000000處獲取棧頂指標MSP(預設使用主堆疊),從0x00000004處獲取程式計數器PC(復位向量)。則印證了上述說法。

下面通過追蹤STM32L1xx標準外設庫V1.2.0(STM32L1xx_StdPeriph_Lib_V1.2.0)中的啟動檔案startup_stm32l1xx_md.s來驗證上述說法。

先復位CPU,從暫存器視窗可以看到:
這裡寫圖片描述
R13(SP)的值為0x20000FC0(MSP),R15(PC)的值為0x08000420。這兩個值就是地址0x00000000和地址0x00000004處存放的內容。由於是從Flash啟動,所以,實際上也就是0x08000000和0x08000004處存放的內容。可以從記憶體視窗中看出:
這裡寫圖片描述

這裡寫圖片描述

從0x00000000處,取出1個字(32位,4個位元組),為0x20000FC0,是堆疊指標SP的值。

從0x00000004處,取出1個字(32位,4個位元組),為0x08000421,而PC指標讀回0x08000420

它把末位的1變成了0,這個是由於記憶體對齊造成的,因為cortex-m3核PC的LSB一定讀回0,因此指令至少是半字對齊的(《cortex-m3程式設計手冊》)。

基於上面分析,可以總結STM32啟動的大體過程。

1、上電覆位,CPU從0x00000000處獲取棧頂指標MSP(預設使用主堆疊),從0x00000004處獲取程式計數器PC(復位向量)。

2、MSP指標必然指向SRAM區的,因為堆疊必須建立在該區。

3、根據PC的值找到復位中斷處理函式Reset_Handler

4、呼叫SystemInit函式。

5、呼叫__main函式,初始化使用者堆疊

6、呼叫main函式,進入C語言環境
這裡寫圖片描述

相關文章