1. 程式人生 > >Keil MDK之RTX任務管理 初始化 建立 刪除

Keil MDK之RTX任務管理 初始化 建立 刪除

在Keil 的安裝目錄下面有個RTX的幫助文件,路徑C:\keil\ARM\Hlp 這裡面的rlarm.chm手冊,詳細介紹了RTX的各函式介面等

一、RTX的初始化和啟動

1、RTX的初始化函式有三個,可以開啟rlarm.chm手冊,如下圖


這三個函式的解析和使用方法大家可以參考手冊,

這裡重點介紹下os_sys_init_user函式,其他兩個有興趣的可以自己看看手冊

函式原型

void os_sys_init_user (
    void (*task)(void),    /* 任務函式*/
    U8    priority,        /* 任務優先順序(1-254) */
    void* stack
, /* 任務棧 */ U16 size); /* 任務棧大小 */
函式描述:

該函式用於實現RTX作業系統的初始化和啟動任務的建立,並且可以自定義任務棧的大小

第一個引數是啟動任務的函式名

第二個引數是任務的優先順序  RTX任務的優先順序越低數字越小

第三個引數是任務棧地址

第四個引數是任務棧大小

舉個列子:

os_sys_init_user(AppTaskStart,            /*任務函式*/
4,                       /*任務優先順序*/
&AppTaskStartStk,        /*任務棧*/
sizeof(AppTaskStartStk));/*任務棧大小*/

二、任務的建立

RTX中任務的建立有4個函式,如下圖


這裡重點解析下os_tsk_create_user函式

函式原型:

OS_TID os_tsk_create_user(
    void (*task)(void),    /*任務函式 */
    U8    priority,        /* 任務優先順序 (1-254) */
    void* stk,             /* 任務棧 */
    U16   size );          /*任務棧大小 */
函式描述:

該函式用於實現RTX作業系統的任務建立,並且可以自定義棧的大小

第一個引數建立的任務函式名

第二個引數任務的優先順序

第三個引數任務棧的地址

低四個引數任務棧的大小

返回值是任務的ID

舉個列子:

HandleTaskLED = os_tsk_create_user(AppTaskLED,            /*任務函式*/
 2,                     /*優先順序 注意RTX的數字越小,優先順序越低*/
       &AppTaskLEDStk,        /*任務棧起始地址*/
sizeof(AppTaskLEDStk));/*任務棧大小*/

三、RTX中的任務刪除

RTX中任務的刪除有兩個函式,如下圖


這裡重點解析下os_tsk_delete函式

函式原型:

OS_RESULT os_tsk_delete (
    OS_TID task_id );    /*任務ID */
函式描述:

該函式用於實現RTX作業系統的任務刪除

第一個引數是刪除任務的ID

返回值:如果任務刪除成功,函式返回OS_R_OK,其餘所有的情況返回OS_R_NOK

舉個列子

if(HandleTaskLED != NULL)
{
if(os_tsk_delete(HandleTaskLED) == OS_R_OK)
{
HandleTaskLED = NULL;
printf("任務AppTaskLED刪除成功\r\n");
}
else
{
printf("任務AppTaskLED刪除失敗\r\n");
}
}

下面就做個實驗

實驗目的:學習RTX的任務建立和刪除

實驗內容:

1、k1按鍵按下,刪除任務AppTaskLED

2、k2按鍵按下,重新建立AppTaskLED

下面是詳細的程式碼

#include "bsp.h"/* 底層硬體驅動 */
#include <RTL.h>




static uint64_t AppTaskLEDStk[256/8];/*任務棧*/
static uint64_t AppTaskStartStk[512/8];/*任務棧*/
static uint64_t AppTaskUserKeyStk[512/8];/**/




/*任務控制代碼*/
OS_TID HandleTaskLED = NULL;
OS_TID HandleTaskKey = NULL;
/*函式宣告*/
static void AppTaskCreate(void);
__task void AppTaskLED(void);
__task void AppTaskStart(void);




/*
*********************************************************************************************************
*函 數 名: main
*功能說明: c程式入口
*形    參:無
*返 回 值: 錯誤程式碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{


/*
ST韌體庫中的啟動檔案已經執行了 SystemInit() 函式,該函式在 system_stm32f4xx.c 檔案,主要功能是
配置CPU系統的時鐘,內部Flash訪問時序,配置FSMC用於外部SRAM
*/
bsp_Init();/*底層初始化*/
os_sys_init_user(AppTaskStart,            /*任務函式*/
4,                       /*任務優先順序*/
&AppTaskStartStk,        /*任務棧*/
sizeof(AppTaskStartStk));/*任務棧大小*/
/* 進入主程式迴圈體 */
while (1)
{
;
}
}
/*
*********************************************************************************************************
*函 數 名: AppTaskLED
*功能說明: LED閃爍的任務
*形    參:無
*返 回 值: 無
*********************************************************************************************************
*/
__task void AppTaskLED(void)
{
static uint8_t i = 0;
while(1)
{
if(i % 2 == 0)
{
GPIO_ResetBits(GPIOI,GPIO_Pin_10);/*點亮LED*/
}
else
{
GPIO_SetBits(GPIOI,GPIO_Pin_10);/*熄滅LED*/
}
i++;
os_dly_wait(800);/*系統延時函式 因為時鐘節拍為1000 所以這裡是延時800ms,也就是使AppTaskLED任務掛起800MS*/
}
}


__task void AppTaskUserKey(void)
{
static uint8_t ucKeyCode  = 0;
while(1)
{
ucKeyCode = bsp_GetKey();/*獲取按鍵按下的鍵值*/
switch(ucKeyCode)
{
case KEY_DOWN_K1:
printf("K1鍵按下,刪除任務AppTaskLED\r\n");
if(HandleTaskLED != NULL)
{
if(os_tsk_delete(HandleTaskLED) == OS_R_OK)/*刪除任務AppTaskLED*/
{
HandleTaskLED = NULL;
printf("任務AppTaskLED刪除成功\r\n");
}
else
{
printf("任務AppTaskLED刪除失敗\r\n");
}
}
break;
case KEY_DOWN_K2:
printf("K2鍵按下,重新建立任務AppTaskLED\r\n");
if(HandleTaskLED == NULL)
{
HandleTaskLED = os_tsk_create_user(AppTaskLED,         /*任務函式*/
2,                 /*任務優先順序*/
AppTaskLEDStk,     /*任務棧*/
sizeof(AppTaskLEDStk));/*任務棧的大小*/
}
break;
default:
break;
}
os_dly_wait(20);
}
}
/*
*********************************************************************************************************
*函 數 名:AppTaskCreate
*功能說明: 任務建立
*形    參:無
*返 回 值: 無
*********************************************************************************************************
*/
static void AppTaskCreate(void)
{
HandleTaskLED = os_tsk_create_user(AppTaskLED,            /*任務函式*/
2,                     /*優先順序 注意RTX的數字越小,優先順序越低*/
&AppTaskLEDStk,        /*任務棧起始地址*/
sizeof(AppTaskLEDStk));/*任務棧大小*/
HandleTaskKey = os_tsk_create_user(AppTaskUserKey,
3,
&AppTaskUserKeyStk,
sizeof(AppTaskUserKeyStk));
}
/*
*********************************************************************************************************
*函 數 名:AppTaskStart
*功能說明: 開始任務
*形    參:無
*返 回 值: 無
*********************************************************************************************************
*/
__task void AppTaskStart(void)
{
AppTaskCreate();/*建立AppTaskLED任務*/
while(1)
{
bsp_KeyScan();/*查詢按鍵是否被按下 並且儲存鍵值*/
os_dly_wait(10);/*系統延時函式*/
}
}

實現結果:

我們可以使用除錯,來觀察每個任務的執行情況,如下圖是剛啟動的任務執行情況


可以看到有是那個使用者任務。一個是開始任務,一個是按鍵處理任務,一個是LED閃爍的任務

當我們按下K1的時候,再來看發現LED閃爍的任務沒有了,如下圖,這就是刪除了LED閃爍的任務


按下K1就刪除了LED的任務

然後按下k2就可以重新建立任務,除錯結果和啟動的結果一樣,同時我們也可以觀察到LED的閃爍情況,按下K1LED停止閃爍,按下k2LED重新閃爍