引子:
? ? 對于ARMv7-M系列SOC來說,上電后程序復位執行的過程相對來說比較簡單,因為絕大部分芯片,都是XIP(eXecute In Place,就地執行)模式執行程序,不需要通過BooROM->PL(preloader)->SBL(second bootloader)->Kernel這樣的復雜加載過程。XIP的程序復位執行的總體流程如下圖(以STM32F407為例):
階段1:硬件自動初始化
1. SOC上電或復位
當STM32F407上電或接收到復位信號時,芯片開始啟動過程
內部電壓調節器、時鐘系統開始工作
2. CPU讀取地址 0x0000_0000
ARM Cortex-M4內核從內存映射的0x0000_0000地址讀取第一個值
在STM32F407中,這個地址映射到Flash存儲器起始位置(0x0800_0000)
讀取的值被加載到主堆棧指針(MSP)中
3. 加載值到MSP
讀取的32位值作為初始堆棧指針值
堆棧通常設置在RAM的起始位置加上棧大小(如0x2000_0000 + RAM大小)
4. CPU讀取地址 0x0000_0004
CPU繼續讀取下一個32位地址(0x0000_0004)
這個地址包含復位向量的值
5. 加載值到PC(復位向量)
從0x0000_0004讀取的值被加載到程序計數器(PC)
這個值指向Reset_Handler函數的地址
CPU開始執行Reset_Handler處的代碼
階段2:軟件初始化(Reset_Handler)
6. PC跳轉到Reset_Handler()
CPU開始執行啟動文件(如startup_stm32f407xx.s)中的Reset_Handler函數
這是芯片上電后執行的第一段程序代碼
7. 堆棧設置判斷
檢查是否需要設置多堆棧(進程堆棧PSP)
對于大多數應用,只使用主堆棧(MSP)
8. C環境設置
復制.data段從Flash到RAM
將已初始化的全局變量和靜態變量從Flash復制到RAM
使用鏈接器定義的符號:
_sidata
: .data段在Flash中的起始地址_sdata
: .data段在RAM中的起始地址_edata
: .data段在RAM中的結束地址
在RAM中清零.bss段
將未初始化的全局變量和靜態變量所在的內存區域清零
使用鏈接器定義的符號:
_sbss
: .bss段的起始地址_ebss
: .bss段的結束地址
9. 系統初始化
調用SystemInit()函數
在system_stm32f4xx.c文件中定義
關鍵配置:
時鐘配置:啟用PLL,設置系統時鐘為168MHz
總線分頻器:配置AHB、APB1、APB2總線時鐘
Flash延遲:設置Flash等待狀態,確保在高速時鐘下可靠運行
電源控制:配置電源管理相關設置
10. (可選)初始化C庫
如果需要,初始化C標準庫
設置堆(heap)和標準I/O等
階段3:應用程序啟動
11. 跳轉到main()函數
所有初始化完成后,跳轉到用戶編寫的main()函數
此時:
時鐘系統已正確配置
內存已正確初始化
外設寄存器處于默認狀態
12. C應用程序運行
用戶應用程序開始執行
可以安全地初始化外設、創建任務、處理中斷等
STM32F407特定細節
Flash基地址:0x0800_0000
RAM基地址:0x2000_0000(112KB或192KB,取決于型號)
系統時鐘:最高168MHz
向量表:位于Flash起始位置,包含中斷服務例程的地址
? ? 這個啟動過程確保了硬件和軟件環境在main()函數執行前都已正確初始化,為應用程序提供了穩定可靠的運行基礎。