前言
如果對硬體任務核心切換不感興趣的同學可以跳過。
由於任務原始碼分析開始涉及到介面層,所以在學習原始碼前,先了解下posix介面層的設計。
本系列介面層會講解兩個:
- posix標準介面。因為本教程demo在linux上跑freertos時實際使用的就是這個介面。
- cortex m3/m4架構介面。因為這才是真正設計到ARM架構硬體的介面。且,這個網上資料較多,看不懂本作者的筆記也可以找度娘輔助分析。
強烈建議:
- 涉及到介面,建議找到對應的架構權威指南學習,掌握底層原理。
- 對於指向學習系統應用的同學,快速移植,直接在freertos原生程式碼中找到結構層進行替換即可。
參考:
- ARM開發官網:http://infocenter.arm.com/
- 《The Definitive Guide to Arm Cortex-M3 and Cortex-M4 Processors_c.pdf》
- 李柱明部落格:https://www.cnblogs.com/lizhuming/p/16062486.html
posix 標準介面層設計
模擬器不涉及到CPU暫存器組。
模擬器的系統心跳
RTOS系統週期是使用ITIMER生成的,並且訊號僅被傳遞給當前執行的pthread。
RTPS系統滴答訊號處理器增加滴答計數,並選擇下一個RTOS任務上下文。
它恢復該執行緒,並向自己傳送一個訊號來暫停。
掛起僅在系統滴答訊號處理程式退出時進行處理,因為訊號已排隊。
模擬器的task底層實質
FreeRTOS模擬器的實現是簡單地包裝平臺本地執行緒,所有切換任務上下文的呼叫將呼叫OS掛起和恢復執行緒API。
這個模擬器使用Posix條件變數和Signals來控制底層Posix執行緒的執行。
訊號可以非同步地傳遞給執行緒,這樣它們就會中斷目標執行緒的執行,而掛起的執行緒則會等待條件變數恢復。
模擬器的任務切換原理
當一個新的Task被建立時,一個pthread被建立為Task的執行上下文。
pthread立即掛起自己,並將執行返回給建立者。
當一個pthread掛起時,它正在pthread_cond_wait呼叫中等待,這個呼叫被阻塞,直到它收到一個恢復訊號pthread_cond_signal。
任務可以通過協作呼叫taskYIELD()或RTOS系統Tick排程兩種方式。
在這個模擬器中,通過恢復下一個任務上下文(由FreeRTOS Scheduler決定)和掛起當前上下文(兩者之間進行簡短的握手)來切換Task上下文。
cortex M3/M4異常處理
參考:《The Definitive Guide to Arm Cortex-M3 and Cortex-M4 Processors_c.pdf》
讀者可以翻看cortex m3/m4的權威指南檢視更多細節即可,本教程只粗略說明下異常時棧幀的動態過程。
CPU暫存器組可自行百度。
雙堆疊指標
Cortex-M3核心有兩個堆疊指標:
- MSP:主堆疊指標,是給系統棧空間使用的。
- PSP:程式堆疊指標,是給任務棧使用的。
在FreeRTOS任務中,所有棧空間的使用都是通過PSP指標進行指向的。
一旦進入了中斷函式以及可能發生的中斷巢狀都是用的MSP指標。
雙操作模式
Cortex-M3支援兩種操作模式(handler模式和thread模式),這兩種模式是為了區別正在執行程式碼的型別:
- handler模式為異常處理程式的程式碼。
- 執行緒模式為普通應用程式的程式碼。
棧幀
異常後硬體壓棧部分:
- 下圖描述的是啟用或需要雙字棧對齊調整時,Cortex-M3或Cortex-M4處理器(不帶浮點)的棧幀。
- 雙字棧對齊這個特性是AAPCS規則的一個要求,意思是棧指標的數值在函式入口或出口處應該是雙字對齊,若未對齊,異常硬體壓棧時會自動插入一個字來保證雙字對齊。(瞭解即可)
注意,異常時硬體壓棧的LR值和函式呼叫時的函式棧幀中的LR值是不一樣的,具體可以瞭解下EXC_RETURN。
EXC_RETURN
進入異常服務程式以後,LR的值被自動更新為特殊的EXC_RETURN
(只有[3:0]位有意義,其他位都為1)。如圖說明:
位段 | 意義 |
---|---|
3 | 0:返回後進入Handler模式 1:返回後進入執行緒模式 |
2 | 0:從主堆疊中執行出棧操作,返回後使用MSP 1:從程式棧中執行出棧操作,返回後使用PSP |
1 | 保留,必須為0 |
0 | 0:返回ARM狀態 1:返回Thumb狀態(在CM3中必須為1) |
有效值如下:
如主程式線上程模式下執行,並且在使用PSP時被中斷,則在服務程式中LR=0xFFFFFFFD(主程式被打斷前LR已被自動入棧)。
異常及異常巢狀時LR動態及棧指標使用過程:下圖是執行緒模式使用程式棧為基礎: