【freertos】002-posix模擬器設計與cortex m3異常處理

李柱明發表於2022-03-27

前言

如果對硬體任務核心切換不感興趣的同學可以跳過。

由於任務原始碼分析開始涉及到介面層,所以在學習原始碼前,先了解下posix介面層的設計。

本系列介面層會講解兩個:

  1. posix標準介面。因為本教程demo在linux上跑freertos時實際使用的就是這個介面。
  2. cortex m3/m4架構介面。因為這才是真正設計到ARM架構硬體的介面。且,這個網上資料較多,看不懂本作者的筆記也可以找度娘輔助分析。

強烈建議:

  1. 涉及到介面,建議找到對應的架構權威指南學習,掌握底層原理。
  2. 對於指向學習系統應用的同學,快速移植,直接在freertos原生程式碼中找到結構層進行替換即可。

參考:

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動態及棧指標使用過程:下圖是執行緒模式使用程式棧為基礎:

相關文章