最近難得有點空閑時間, 就來講講 STM32 上任務調度的策略吧。
在我的認知中, 最基本的任務調度無非有兩種方式:

  • 利用 system tick 的中斷計數
  • 保存上下文, 利用中斷進行上下文切換

這麽簡單概括肯定不方便理解, 一次講不完肯定要分兩次 (挖坑)。那這次就先來説説 system tick 的方式吧。

什麽是 system tick

這是一個 24 位的系統節拍定時器, 具有自動重載和溢出中斷功能,
所有基於 Cortex Profile M 的微控制器都可以由這個定时器獲得一定的時間間隔。

它每隔一段時間會產生一次中斷, 一般使用 1ms 為佳,
STM32 的 HAL 庫會使用 HAL_IncTick 來更新系統時間計數, 它就相當於整個單片機系統的心臟。

1
2
3
4
5
6
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void) {
HAL_IncTick();
}

HAL_Delay 它的内部就使用 system tick 來實現等待,
就連 HAL 庫中阻塞調用外設的接口也是使用它來進行超時檢測的。

基於 system tick 任務調度的實現

在知道它之後, 我們來開始講怎麽去用它實現任務調度。
我們需要擬定一下它整個運作的生命周期:

img

如上圖所示, 我們需要在中斷中遞增 tick_inc,
並在主循環中每次遍歷任務之前保存它並重置計數。 因爲中斷隨時會發生, 所以這一步要越快越好。
在遍歷中逐個減少任務的剩餘時間, 當有任務的剩餘時間為 0 或者小於 0 時, 執行該任務並重置它的剩餘時間。

這個模型的好處有

  • 穩定可靠
  • 編寫和使用簡單
  • 平台相關程式碼少, 移植方便快捷
  • 非搶占模型, 不會發生資源衝突

缺點如下

  • 無法保證調度實時性
  • 任務過多容易造成性能瓶頸

囉嗦) 關於不能保證任務實時性

因爲執行任務的時候必定會消耗一定的時間, 如果此時單片機處理速度較慢且任務間隔時間小,
則會造成任務堆積導致卡頓或者響應速度變慢。

所以在使用時應提高間隔時間, 盡可能降低調度壓力。

囉嗦) 與 RTOS 的不同

實際上它跟 RTOS 的任務調度方式不是一種東西, 它的任務並非「綫程」。
因爲不需要進行上下文切換, 且任務之間不是並行的關係, 因此也不存在資源競爭。

C 語言中的實現

本程式碼經過測試, 運行穩定。

寫到最後

如果有任何意見或者問題或是錯誤或遺漏, 請在下方評論區留言。謝謝 (๑•̀ㅂ•́)و✧

引用

  1. STM32知识:什么是SYSTICK 作用是什么