FreeRTOS-01-任務相關函式

zhengcixi發表於2021-07-25

3 任務相關API函式

任務相關函式如下:

任務建立和刪除API函式

任務建立和刪除實驗(動態方法)

任務建立和刪除實驗(靜態方法)

任務掛起和恢復API函式

任務掛起和恢復實驗

3.1 任務建立API函式(動態方法)

函式原型:

#include "FreeRTOS.h"
#include "task.h"

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
    const char * const pcName,
    const configSTACK_DEPTH_TYPE usStackDepth,
    void * const pvParameters,
    UBaseType_t uxPriority,
    TaskHandle_t * const pxCreatedTask );

函式描述:使用動態方法建立一個任務,任務控制塊和任務堆疊在函式內建立。最新建立的任務初始化為就緒態,如果當前沒有更高優先順序的任務執行,則立刻變為執行態。

函式引數說明:

引數名 說明
pxTaskCode 任務函式,通常為一個無限迴圈。
pcName 任務名字,名稱長度有限制,在FreeRTOSConfig.h中有定義configMAX_TASK_NAME_LEN。
usStackDepth 任務堆疊大小,實際申請到的堆疊是usStackDepth的4倍。configMINIMAL_STACK_SIZE定義的是空閒任務堆疊大小。
pvParameters 傳遞給任務函式的引數
uxPriority 任務優先順序,範圍0~configMAX_PRIORITIES-1。
pxCreatedTask 任務控制程式碼,任務建立成功以後會返回此任務的任務控制程式碼, 這個控制程式碼其實就是 任務的任務堆疊。 此引數就用來儲存這個任務控制程式碼。其他 API 函式可能會使 用到這個控制程式碼。如果任務控制程式碼不需要使用,可以被設定為NULL。

返回值:

pdPASS:任務建立成功。
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任務建立失敗,因為堆記憶體不足!

3.2 任務建立函式(靜態方法)

函式原型:

#include "FreeRTOS.h"
#include "task.h"

TaskHandle_t 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 );

函式描述:使用靜態方法建立一個任務。任務所需要的RAM需要使用者來提供。

函式引數說明:

引數名 說明
pxTaskCode 任務函式,通常為一個無限迴圈。
pcName 任務名字,名稱長度有限制,在FreeRTOSConfig.h中有定義configMAX_TASK_NAME_LEN。
usStackDepth 任務堆疊大小,靜態建立任務的堆疊由使用者給出,通常為一個陣列,這個引數就是陣列的大小。
pvParameters 傳遞給任務函式的引數
uxPriority 任務優先順序,範圍0~configMAX_PRIORITIES-1。
puxStackBuffer 任務堆疊,一般為陣列,陣列型別為StackType_t型別。
pxTaskBuffer 任務控制塊

返回值:

NULL:任務建立失敗,puxStackBuffer或pxTaskBuffer為空。
其他值: 任務建立成功,返回任務的任務控制程式碼。

3.3 任務刪除API函式

函式原型:

void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;

函式描述:刪除任務,刪除之後的任務不再存在,也不能再使用此函式的控制程式碼。如果任務使用的是xTaskCreate()建立的,此任務被刪除後此任務之前申請的堆疊和控制塊記憶體會在任務中被釋放掉。

函式引數:xTaskToDelete要刪除的任務的任務控制程式碼。

返回值:

3.4 任務建立和刪除實驗(動態方法)

建立兩個任務,這兩個任務的功能如下:

task00:此任務每個1000ms列印一次字串,呼叫5次之後呼叫vTaskDelete()函式刪除task01。

task01:此任務為普通任務,間隔500ms列印一次字串,和task00同樣的任務優先順序。

task00任務建立程式碼:

configSTACK_DEPTH_TYPE Task00_STACK_SIZE = 5;
UBaseType_t  Task00_Priority = 1;
TaskHandle_t Task00_xHandle;

void vTask00_Code(void *para)
{
    static unsigned int cnt = 0;
    for (;;)
    {
        PRINT(" task00 cnt %u...", cnt);
        if (cnt == 4)
            vTaskDelete(Task01_xHandle);
        cnt++;
        vTaskDelay(1000);
    }
}

xTaskCreate(vTask00_Code, "task00", Task00_STACK_SIZE, NULL, Task00_Priority, &Task00_xHandle);

task01任務建立程式碼:

configSTACK_DEPTH_TYPE Task01_STACK_SIZE = 5;
UBaseType_t  Task01_Priority = 1;
TaskHandle_t Task01_xHandle;

void vTask01_Code(void *para)
{
    static unsigned int cnt = 0;
    for (;;)
    {
        PRINT(" task01 cnt %u...", cnt);
        cnt++;
        vTaskDelay(500);
    }
}

xTaskCreate(vTask01_Code, "task01", Task01_STACK_SIZE, NULL, Task01_Priority, &Task01_xHandle);

編譯,執行,測試結果符合預期,task00執行5秒之後刪除了task01:

image-20210717164936914

3.5 任務建立和刪除實驗(靜態方法)

使用靜態方式建立一個任務,該任務每個1秒列印一個字串:

#define STATIC_STACK_SIZE 5
UBaseType_t  Static_Task_Priority = 1;
StaticTask_t Static_xTaskBuffer;
StackType_t  Static_xStack[STATIC_STACK_SIZE];
TaskHandle_t Static_xhandle = NULL;  //任務控制程式碼

void static_task_code(void *para)
{
    static unsigned int cnt = 0;
    for (;;)
    {
        PRINT(" static task cnt %u...", cnt);
        cnt++;
        vTaskDelay(1000);
    }
}

Static_xhandle = xTaskCreateStatic (static_task_code,
        "static task",
        STATIC_STACK_SIZE,
        NULL,
        Static_Task_Priority,
        Static_xStack,
        &Static_xTaskBuffer);

3.6 vTaskDelay()

函式原型:

#include "FreeRTOS.h"
#include "task.h"

void vTaskDelay( const TickType_t xTicksToDelay );

函式描述:呼叫該函式的任務將進入阻塞態,中斷一段固定的時鐘週期。

函式引數:xTicksToDelay表示呼叫函式的任務的阻塞態保持時間。延時達到之後將進入就緒態。例如:當時鍾計數到10000時,函式呼叫了vTaskDelay(100),然後任務進入阻塞態,並且保持阻塞態直到時鐘計數到10100。

巨集pdMS_TO_TICKS()可以被使用來延時毫秒。例如:呼叫vTaskDelay( pdMS_TO_TICKS(100) ),任務將進入阻塞態100毫秒。

3.7 任務掛起函式

函式原型:

#include “FreeRTOS.h”
#include “task.h”
void vTaskSuspend( TaskHandle_t pxTaskToSuspend );

函式描述:將一個任務設定為掛起態。一個任務在掛起態將不會被排程轉為執行態。將任務從掛起態移出來的唯一方式是呼叫vTaskResume()函式。

函式引數:pxTaskToSuspen表示需要掛起的任務控制程式碼。一個任務可以通過設定引數為NULL來掛起自己。

3.8 排程器掛起函式

函式原型:

#include “FreeRTOS.h”
#include “task.h”
void vTaskSuspendAll( void );

函式描述:掛起排程器,但保留中斷使能。當排程器被掛起時,如果一箇中斷需要請求上下文切換,中斷請求將保持等待直到排程器從掛起中恢復。排程器從掛起態恢復需要呼叫xTaskResumeAll()函式。vTaskSuspendAll()支援巢狀使用,當要恢復排程器執行時,vTaskSuspendAll()函式被呼叫幾次就需要呼叫xTaskResumeAll()函式幾次。

3.9 任務恢復函式

函式原型:

#include “FreeRTOS.h”
#include “task.h”
void vTaskResume( TaskHandle_t pxTaskToResume );

函式描述:將一個任務從掛起態轉換為就緒態。任務必須是之前使用vTaskSuspend()函式進入的掛起態。

函式引數:pxTaskToResume需要恢復的任務控制程式碼。

3.10 排程器恢復函式

函式原型:

#include “FreeRTOS.h”
#include “task.h”
BaseType_t xTaskResumeAll( void );

函式描述:恢復排程器為排程狀態。排程器必須是之前使用vTaskSuspendAll()函式進入的掛起狀態。

返回值:pdTRUE:排程器轉換為活躍狀態。

pdFALSE:排程器巢狀呼叫了vTaskSuspendAll(),排程器依然保持掛起狀態。

3.11 任務掛起和恢復實驗

建立兩個任務,任務二建立之後就掛起,任務三建立之後延時5秒之後,恢復任務二的執行。

程式碼大致實現如下:

/* test suppend task */
configSTACK_DEPTH_TYPE Task02_STACK_SIZE = 5;
UBaseType_t  Task02_Priority = 2;
TaskHandle_t Task02_xHandle;

configSTACK_DEPTH_TYPE Task03_STACK_SIZE = 5;
UBaseType_t  Task03_Priority = 1;
TaskHandle_t Task03_xHandle;

void vTask02_Code(void *para)
{
    static unsigned int cnt = 0;
    for (;;)
    {
        PRINT(" task02 cnt %u...", cnt);
        cnt++;
        vTaskDelay(1000);
    }
}

void vTask03_Code(void *para)
{
    static unsigned int cnt = 0;
    for (;;)
    {
        PRINT(" task03 cnt %u...", cnt);
        cnt++;
        vTaskDelay(1000);
        if (cnt == 5)
            vTaskResume(Task02_xHandle);
    }
}

void create_task_test_suppend(void)
{
    if (xTaskCreate(vTask02_Code, "suppend task02", Task02_STACK_SIZE, 
        NULL, Task02_Priority, &Task02_xHandle) != pdPASS)
        PRINT("creat task failed!\n");
    if (xTaskCreate(vTask03_Code, "suppend task03", Task03_STACK_SIZE, 
        NULL, Task03_Priority, &Task03_xHandle) != pdPASS)
        PRINT("creat task failed!\n");
    vTaskSuspend(Task02_xHandle);
}

編譯執行,得到的結果如下:

$ ./build/freertos-simulator 
 task03 cnt 0...
 task03 cnt 1...
 task03 cnt 2...
 task03 cnt 3...
 task03 cnt 4...
 task02 cnt 0...
 task03 cnt 5...
 task02 cnt 1...
 task03 cnt 6...
 task02 cnt 2...
 task03 cnt 7...
 task02 cnt 3...
 task03 cnt 8...

3.11 排程器掛起和恢復實驗

建立兩個任務,任務四建立之後執行,任務五建立之後延時5秒之後,掛起排程器,然後恢復排程器。

程式碼大致實現如下:

configSTACK_DEPTH_TYPE Task04_STACK_SIZE = 5;
UBaseType_t  Task04_Priority = 2;
TaskHandle_t Task04_xHandle;

configSTACK_DEPTH_TYPE Task05_STACK_SIZE = 5;
UBaseType_t  Task05_Priority = 1;
TaskHandle_t Task05_xHandle;

void vTask04_Code(void *para)
{
    static unsigned int cnt = 0;
    for (;;)
    {
        PRINT(" task04 cnt %u...", cnt);
        cnt++;
        vTaskDelay(1000);
    }
}

void vTask05_Code(void *para)
{
    static unsigned int cnt = 0;
    for (;;)
    {
        PRINT(" task05 cnt %u...", cnt);
        cnt++;
        vTaskDelay(1000);
        if (cnt == 5) {
            vTaskSuspendAll();
            PRINT("... ...\n");
            xTaskResumeAll();
        }
    }
}

void create_task_test_suppend(void)
{
    if (xTaskCreate(vTask04_Code, "suppend task04", Task04_STACK_SIZE, 
        NULL, Task04_Priority, &Task04_xHandle) != pdPASS)
        PRINT("creat task failed!\n");
    if (xTaskCreate(vTask05_Code, "suppend task05", Task05_STACK_SIZE, 
        NULL, Task05_Priority, &Task05_xHandle) != pdPASS)
        PRINT("creat task failed!\n");
}

編譯執行:

 task04 cnt 0...
 task05 cnt 0...
 task04 cnt 1...
 task05 cnt 1...
 task04 cnt 2...
 task05 cnt 2...
 task04 cnt 3...
 task05 cnt 3...
 task04 cnt 4...
 task05 cnt 4...
 task04 cnt 5...
... ...

 task05 cnt 5...
 task04 cnt 6...
 task05 cnt 6...
 task04 cnt 7...
 task05 cnt 7...

相關文章