STM32啟動過程解讀與跟蹤驗證
本文轉載自: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語言環境
相關文章
- PostgreSQL 原始碼解讀(15)- Insert語句(執行過程跟蹤)SQL原始碼
- STM32記憶體分佈,啟動過程及bootloader記憶體boot
- Oracle開始啟動Java版本許可證的跟蹤審查 - theregisterOracleJava
- spring原始碼閱讀--容器啟動過程Spring原始碼
- 服務啟動過程效能波動的分析與解決方案
- 視覺化程式碼跟蹤除錯與STM32應用設計視覺化除錯
- 報表開啟慢跟蹤難?可通過效能監控快速解決
- sp_trace_setfilter sqlserver篩選跟蹤或跟蹤過濾FilterSQLServer
- SOFAJRaft原始碼閱讀-模組啟動過程Raft原始碼
- MYSQL sql執行過程的一些跟蹤分析(一)MySql
- HTTPS加密過程和TLS證書驗證HTTP加密TLS
- spring security 認證原始碼跟蹤Spring原始碼
- SpringBoot啟動過程Spring Boot
- Windows 啟動過程Windows
- Service啟動過程
- Java原始碼跟蹤閱讀技巧Java原始碼
- Android系統啟動流程(四)Launcher啟動過程與系統啟動流程Android
- App 啟動過程(含 Activity 啟動過程) | 安卓 offer 收割基APP安卓
- iOS App啟動過程iOSAPP
- Android App啟動過程AndroidAPP
- SpringBoot 系列-啟動過程Spring Boot
- jmeter 啟動過程剖析JMeter
- Liferay 啟動過程分析
- main的啟動過程AI
- Spring Boot 啟動過程Spring Boot
- Angular的啟動過程Angular
- Spring啟動過程(一)Spring
- Linux 啟動過程分析Linux
- MYSQL sql執行過程的一些跟蹤分析(二.mysql優化器追蹤分析)MySql優化
- 命案偵破過程揭示Google能夠跟蹤全世界的手機Go
- httpd使用systemctl啟動超時解決過程httpd
- fabric網路環境啟動過程詳解
- APT組織跟蹤與溯源APT
- Git跟蹤與提交檔案Git
- [20211013]閱讀ldd原始碼跟蹤.txt原始碼
- vagrant啟動身份驗證失敗的解決方式
- DrissionPage 過滑動驗證碼
- 淺讀tomcat架構設計和tomcat啟動過程(1)Tomcat架構