freertos task創建和 queue使用簡述

freertos中的task可以任務是一個線程,它是freertos系統調度的一個單位,使用xTaskCreate() 可以創建出task,函數原型如下

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

第一個參數是task的入口函數;第二個參數是task 的名稱,第三個參數是task的棧大小(單位不一定是字節,有些平臺是4字節對齊,所以棧大小爲usStackDepth * 4 字節),第四個參數是傳到入口函數的參數,第五個參數是task的優先級,數值越大優先級越高(idle 的優先級是0),第六個參數是指向創建出來task的指針,可用於銷燬該task。

下面是一個簡單的示例

#include <stdio.h>
#include <string.h>
#include "FreeRTOS/FreeRTOS.h"
#include "FreeRTOS/task.h"
#include "FreeRTOS/queue.h"

#define DEMO_TASK_NAME          "demo_task"               // 任務名稱
#define DEMO_TASK_PRIORITY	    (tskIDLE_PRIORITY + 12 )  // 任務優先級
#define DEMO_TASK_STACK_SIZE    ( 2048 )                  // 任務棧大小
#define DEMO_QUEUE_LENGTH 	    ( 5 )                     // 隊列長度

enum
{
   DEMO_MSG_LOG,
}; //消息類型枚舉

typedef struct demo_message
{
	unsigned char msg_type;
	char* msg_content;
} demo_message_t; //消息結構體

static QueueHandle_t demo_message_queue;    //指向消息隊列
static TaskHandle_t demo_task_handle;       //指向創建出來的任務
static BaseType_t demo_task_ready = pdFALSE;//任務是否成功創建標誌


static void demo_task(void *pvParameters)
{
    demo_message_t xMessage;
    for( ;; )
    {
        /* Wait until a message arrives. */
        while(xQueueReceive(demo_message_queue, ( void * )&xMessage, portMAX_DELAY ) == pdPASS )
        {
            switch(xMessage.msg_type) //需要處理的消息類型
            {
            case DEMO_MSG_LOG:
               if(xMessage.msg_content != NULL)
               {
                   printf("[demo_task] msg_content = %s \n",xMessage.msg_content);
                   free(xMessage.msg_content);  //釋放內存
               }
            break;
            default: break;
        }
    }
}

int create_demo_task()
{
    if(demo_task_ready == pdTRUE)
    {
        printf("[demo_task] demo task had create.\n");
        return 0;
    }

    demo_message_queue = xQueueCreate(DEMO_QUEUE_LENGTH, sizeof(demo_message_t));
    if(demo_message_queue == NULL)
    {
        printf("[demo_task] xQueueCreate fail.\n");
        return -1;
    }
    BaseType_t ret=xTaskCreate(demo_task, DEMO_TASK_NAME, DEMO_TASK_STACK_SIZE, NULL, DEMO_TASK_PRIORITY, &demo_task_handle);
    if(ret != pdPASS)
    {
        printf("[demo_task] xTaskCreate fail.\n");
        vQueueDelete(demo_message_queue); //銷燬消息隊列
        return -1;
    }
    demo_task_ready = pdTRUE;  //標誌任務成功創建
    return 0;
}

int destroy_demo_task()
{
    if(demo_task_ready == pdTRUE)
    {
        vQueueDelete(demo_message_queue);
        vTaskDelete(demo_task_handle);
    }
    demo_task_ready = pdFALSE;
    return 0;
}

int demo_log_d(const char* log)
{
    if(demo_task_ready == pdFALSE)
    {
        printf("[demo_task] demo task had no start.\n");
        return -1;
    }
    if(log == NULL)
    {
        printf("[demo_task] log is null.\n");
        return -1;
    }
    int len = strlen(log); 
    demo_message_t xMessage;
    xMessage.msg_type = DEMO_MSG_LOG;
    xMessage.msg_content = (char*)malloc(len+1);//多加一個結束標誌
    if(xMessage.msg_content == NULL)
    {
        printf("[demo_task] malloc buff fail.\n");
        return -1;
    } 
    xMessage.msg_content[len] = '\0';  //結束標誌
    BaseType_t ret = xQueueSend(demo_message_queue, ( void * )&xMessage, 0);
    if(ret == pdFALSE)
    {
        printf("[demo_task] xQueueSend fail.\n");
        free(xMessage.msg_content);  //釋放內存
        return -1;
    }
    return 0;
}

task 和queue 的創建調用接口就行了,考慮好創建失敗的情況就可以了。創建好了之後,將queue和task關聯起來就可以做成一個消息隊列,task循環從隊列中取出消息進行處理,如果隊列中沒有消息,就休眠等待,直到有消息進來。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章