1. 在ARM Cortex-M3架構中,堆棧通常由兩個寄存器來管理:主堆棧指針(MSP)和進程堆棧指針(PSP)。
1.1.?MSP是處理器的默認堆棧指針,用于保存中斷處理程序的現場。當芯片復位或發生中斷時,處理器會自動將MSP的值保存到堆棧中,并使用一個新的堆棧來保存中斷處理程序的現場。MSP的值可以通過專門的寄存器進行讀寫,以便在需要時進行堆棧切換。
1.2. PSP是用于保存應用程序現場的堆棧指針。在應用程序執行期間,PSP用于保存當前執行線程的現場。當發生中斷時,處理器會自動將PSP的值保存到堆棧中,并使用MSP來保存中斷處理程序的現場。PSP的值也可以通過專門的寄存器進行讀寫,以便在需要時進行堆棧切換。

1.3. 其實說白了就是如果你跑的是裸機程序,他用的就是一個堆棧的機制,就是只跑MSP的堆棧。但是如果你要跑操作系統,他就要用到雙堆棧機制,比如程序正在順序執行,突然產生一個中斷,處理器把TASK的信息現場保存在PSP棧中,然后進入中斷服務程序,中斷服務程序中使用MSP棧,退出中斷時從PSP棧中還原現場,返回用戶程序。還有就是TASK的切換也是在PSP里切的,比如在一個時間片里TASK1沒有執行完,他就會把TASK的現場保存在PSP棧中,之后執行TASK2,當TASK2執行完后,在還原PSP棧中TASK1的現場繼續執行。
1.4 堆棧是一種用于保存函數調用現場和局部變量的數據結構,它的操作是先進后出(Last-In-First-Out,LIFO)。棧幀(stack frame)是在函數調用期間在堆棧上分配的一塊內存區域,用于存儲函數的局部變量、參數和返回地址等信息。在函數調用過程中,每個函數都會分配一個新的棧幀,用于保存它的執行上下文。當函數返回時,棧幀被彈出堆棧,釋放內存空間,并將控制權返回給調用者。所以說白了棧就是嵌入式RAM的一塊連續內存空間,當程序執行時,會將相關數據壓入棧中,棧指針會向下移動,分配新的內存空間。當函數執行出棧操作時,棧指針會向上移動,釋放內存空間。
2. 上面說的是Cortex-M3內核的指針堆棧寄存器,但是TC397與Cortex-M3不同,他是有5個核,每個核都有自己的堆棧空間,它分為內核堆棧(core stack)和用戶堆棧(user stack)和中斷堆棧(interrupt stack)。如下圖,下圖沒有說內核堆棧(core stack),是因為(core stack)是用于跑OS的。內核堆棧用于保存操作系統內核的執行上下文,而用戶堆棧用于保存應用程序的執行上下文。中斷棧(interrupt stack)則是用于保存中斷處理程序執行上下文的堆棧空間。上面說的3個堆??臻g,其實就是說在跑操作系統和中斷的時候用的是MSP,跑任務,用的用戶堆棧,也就是PSP。所謂的內核堆棧和用戶堆棧是基于OS的堆棧指針的指向是根據當前處理器所處的模式(特權模式或用戶權模式)來確定的。
2.1 在特權模式下,處理器可以訪問所有的處理器資源和指令,包括特殊的系統寄存器、中斷控制器、內存管理單元等。也就是說,在特權模式下,處理器可以訪問用戶模式下的堆棧。處理器可以使用PSP指針來訪問用戶堆棧,并讀取或寫入用戶堆棧上的數據。
2.2 而在用戶模式下,處理器只能訪問受限的處理器資源和指令。用戶模式下,處理器只能訪問用戶的數據和代碼,無法訪問系統的關鍵資源。這樣可以確保用戶代碼不會對系統的穩定性和安全性產生影響。
也就是說內核堆棧是在特權模式下,并且用的MSP,但是他可以方訪問PSP。而中斷也是在特權模式下的MSP里,可以方訪問PSP。用戶堆棧就是在非特權模式下只能用的PSP。
?2.3 因為中斷和異常處理通常需要訪問操作系統內核代碼和資源,而這些資源只能在特權模式下訪問,所以中斷堆棧必須位于特權模式下。
?2.4 中斷堆棧包含了一些重要的信息,如 CPU 寄存器、程序計數器、堆棧指針等,這些信息用于在中斷或異常處理完成后恢復原來的執行上下文。
2.5 內核堆棧和用戶堆棧用于保存執行上下文,中斷堆棧用于保存中斷處理程序的執行上下文。



除此之外還有三個寄存器,一個是SP也就是A[10],一個ISP,還有一個PSW.
A[10]:這個就在GPR中,也稱之為SP(Stack Pointer),與傳統內核的SP類似.如下圖:

ISP:在CSFR中,專用于中斷的Stack.進入中斷后自動切換使用ISP,以防止對主任務Stack的誤操作.
PSW中的IS用于標記當前Stack Pointer狀態. PSW.IS==0時,表示Upper Context已經被保存,A10(SP)已經裝入ISP的值.當PSW.IS==1時,表示已經使用的ISP的值(比如中斷嵌套),此時SP已經是ISP的值,無須再裝入ISP的值.

3. 代碼中的堆棧

3.1 棧(操作系統):存局部變量、函數,調用函數時會開辟棧區,函數結束時就自動回收,遵循后進先出的原則,從高地址向低地址增長。
靜態內存分配:靜態內存是程序編譯執行后系統自動分配,由系統自動釋放,靜態內存是棧分配的,特點:不持久。
使用靜態內存分配的變量有:全局變量&靜態變量
3.2 堆(操作系統): malloc、realloc、calloc等開辟的內存就在堆,從低地址向高地址增長,由程序員分配和釋放,系統不自動回收,所以一定要記得申請了就要釋放,以免溢出。
在嵌入式系統中,使用堆內存相對于棧內存來說是比較少的。嵌入式系統通常擁有有限的內存資源,而使用堆內存可能會導致內存碎片和性能問題。在嵌入式系統中,通常會限制堆內存的大小,并且使用堆內存時需要非常小心,以確保不會出現內存泄漏或者堆溢出等問題。在某些情況下,嵌入式系統需要使用堆內存,例如當需要動態創建對象或者動態分配數組時。在這種情況下,程序員需要小心地管理堆內存,以確保不會出現內存泄漏或者堆溢出等問題。
動態內存分配:動態內存是開發者手動分配的,是堆分配的。特點:持久。
在C語言中,全局變量分配在內存中的靜態存儲區,非靜態的局部變量【動態局部變量】(包括形參)是分配在內存的動態存儲區,該存儲區被稱為棧。除此之外,c語言還允許建立內存動態分配區域,以存放一些臨時用的數據,這些數據不必在程序的聲明部分定義,也不必等到函數結束時才釋放,而是需要時隨時開辟,不需要是隨時釋放。這些數據臨時存在一個特別的自由存儲區,稱為堆區。
4. 如何調試

————————————————? ? ? ? ? ? ? ? ? ? ? ?
原文鏈接:https://blog.csdn.net/xiandang8023/article/details/131724885
End
「汽車電子嵌入式在CSDN上同步推出AUTOSAR精進之路專欄,本專欄每個模塊完全按實際項目中開發及維護過程來詳細介紹。模塊核心概念介紹、實際需求描述、實際工程配置、特殊需求介紹及背后原理、實際工程使用經驗總結。目的是讓讀者看完每一個章節后能理解原理后根據需求完成一個模塊的配置或者解決一個問題。」
點擊文章最后左下角的閱讀原文可以獲取更多信息
或者復制如下鏈接到瀏覽器獲取更多信息
https://blog.csdn.net/qq_36056498/article/details/132125693
文末福利
2.為便于技術交流,創建了汽車電子嵌入式技術交流群,可盡情探討AP,CP,DDS,SOME/IP等前沿熱點話題,后臺回復“加群”即可加入;
注:本文引用了一些第三方工具和文檔,若有侵權,請聯系作者刪除!
推薦閱讀
汽車電子嵌入式精彩文章匯總第一期:20210530-20230703
汽車電子嵌入式精彩文章匯總第2期
TC3xx芯片GTM模塊-CMU,CCM,TBU詳解
TC3xx芯片GTM模塊-TOM詳解
AUTOSAR架構下PWM模塊配置實踐
TC3xx芯片GTM模塊-TIM詳解
AUTOSAR架構下ICU模塊配置實踐
TC3xx芯片電源管理系統PMS詳解
TC3xx DMA模塊詳解
TC3xx芯片SMU模塊詳解
如何監控TC3xx芯片PFlash的ECC錯誤
TC3xx芯片RAM的錯誤檢測
TC3xx芯片的總線內存保護
AUTOSAR架構下MCAL Modules軟件分區問題分析
AUTOSAR架構下內部看門狗復位檢測
TC3xx芯片時鐘監控
TC3xx芯片電壓監控和溫度監控
嵌入式基礎:環形緩沖區ring buffer
【OS】AUTOSAR架構下的中斷和異常向量表
【OS】AUTOSAR Os是如何啟動第一個Task的
編譯鏈接專題第1篇-make和makefile介紹
編譯鏈接專題第2篇-初識makefile結構
編譯鏈接專題第3篇-初識makefile中的偽目標
編譯鏈接專題第4篇-變量和變量的不同賦值方式
編譯鏈接專題第5篇-預定義變量的使用
編譯鏈接專題第6篇-變量的高級主題(上)
編譯鏈接專題第7篇-變量的高級主題(下)
編譯鏈接專題第8篇-條件判斷語句
End
歡迎點贊,關注,轉發,在看,您的每一次鼓勵,都是我最大的動力!
汽車電子嵌入式
微信掃描二維碼,關注我的公眾號