创建任务

动态分配内存:

BaseType_t xTaskCreate(

TaskFunction_t pxTaskCode, // 函数指针, 任务函数

const char * const pcName, // 任务的名字

const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节

void * const pvParameters, // 调用任务函数时传入的参数

UBaseType_t uxPriority, // 优先级

TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务

静态分配内存:

TaskHandle_t xTaskCreateStatic (

TaskFunction_t pxTaskCode, // 函数指针, 任务函数

const char * const pcName, // 任务的名字

const uint32_t ulStackDepth, // 栈大小,单位为word,10表示40字节

void * const pvParameters, // 调用任务函数时传入的参数

UBaseType_t uxPriority, // 优先级

StackType_t * const puxStackBuffer, // 静态分配的栈,就是一个buffer

StaticTask_t * const pxTaskBuffer // 静态分配的任务结构体的指针,用它来操作这个任务

);

使用任务参数:

任务传参一般使用结构体,用一个结构体来将函数需要的参数都包括在内,然后传参时传递结构体的地址就行了。

struct TaskPrintInfo{
    uint8_t x;
    uint8_t y;
    char name[16];
};

static struct TaskPrintInfo LCDTask1 = {
0,
0,
"LCDTask1"
};
static struct TaskPrintInfo LCDTask2 = {
0,
3,
"LCDTask2"
};
static struct TaskPrintInfo LCDTask3 = {
0,
6,
"LCDTask3"
};

void LcdPrintTask(void* params)
{
    struct TaskPrintInfo* pinfo = params;
    //...
    //通过 pinfo 指针调用结构体成员,完成任务
    //...
}

//使用同一个函数创建不同的任务
	xTaskCreate(LcdPrintTask,"LCDTask1",128,&LCDTask1,osPriorityNormal,NULL);
	xTaskCreate(LcdPrintTask,"LCDTask2",128,&LCDTask2,osPriorityNormal,NULL);
	xTaskCreate(LcdPrintTask,"LCDTask3",128,&LCDTask3,osPriorityNormal,NULL);

估算栈大小

估算栈的大小:

下图为理论上最多要保存的寄存器:

删除任务

使用 void vTaskDelete( TaskHandle_t xTaskToDelete ) 这个函数来删除任务,xTaskToDelete就是创建任务时接收的任务句柄,如下示例代码:

//读取红外遥控器
if (IRReceiver_Read(&dev, &data) == 0)
{
    if (data == 0xa8)//play
    {
        //创建播放音乐的任务
        extern void PlayMusic(void* params);
        if (xSoundTaskHandle == NULL)
        {
            LCD_ClearLine(0, 0);
            LCD_PrintString(0, 0, "Create Task");
            SoundRet = xTaskCreate(PlayMusic, "SoundTask", 128, NULL, osPriorityNormal, &xSoundTaskHandle);
        }
    }
    else if (data == 0xa2)//power
    {
        //删除播放音乐的任务
        if (xSoundTaskHandle != NULL)
        {
            LCD_ClearLine(0, 0);
            LCD_PrintString(0, 0, "Delete Task");
            vTaskDelete(xSoundTaskHandle);
            PassiveBuzzer_Control(0);//停止蜂鸣器
            xSoundTaskHandle = NULL;
        }

    }
}

但是一般来说不会频繁创建任务与删除任务,因为任务创建需要栈的空间,频繁创建与删除会形成大量碎片内存空间,可能会导致大量内存空间无法利用,最后无内存可用。

任务如何退出

优先级与阻塞

        假设此时有个任务是播放音乐,如果任务优先级较低,音乐播放会很缓慢,可以提高任务优先级来提高音乐质量,但是提高任务优先级会导致他抢占cpu,需要让他主动放弃cpu资源才能让其他任务工作,所以可以将音乐播放任务中断的mdelay函数换成vTaskDelay,这样,在delay过程中音乐播放任务就会主动放弃cpu资源让其他任务工作了。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐