使用過cortex-M4內核單片機的朋友對下面這張圖一定不會感到陌生,它是ST原廠手冊里面的memory map,里面的信息量其實非常多,今天簡單說明一部分。
我們在編寫stm32代碼的時候最長使用的地址有兩塊,第一塊是0x0000 0000~0x3FFF FFFF,
第二塊是0x4000 0000~0x5003 FFFF。注意,第二塊地址是我們APB與AHB總線上面掛載著的各種外設的物理地址,我們想要操作外設就是配置這些寄存器地址。我們今天討論的內存是第一塊兒,可供我們進行數據存儲的內存。
首先0x000 000~0x0007 FFFF并不可以用來進行用戶數據存儲,這一段固化的代碼作用是根據BOOT引腳輸入的電平高低來決定將Flash memory、System memory還是SRAM的首地址映射到起始位置。
那么在真正可供我們操作的內存空間中,首先我們來討論SRAM,SRAM只要芯片沒有下電就可以一直存儲數據(除非軟失效等情形發生)。
Option bytes主要可以設置對 Flash 存儲器的讀寫保護級別,防止未經授權的程序對 Flash 中的代碼和數據進行讀取或修改,保障程序和數據的安全性。
System memory里面存儲著ST原廠編寫的bootloader,當我們無法通過工具鏈下載代碼時,可以通過改變boot引腳高低電平的方式選擇使用該段內存中的bootloader。我們經常使用的串口升級代碼也存儲在這一段內存中。
我們平時下載的代碼主要就存儲在0x0800 0000~0x0807 FFFF中,這512K的內存又可以分為兩部分,代碼.text段和數據.rodata段。這段內存的第一個字節(0x08000 0000~0x0800 0003)存儲著至關重要的MSP指針(棧底指針);第二個字節裝著PC指針,PC指針指向了我們的復位函數。
下面介紹SRAM的作用,首先最底部的.data段的數據來源自上圖用戶代碼的.rodatda。那么我們在編程中如何定義變量會導致數據被存儲在.data段內部呢?下面介紹了兩種特定值可修改的變量定義方式。
int cnt3=1;
fun1(void)
{static int cnt=1;
}
其次.bss段存儲兩類內容,一類是FreeRTOS中的heap size,另外一類是其他未初始化或者初始化為0的可修改變量;第二類又可以分為3小類,第一類是如同下文中cnt那樣的未初始化全局變量,第二類是初始化為0的全局變量,第三類是靜態的局部變量。
int cnt;
int cnt1=0;
int fun1(char *argv)
{static int cnt2;}
.s文件中映射單片機堆棧中的數據,msp指針向下壓入數據,當msp向下生長影響到隊時就會在造成棧溢出。堆中的數據則是用malloc手動分配。
那么在移植freertos的過程中,動態創建的任務與靜態創建的任務分別都被存儲在了哪里?都在.bss段中的freertos_heap_size中。
下面討論上下文堆棧:
cortex-M內核擁有雙堆棧機制,除了MSP指針外還有一個PSP指針。在 Cortex-M 內核中,PSP(Process Stack Pointer,進程棧指針)是專門用于應用任務(用戶任務)的棧指針,與 MSP(Main Stack Pointer,主棧指針)配合實現了內核與用戶任務的棧空間分離,是支持實時操作系統(如 FreeRTOS)多任務管理的核心機制之一。
機制原理
棧指針的分離設計
Cortex-M 內核有兩個棧指針:- MSP(主棧指針):默認用于內核模式(如中斷服務程序、異常處理、內核代碼),復位后默認使用 MSP。
- PSP(進程棧指針):僅用于用戶模式(應用任務),由用戶任務代碼使用。
內核通過CONTROL 寄存器的 bit [1] 控制當前使用的棧指針:
CONTROL[1] = 0
:使用 MSP(內核模式默認)。CONTROL[1] = 1
:使用 PSP(用戶任務運行時)。
任務切換時的 PSP 作用
當發生任務切換(如由調度器觸發)時:- 內核先將當前任務的寄存器狀態(R0-R15 等)壓入該任務的 PSP 所指向的棧空間(保存上下文)。
- 然后加載下一個任務的 PSP 值(從該任務的 TCB 中獲取),并從其棧中恢復寄存器狀態(恢復上下文)。
- 最后通過修改 CONTROL 寄存器,使 CPU 切換到 PSP,運行新任務。
核心作用
實現任務棧隔離
每個用戶任務擁有獨立的棧空間(由 PSP 指向),任務間的棧數據互不干擾,避免了多任務運行時的棧沖突,提高了系統穩定性。支持實時操作系統的多任務調度
操作系統(如 FreeRTOS)通過管理每個任務的 PSP 值(存儲在 TCB 中),實現快速的任務上下文切換,是多任務并發執行的基礎。區分內核與用戶權限
MSP 用于內核和異常處理,PSP 用于用戶任務,配合內核的特權模式機制,實現了系統資源的權限隔離(如某些寄存器僅能在特權模式下訪問)。