論壇原始地址(持續更新):【安富萊】RTX5核心教學,採用CMSIS-RTOS V2封裝層,已經更新發布至第9章 (2021-12-27) - STM32H7 - 硬漢嵌入式論壇 - Powered by Discuz!
本章節主要為大家講解RTX5任務優先順序設定的注意事項,任務優先順序的分配方案及其相關的一個例子,內容相對比較簡單。
目錄
8.3 任務優先順序設定函數osThreadSetPriority
8.4 任務優先順序獲取函數osThreadGetPriority
RTX5作業系統支援的優先順序設定如下:
/// Priority values.
typedef enum {
osPriorityNone = 0, ///< No priority (not initialized).
osPriorityIdle = 1, ///< Reserved for Idle thread.
osPriorityLow = 8, ///< Priority: low
osPriorityLow1 = 8+1, ///< Priority: low + 1
osPriorityLow2 = 8+2, ///< Priority: low + 2
osPriorityLow3 = 8+3, ///< Priority: low + 3
osPriorityLow4 = 8+4, ///< Priority: low + 4
osPriorityLow5 = 8+5, ///< Priority: low + 5
osPriorityLow6 = 8+6, ///< Priority: low + 6
osPriorityLow7 = 8+7, ///< Priority: low + 7
osPriorityBelowNormal = 16, ///< Priority: below normal
osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1
osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2
osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3
osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4
osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5
osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6
osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7
osPriorityNormal = 24, ///< Priority: normal
osPriorityNormal1 = 24+1, ///< Priority: normal + 1
osPriorityNormal2 = 24+2, ///< Priority: normal + 2
osPriorityNormal3 = 24+3, ///< Priority: normal + 3
osPriorityNormal4 = 24+4, ///< Priority: normal + 4
osPriorityNormal5 = 24+5, ///< Priority: normal + 5
osPriorityNormal6 = 24+6, ///< Priority: normal + 6
osPriorityNormal7 = 24+7, ///< Priority: normal + 7
osPriorityAboveNormal = 32, ///< Priority: above normal
osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1
osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2
osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3
osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4
osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5
osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6
osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7
osPriorityHigh = 40, ///< Priority: high
osPriorityHigh1 = 40+1, ///< Priority: high + 1
osPriorityHigh2 = 40+2, ///< Priority: high + 2
osPriorityHigh3 = 40+3, ///< Priority: high + 3
osPriorityHigh4 = 40+4, ///< Priority: high + 4
osPriorityHigh5 = 40+5, ///< Priority: high + 5
osPriorityHigh6 = 40+6, ///< Priority: high + 6
osPriorityHigh7 = 40+7, ///< Priority: high + 7
osPriorityRealtime = 48, ///< Priority: realtime
osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1
osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2
osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3
osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4
osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5
osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6
osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7
osPriorityISR = 56, ///< Reserved for ISR deferred thread.
osPriorityError = -1, ///< System cannot determine priority or illegal priority.
osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization.
} osPriority_t;
大家設定任務優先順序的時候需要呼叫這些指定的優先順序,其中osPriorityIdle是最低優先順序,供空閒任務使用,而osPriorityRealtime7是最高優先順序。
對於初學者,有時候會糾結任務優先順序設定為多少合適,因為任務優先順序設定多少是沒有標準的。對於這個問題,RTX5有一個推薦的設定標準,任務優先順序設定推薦方式如下圖8.1所示:
圖8.1 任務優先順序分配方案
這裡的優先順序分配方案是RTX作業系統推薦的一種方式,實際專案也可以不採用這種方法。偵錯出適合專案需求的才是最好的。
函數原型:
osStatus_t osThreadSetPriority(osThreadId_t thread_id,
osPriority_t priority )
函數描述:
此函數用於修改任務的優先順序。
函數引數:
1、 第1個引數填任務的ID。
2、 第2個引數是任務優先順序。
3、 返回值:
使用舉例:
/*
**********************************************************************************************************
變數
**********************************************************************************************************
*/
static uint64_t AppTaskUserIFStk[512/8]; /* 任務棧 */
/* 任務控制程式碼 */
OS_TID HandleTaskUserIF = NULL;
/*
*********************************************************************************************************
* 函 數 名: AppTaskChangePrio
* 功能說明: 修改任務優先順序
* 形 參: 無
* 返 回 值: 無
*********************************************************************************************************
*/
static void AppTaskDelete (void)
{
HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF, /* 任務函數 */
1, /* 任務優先順序 */
&AppTaskUserIFStk, /* 任務棧 */
sizeof(AppTaskUserIFStk)); /* 任務棧大小,單位位元組數 */
if(os_tsk_prio(HandleTaskLED, 3) == OS_R_OK)
{
printf("任務AppTaskLED優先順序修改成功\r\n");
}
else
{
printf("任務AppTaskLED優先順序修改失敗\r\n");
}
}
函數原型:
osPriority_t osThreadGetPriority (osThreadId_t thread_id )
函數描述:
此函數用於獲取任務的優先順序。
函數引數:
1、 第1個引數填任務的ID。
2、 返回值:
使用舉例:
/*
**********************************************************************************************************
變數
**********************************************************************************************************
*/
static uint64_t AppTaskUserIFStk[512/8]; /* 任務棧 */
/* 任務控制程式碼 */
OS_TID HandleTaskUserIF = NULL;
/*
*********************************************************************************************************
* 函 數 名: AppTaskChangePrio
* 功能說明: 修改任務優先順序
* 形 參: 無
* 返 回 值: 無
*********************************************************************************************************
*/
static void AppTaskDelete (void)
{
HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF, /* 任務函數 */
1, /* 任務優先順序 */
&AppTaskUserIFStk, /* 任務棧 */
sizeof(AppTaskUserIFStk)); /* 任務棧大小,單位位元組數 */
if(os_tsk_prio(HandleTaskLED, 3) == OS_R_OK)
{
printf("任務AppTaskLED優先順序修改成功\r\n");
}
else
{
printf("任務AppTaskLED優先順序修改失敗\r\n");
}
}
配套例子:
V5-404_RTX5 Task Priority
實驗目的:
實驗內容:
AppTaskUserIF任務 : 按鍵訊息處理。
AppTaskLED任務 : LED閃爍。
AppTaskMsgPro任務 : 訊息處理。
AppTaskStart任務 : 啟動任務,也是最高優先順序任務,這裡實現按鍵掃描。
osRtxTimerThread任務 : 定時器任務,暫未使用。
串列埠列印資訊:
波特率 115200,資料位 8,奇偶校驗位無,停止位 1。
RTX設定:
RTX設定向導詳情如下:
System Configuration
全域性動態記憶體,這裡設定為32KB。
系統時鐘節拍,這裡設定為1KHz。
Thread Configuration
預設的任務棧大小,這裡設定為1024位元組
RTX5任務偵錯資訊:
程式設計:
任務棧大小分配:
全部獨立設定,沒有使用RTX5預設設定:
/*
**********************************************************************************************************
變數
**********************************************************************************************************
*/
/* 任務的屬性設定 */
const osThreadAttr_t ThreadStart_Attr =
{
/* 未使用 */
// .cb_mem = &worker_thread_tcb_1,
// .cb_size = sizeof(worker_thread_tcb_1),
// .stack_mem = &worker_thread_stk_1[0],
// .stack_size = sizeof(worker_thread_stk_1),
// .priority = osPriorityAboveNormal,
// .tz_module = 0
.name = "osRtxStartThread",
.attr_bits = osThreadDetached,
.priority = osPriorityHigh4,
.stack_size = 2048,
};
const osThreadAttr_t ThreadMsgPro_Attr =
{
.name = "osRtxMsgProThread",
.attr_bits = osThreadDetached,
.priority = osPriorityHigh3,
.stack_size = 1024,
};
const osThreadAttr_t ThreadLED_Attr =
{
.name = "osRtxLEDThread",
.attr_bits = osThreadDetached,
.priority = osPriorityHigh2,
.stack_size = 512,
};
const osThreadAttr_t ThreadUserIF_Attr =
{
.name = "osRtxThreadUserIF",
.attr_bits = osThreadDetached,
.priority = osPriorityHigh1,
.stack_size = 1024,
};
系統棧大小分配:
RTX5初始化:
/*
*********************************************************************************************************
* 函 數 名: main
* 功能說明: 標準c程式入口。
* 形 參: 無
* 返 回 值: 無
*********************************************************************************************************
*/
int main (void)
{
/* HAL庫,MPU,Cache,時鐘等系統初始化 */
System_Init();
/* 核心開啟前關閉HAL的時間基準 */
HAL_SuspendTick();
/* 核心初始化 */
osKernelInitialize();
/* 建立啟動任務 */
ThreadIdStart = osThreadNew(AppTaskStart, NULL, &ThreadStart_Attr);
/* 開啟多工 */
osKernelStart();
while(1);
}
RTX5任務建立:
/*
*********************************************************************************************************
* 函 數 名: AppTaskCreate
* 功能說明: 建立應用任務
* 形 參: 無
* 返 回 值: 無
*********************************************************************************************************
*/
static void AppTaskCreate (void)
{
ThreadIdTaskMsgPro = osThreadNew(AppTaskMsgPro, NULL, &ThreadMsgPro_Attr);
ThreadIdTaskLED = osThreadNew(AppTaskLED, NULL, &ThreadLED_Attr);
ThreadIdTaskUserIF = osThreadNew(AppTaskUserIF, NULL, &ThreadUserIF_Attr);
}
四個RTX任務的實現:
/*
*********************************************************************************************************
* 函 數 名: AppTaskUserIF
* 功能說明: 按鍵訊息處理
* 形 參: 無
* 返 回 值: 無
* 優 先 級: osPriorityHigh1 (數值越小優先順序越低,這個跟uCOS相反)
*********************************************************************************************************
*/
void AppTaskUserIF(void *argument)
{
uint8_t ucKeyCode;
while(1)
{
ucKeyCode = bsp_GetKey();
if (ucKeyCode != KEY_NONE)
{
switch (ucKeyCode)
{
/* K1鍵按下,設定任務優先順序為osPriorityHigh */
case KEY_DOWN_K1:
printf("K1鍵按下,設定任務 HandleTaskLED的優先順序為osPriorityHigh\r\n");
osThreadSetPriority(ThreadIdTaskLED, osPriorityHigh);
printf("任務ThreadIdTaskLED的優先順序 = %d\r\n",osThreadGetPriority(ThreadIdTaskLED));
break;
/* K2鍵按下,設定任務優先順序為osPriorityHigh2 */
case KEY_DOWN_K2:
printf("K2鍵按下,設定任務 HandleTaskLED的優先順序為osPriorityHigh2\r\n");
osThreadSetPriority(ThreadIdTaskLED, osPriorityHigh2);
printf("任務ThreadIdTaskLED的優先順序 = %d\r\n", osThreadGetPriority(ThreadIdTaskLED));
break;
/* 其他的鍵值不處理 */
default:
break;
}
}
osDelay(20);
}
}
/*
*********************************************************************************************************
* 函 數 名: AppTaskLED
* 功能說明: LED閃爍。
* 形 參: 無
* 返 回 值: 無
* 優 先 級: osPriorityHigh2
*********************************************************************************************************
*/
void AppTaskLED(void *argument)
{
const uint16_t usFrequency = 200; /* 延遲週期 */
uint32_t tick;
/* 獲取當前時間 */
tick = osKernelGetTickCount();
while(1)
{
bsp_LedToggle(2);
/* 相對延遲 */
tick += usFrequency;
osDelayUntil(tick);
}
}
/*
*********************************************************************************************************
* 函 數 名: AppTaskMsgPro
* 功能說明: 訊息處理,暫時未用到。
* 形 參: 無
* 返 回 值: 無
* 優 先 級: osPriorityHigh3
*********************************************************************************************************
*/
void AppTaskMsgPro(void *argument)
{
while(1)
{
osDelay(10);
}
}
/*
*********************************************************************************************************
* 函 數 名: AppTaskStart
* 功能說明: 啟動任務,這裡用作BSP驅動包處理。
* 形 參: 無
* 返 回 值: 無
* 優 先 級: osPriorityHigh4
*********************************************************************************************************
*/
void AppTaskStart(void *argument)
{
const uint16_t usFrequency = 1; /* 延遲週期 */
uint32_t tick;
/* 初始化外設 */
HAL_ResumeTick();
bsp_Init();
/* 建立任務 */
AppTaskCreate();
/* 獲取當前時間 */
tick = osKernelGetTickCount();
while(1)
{
/* 需要週期性處理的程式,對應裸機工程呼叫的SysTick_ISR */
bsp_ProPer1ms();
/* 相對延遲 */
tick += usFrequency;
osDelayUntil(tick);
}
}
本章節內容相對比較容易,重點是學習任務優先順序分配方案,隨著後面的學習,初學者需要慢慢積累這方面的經驗。