1. 程式人生 > >FreeRTOS任務API函式的使用

FreeRTOS任務API函式的使用

1. 任務建立和刪除API函式

1.1 xTaskCreate()

函式xTaskCreate()使用動態的方法建立一個任務,建立人物所需的RAM自動從FreeRTOS的堆中分配,巨集configSUPPORT_DYNAMIC_ALLOCATION必須為1

函式原型:

    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: 任務名字,任務名字長度不能超過 configMAX_TASK_NAME_LEN

usStackDepth: 任務堆疊大小,實際申請堆疊是usStackDepth的4倍(因為這裡是uint16,而申請時的型別是uint32).空閒任務的堆疊大小為configMINIMAL_STACK_SIZE

pvParameters: 傳遞給任務函式的引數

uxPriotiry: 任務優先順序,範圍0~configMAX_PRIORITIES-1

pxCreatedTask: 任務控制代碼,任務建立成功以後返回此任務的任務控制代碼,任務控制代碼其實就是這個任務的任務堆疊。此引數就是用來儲存這個任務控制代碼,其他API函式可能會使用到這個任務控制代碼。

返回值:

pdPASS: 任務建立成功

errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任務建立失敗,堆記憶體不足。

1.2 xTaskCreateStatic()

此函式與xTaskCreate()的功能相同,但是建立任務所需的RAM需要使用者來提供,巨集configSUPPORT_STATIC_ALLOCATION必須定義為1

函式原型:

xTaskCreateStatic(
    TaskFunction_t pxTaskCode,
    const char * const pcName,
    const uint32_t ulStackDepth,
    void
* const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer )

pxTaskCode: 任務函式

pcName:任務名字,任務名字長度不能超過 configMAX_TASK_NAME_LEN

usStackDepth: 任務堆疊大小,由於此函式是用靜態方法建立任務,所以任務堆疊由使用者給出,一般是一個數組,此引數就是這個陣列的大小

pvParameters: 傳遞給任務函式的引數

uxPriotiry: 任務優先順序,範圍0~configMAX_PRIORITIES-1

puxStackBuffer: 任務堆疊,一般為陣列,型別為StackType_t

pxTaskBuffer: 任務控制塊

返回值:

NULL: 任務建立失敗,pxTaskBuffer或puxStackBuffer為NULL時會導致錯誤發生

其他值:任務建立成功,返回任務的任務控制代碼

1.3 VTaskDelete()

刪除一個已經建立樂的任務,被刪除的任務不再存在(不會進入執行態)。任務被刪除後不能再使用此任務的控制代碼。

若是用動態方法建立,刪除任務後,此任務之前申請的堆疊和控制塊記憶體會在空閒任務中被釋放掉,因此當呼叫函式vTaskDelete()刪除任務以後必須給空閒任務一定的執行時間

若是靜態方法建立任務,刪除任務後用戶分配給任務的記憶體需要使用者自行釋放掉。

函式原型:

void vTaskDelete( TaskHandle_t xTaskToDelete )

xTaskDelete: 要刪除的任務的任務控制代碼

2. 任務建立和刪除

2.1 任務相關宣告:

//任務優先順序
#define START_TASK_PRIO         1
//任務堆疊大小    
#define START_STK_SIZE          256  
//任務控制代碼
TaskHandle_t StartTask_Handler;
//任務函式
void start_task(void *pvParameters);

//任務優先順序
#define LED0_TASK_PRIO      2
//任務堆疊大小    
#define LED0_STK_SIZE       50  
//任務控制代碼
TaskHandle_t LED0Task_Handler;
//任務函式
void led0_task(void *pvParameters);

//任務優先順序
#define LED1_TASK_PRIO      3
//任務堆疊大小    
#define LED1_STK_SIZE       50  
//任務控制代碼
TaskHandle_t LED1Task_Handler;
//任務函式
void led1_task(void *pvParameters);

聲明瞭每個任務的優先順序,堆疊大小和控制代碼,以及任務函式

2.2 main()

int main(void)
{
  HAL_Init();                     //初始化HAL庫   
  Stm32_Clock_Init(360,25,2,8);   //設定時鐘,180Mhz
    delay_init(180);                //初始化延時函式
    uart_init(115200);              //初始化串列埠
  LED_Init();                     //初始化LED 

    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);   //任務控制代碼        
    vTaskStartScheduler();//開啟任務排程
}

用來初始化相關硬體,並且呼叫函式xTaskCreate()建立start_task任務,再呼叫函式vTaskStartScheduler()開啟FreeRTOS的任務排程器,FreeRTOS開始執行

2.3 任務函式

//開始任務任務函式
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //進入臨界區
    //建立LED0任務
    xTaskCreate((TaskFunction_t )led0_task,         
                (const char*    )"led0_task",       
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,              
                (UBaseType_t    )LED0_TASK_PRIO,    
                (TaskHandle_t*  )&LED0Task_Handler);   
    //建立LED1任務
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);        
    vTaskDelete(StartTask_Handler); //刪除開始任務
    taskEXIT_CRITICAL();            //退出臨界區
}
//LED0任務函式 
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
    }
}   

//LED1任務函式
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

start_task任務的任務函式中建立了另外兩個任務led0_task和led1_task。這個任務用來建立其他任務,完成之後呼叫vTaskDelete(StartTask_Handler)刪除掉開始任務

led0_task的任務函式每隔500ms讓LED0亮滅反轉,led1_task的任務函式間隔200ms和800ms來回反轉LED1

3. 任務掛起和恢復API函式

暫停某個任務的執行,過一段時間再重新執行。 任務掛起後任務中變數儲存的值不變,而任務刪除和重建後任務中變數儲存的值會丟失。

3.1 vTaskSuspend()

此函式用於將某個任務設定為掛起狀態。

函式原型:

void vTaskSuspend( TaskHandle_t xTaskToSuspend )

xTaskToSuspend: 要掛起任務的任務控制代碼。如果引數為NULL表示掛起任務自己。

3.2 vTaskResume()

將一個任務從掛起態恢復到就緒態

函式原型:

void vTaskResume( TaskHandle_t xTaskToResume )

xTaskToResume: 要恢復任務的任務控制代碼

3.3 xTaskResumeFromISR()

此函式用於在中斷服務函式中恢復一個任務,是vTaskResume()的中斷版本
函式原型:

BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )

xTaskResumeFromISR:要恢復任務的任務控制代碼

返回值:

pdTRUE: 恢復執行的任務的任務優先順序等於或高於正在執行的任務(被中斷打斷的任務),在退出中斷服務函式以後必須進行一次上下文切換

pdFALSE: 恢復執行的任務的任務優先順序低於正在執行的任務(被中斷打斷的任務),在退出中斷服務函式以後不需要進行一次上下文切換

4. 任務掛起和恢復

4.1 任務相關宣告:

#define START_TASK_PRIO         1
//任務堆疊大小    
#define START_STK_SIZE          256  
//任務控制代碼
TaskHandle_t StartTask_Handler;
//任務函式
void start_task(void *pvParameters);

//任務優先順序
#define KEY_TASK_PRIO   2
//任務堆疊大小    
#define KEY_STK_SIZE        128  
//任務控制代碼
TaskHandle_t KEYTask_Handler;
//任務函式
void key_task(void  *pvParameters);

//任務優先順序
#define LED0_TASK_PRIO      3
//任務堆疊大小    
#define LED0_STK_SIZE       50  
//任務控制代碼
TaskHandle_t LED0Task_Handler;
//任務函式
void led0_task(void *pvParameters);

//任務優先順序
#define LED1_TASK_PRIO      4
//任務堆疊大小    
#define LED1_STK_SIZE       50  
//任務控制代碼
TaskHandle_t LED1Task_Handler;
//任務函式
void led1_task(void  *pvParameters);

4.2 main()

int main(void)
{
  HAL_Init();                     //初始化HAL庫   
  Stm32_Clock_Init(360,25,2,8);   //設定時鐘,180Mhz
    delay_init(180);                //初始化延時函式
    uart_init(115200);              //初始化串列埠
  LED_Init();                     //初始化LED 
  KEY_Init();                     //初始化KEY

    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);   //任務控制代碼        
    vTaskStartScheduler();//開啟任務排程
}

4.3 任務函式

//開始任務任務函式
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //進入臨界區
      //建立KEY任務
        xTaskCreate((TaskFunction_t )key_task,      
                (const char*    )"key_task",    
                (uint16_t       )KEY_STK_SIZE, 
                (void*          )NULL,              
                (UBaseType_t    )KEY_TASK_PRIO, 
                (TaskHandle_t*  )&KEYTask_Handler);  
    //建立LED0任務
    xTaskCreate((TaskFunction_t )led0_task,         
                (const char*    )"led0_task",       
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,              
                (UBaseType_t    )LED0_TASK_PRIO,    
                (TaskHandle_t*  )&LED0Task_Handler);   
    //建立LED1任務
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);        
    vTaskDelete(StartTask_Handler); //刪除開始任務
    taskEXIT_CRITICAL();            //退出臨界區
}
//KEY任務函式
void key_task(void *pvParameters)
{
    u8 key;
    while(1)
    {
        key=KEY_Scan(0);
        switch(key)
        {
            case WKUP_PRES:
                vTaskSuspend(LED0Task_Handler);//掛起任務led0
                printf("掛起LED0!\r\n");
                break;
            case KEY0_PRES:
                vTaskResume(LED0Task_Handler);  //恢復任務led0
                printf("恢復LED0!\r\n");
                break;
            case KEY1_PRES:
                vTaskSuspend(LED1Task_Handler);//掛起任務led1
                printf("掛起LED1!\r\n");
                break;
            case KEY2_PRES:
                vTaskResume(LED1Task_Handler);//恢復任務led1
                printf("恢復LED1!\r\n");
                break;  
        }
        vTaskDelay(10);         //延時10ms 
    }
}
//LED0任務函式 
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
    }
}   

//LED1任務函式
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

start_task任務建立了三個任務函式後刪除自己;

key_task任務函式進行按鍵掃描,當WKUP按下 掛起任務led0_task;當KEY0按下,恢復任務led0_task;當KEY1按下,掛起任務led1_task;當KEY2按下,恢復任務led1_task;並且串列埠輸出列印在電腦端顯示
這裡寫圖片描述

led0_task和led1_task 分別控制LED0和LED1閃爍