以下转载自安富莱电子: http://forum.armfly.com/forum.php
vTaskDelete() API 函数
任务可以使用 API 函数 vTaskDelete()删除自己或其它任务。
任务被删除后就不复存在,也不会再进入运行态。
空闲任务的责任是要将分配给已删除任务的内存释放掉。因此有一点很重要,那就
是使用 vTaskDelete() API 函数的任务千万不能把空闲任务的执行时间饿死。
需要说明一点,只有内核为任务分配的内存空间才会在任务被删除后自动回收。任
务自己占用的内存或资源需要由应用程序自己显式地释放。
在使用这个API函数之前,需要配置INCLUDE_vTaskDelete == 1。
刚开始,看历程有点不解,给一个任务句柄初始化为NULL,为什么删除任务(非自身任务)的时候,传入的还是句柄,句柄不是初始化为NULL了吗?思前想后觉得应该是xTaskCreate创建函数会更改任务句柄的值,果然,xTaskCreate函数接受的任务句柄是个二级指针,就算我们给任务句柄初始化为NULL,xTaskCreate函数执行之后,任务句柄会被更改为一个非NULL指针。所以就有了下面的代码:
//初始化任务句柄
static TaskHandle_t xHandleTaskLED1 = NULL;
static TaskHandle_t xHandleTaskBeep = NULL;
//创建任务
static void AppTaskCreate(void) { xTaskCreate(vTaskLed1, /* 任务函数名 */ "Task Led1", /* 任务名,字符串形式,方便调试 */ 512, /* 栈大小,单位为字,即4个字节 */ (void *)&task_led3, /* 任务形参 */ 1, /* 优先级,数值越大,优先级越高 */ &xHandleTaskLED1); /* 任务句柄 */ xTaskCreate( vTaskBeep, "Task Beep", 512, NULL, 2, &xHandleTaskBeep); }
//在任务beep中删除led任务
void vTaskBeep(void *pvParameters) { /* 任务都是一个无限循环,不能返回 */ while(1) { BEEP_ON; /* 阻塞延时,单位ms */ vTaskDelay( 20 ); BEEP_OFF; vTaskDelay( 500 ); if(xHandleTaskLED1!=NULL) vTaskDelete(xHandleTaskLED1); } }
led的任务句柄,虽然初始化为NULL,但是任务创建函数执行之后,任务句柄(是个一级指针)会被二级指针改变,所以当它不是NULL的时候,证明led任务被创建,就可以在beep中将其删除,如果要删除beep任务自身,vTaskDelete(NULL)即可。
改变任务优先级
vTaskPrioritySet() API 函数
API 函数 vTaskPriofitySet()可以用于在调度器启动后改变任何任务的优先级。
函数 vTaskPrioritySet 用于实现 FreeRTOS 任务优先级的修改。
第 1 个参数是任务句柄,用于区分不同的任务。
第 2 个参数是给任务配置的新优先级。
使用这个函数要注意以下问题:
1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_vTaskPrioritySet 1
2. 如果第一个参数里面填的是 NULL,即数值 0 的话,那么配置的就是当前正在执行的任务。
3. 如果被修改的任务的优先级,修改后高于正在执行的任务,将执行任务切换,切换到修改好的高优先级任务。
4. 第二个参数数值不可大于等于 FreeRTOSConfig.h 文件中的宏定义:
#define configMAX_PRIORITIES 配置的数值。
使用这个函数要注意以下问题:
1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_vTaskPriorityGet 1
2. 如果第一个参数里面填的是 NULL,即数值 0 的话,那么获取的优先级就是当前正在执行的任务。
改变任务优先级
调度器总是在所有就绪态任务中选择具有最高优先级的任务,并使其进入运行态。
本例即是通过调用 vTaskPrioritySet() API 函数来改变两个任务的相对优先级,以达到
对调度器这一行为的演示。
在不同的优先级上创建两个任务。这两个任务都没有调用任何会令其进入阻塞态的
API 函数,所以这两个任务要么处于就绪态,要么处于运行态——这种情形下,调度器
选择具有最高优先级的任务来执行。
所以,我们创建任务一LED亮,优先级1,任务二,蜂鸣器响,优先级2。这样在不阻塞的情况下,只会执行任务2,蜂鸣器响,但是,我们在任务二中,修改任务一的优先级,使它高于任务二。步骤如下:
void vTaskLed1(void *pvParameters) { /* 任务都是一个无限,不能返回 */ int *piParameters; piParameters=(int *)pvParameters; while(1) { if(*piParameters==1) { LED1( ON ); /* 阻塞延时,单位ms */ vTaskDelay( 500 ); LED1( OFF ); vTaskDelay( 500 ); } else if(*piParameters==2) { LED2( ON ); /* 阻塞延时,单位ms */ vTaskDelay( 500 ); LED2( OFF ); vTaskDelay( 500 ); } else if(*piParameters==3) { LED3( ON ); } } } /********************************************************************************* * @ 函数名 : vTaskBeep * @ 功能说明: Beep 任务 * @ 参数 : pvParameters,当任务创建的时候传进来,可以没有 * @ 返回值 : 无 ********************************************************************************/ void vTaskBeep(void *pvParameters) { /* 任务都是一个无限循环,不能返回 */ while(1) { BEEP_ON; } }
上面代码,任务2,beep优先级为2,任务1,led优先级为1,没有阻塞操作,调度器只执行优先级高的任务2,但是,我们更改任务2代码如下:
void vTaskBeep(void *pvParameters) { /* 任务都是一个无限循环,不能返回 */ while(1) { BEEP_ON; vTaskPrioritySet(xHandleTaskLED1,3); } }
把任务一优先级设成3,这样任务2运行到vTaskPrioritySet ()函数后(就算vTaskPrioritySet 函数后面还有程序都不会再执行),调度器会重新选择优先级更高的执行。
再试试我们用vTaskPrioritySet 的NULL参数修改自身优先级为1,这样任务1,2优先级都是1,这样都可以运行。
void vTaskBeep(void *pvParameters) { /* 任务都是一个无限循环,不能返回 */ while(1) { BEEP_ON; vTaskPrioritySet(NULL,1); } }