- RTOS多任務運行
- Cortex-M4對於多任務運行的硬件架構支持特性
最近研究FreeRTOS的內核源碼,產生了一個疑問?
//創建開始任務
xTaskCreate((TaskFunction_t )start_task, //任務函數
(const char* )"start_task", //任務名稱
(uint16_t )START_STK_SIZE, //任務堆棧大小
(void* )NULL, //傳遞給任務函數的參數
(UBaseType_t )START_TASK_PRIO, //任務優先級
(TaskHandle_t* )&StartTask_Handler); //任務句柄
//創建TASK1任務
xTaskCreate((TaskFunction_t )malloc_task,
(const char* )"malloc_task",
(uint16_t )MALLOC_STK_SIZE,
(void* )NULL,
(UBaseType_t )MALLOC_TASK_PRIO,
(TaskHandle_t* )&MallocTask_Handler);
vTaskDelete(StartTask_Handler); //刪除開始任務
只要通過FreeRTOS提供的任務創建函數API就能夠運行我們應用層寫的代碼。換句話說,FreeRTOS是怎麼找到我們寫的代碼,然後進行運行的呢?首先看一下任務創建函數聲明:
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
參數說明如下:
pxTaskCode:我們應用程序編寫的任務函數指針;
pcName:任務的名字,應用層自己設定;
usStackDepth:每一個任務堆棧的深度,我們這裏是32位MCU,那麼堆棧深度爲usStackDepth*4字節;
pvParameters:執行的任務函數時傳遞的參數;
uxPriority:任務的優先級;
pxCreatedTask:任務句柄,實際就是指向任務控制塊指針。
在這裏我要用兩篇博客進行探究上述問題。其中,第一篇會從MCU硬件架構方面是怎麼能夠支持上述功能的(這裏分析的是STM32F407 MCU,該MCU是基於Cortex-M4架構);第二篇會實際分析FreeRTOS具體實現方法。
一、RTOS多任務運行
實時操作系統RTOS可用於處理任務調度,它是將處理時間分爲多個時間片且將時間片分配給所需的任務,實現多個任務同時執行。需要一個定時器記錄RTOS中每個人物的運行時間,當時間到之後就會觸發任務調度器執行上下文切換,轉而執行其他任務。
二、Cortex-M4對於多任務運行的硬件架構支持特性
1、寄存器組
Cortex-M4處理器的寄存器組中含有16個寄存器,其中13個是32位通用目的寄存器,3個特殊寄存器。
1)R0~R12
前8個被稱作低寄存器,由於指令中可用的空間有限,許多16位指令只能訪問低寄存器。後面4個寄存器被稱爲高寄存器,可以用於32位指令和幾個16位指令。
2)R13,棧指針(SP)
可以通過PUSH和POP操作實現棧存儲的訪問,其實在物理上會有兩個棧指針。MSP被稱爲主棧指針,復位後或者處於處理模式時會使用該針;PSP進程棧指針,只能用於線程模式。在進行PUSH和POP時候總是32位,棧操作的地址必須對齊到32位的字邊界上。一般如果我們的應用程序中沒有涉及到嵌入式OS是不會用到PSP寄存器的,但是如果用到嵌入式OS就必須設置PSP。
3)R14,連接寄存器(LR)
函數或者子程序調用時返回地址的保存,在函數或者子程序結束時,程序控制可以通過將LR的數值加載到PC寄存器中實現返回調用的程序。***當執行函數或者子程序調用後,LR寄存器的數值會自動更新。***因此在調用函數之前要先把LR的數值保存到棧中。
在異常處理期間,LR會被自動更新爲特殊的EXC_RETURN(異常返回)的數值,之後該數值在異常處理結束之後出發異常返回。
4)程序計數器PC
可讀可寫,寫會導致跳轉。
2、EXC_RETURN
處理器進入異常處理或者中斷服務程序時,連接寄存器LR的數值會被更新爲EXC_RETURN。利用BX指令加載到PC寄存器時,該數值就會觸發異常返回機制。由於地址區域0xF0000000~0xFFFFFFFF被架構定義爲不可執行,這樣不會帶來問題。
3、影子棧指針
由於在物理上採用兩個棧指針寄存器,因此可以將處理器處於不同模式下使用不同的棧指針,這樣我們在內核和異常處理狀態下使用MSP,在普通任務下使用PSP,使得應用層與內核層完全分離。當我們應用層的代碼出現BUG可以減少對內核層代碼的影響,保證了軟件的健壯性。
5)SVC異常
由SVC指令觸發,異常類型爲11,並且優先級是可編程的。利用SVC可以實現應用任務訪問系統資源的API,如下圖所示:
在FreeRTOS中使用SVC異常從出初始化切換到調度第一個任務。
總結:本文主要介紹了Cortex-m4對於RTOS支持的硬件特性,下一篇文章將會介紹FreeRTOS是怎樣利用這些特性開啓第一個任務的。