任务的挂起与恢复
相关API函数:(使用对应函数要去修改宏对应的值)
1.vTaskSuspend(): 挂起任务
2.vTaskResume():恢复任务运行
3.vTaskResumeFromISR():中断服务函数中恢复一个任务的运行
那么问题来了,为什么我们不能像上节那样用删除再创建来控制任务的运行呢?
原因其实很明显,不仅是写代码变得冗杂,而且删除任务这个操作,会把之前任务的堆载删除,然后后面想运行这个任务就找不到了。但是如果只是挂起,它的任务堆载及其数据都是有效的。
我们来链接上一节的代码来完善一下
观前知识拓展:
what is 临界区?
简单来说,临界区是多个访问资源共用的一个程序片段。当某个线程进入时,其他线程需要等待,防止程序因这些共用资源而发生出错。
#define START_TASK_PRIO 1//任务优先级(这里一般不设为0,因为系统开启需要一个空闲函数)
#define START_STK_SIZE 120//任务内存
void start_task(void*pvParameters);//任务函数
TaskHandle_t StartTask_Handler;//任务句柄
#define TASK1_TASK_PRIO 2//任务优先级(这里一般不设为0,因为系统开启需要一个空闲函数)
#define TASK1_STK_SIZE 120//任务内存
void task1_task(void*pvParameters);//任务函数
TaskHandle_t Task1Task_Handler;//任务句柄
#define TASK2_TASK_PRIO 3//任务优先级(这里一般不设为0,因为系统开启需要一个空闲函数)
#define TASK2_STK_SIZE 120//任务内存
void task2_task(void*pvParameters);//任务函数
TaskHandle_t Task2Task_Handler;//任务句柄
int main
{
xTaskCreate(
(TaskFunction_t)start_task,
(char* )"start_task",
(uint16_t )START_STK_SIZE,
(void* )NULL,
(UBaseType_t )START_TASK_PRIO,
(TaskHandle_t* )&StartTask_Handler,
);//创建任务环
vTaskStartScheduler();//开启任务调度
}
void start_task(void*pvParemeters)
{
taskENTER_CRITICAL();//进入临界区
//创建任务一
xTaskCreate((TaskFunction_t)task1_task,
(char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler,);
//创建任务二
xTaskCreate((TaskFunction_t)task2_task,
(char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler,);
vTaskDelete(StartTask_Handler);//删除任务,注意要用该任务的任务句柄
taskEXIT_CRITICAL(); // 退出临界区
}
//这里我们写一个识别颜色的程序
void task1_task(void*pvParemeters//这里的意思是动态创建任务函数)
{
u8 task1_num=0;//系统运行次数,加到255次会清零。
Read_OpenData();//识别颜色外设(接收openmv的数据)
//假定读取颜色green正确赋值为一,假定接收五次任务挂起
while(1)
{
if(green==1)
{
task1_num++;
if(task==5)
{
printf("green")
vTaskSuspend();//挂起当前任务
}
}
}
}
void task2_task(void*pvParemeters//这里的意思是动态创建任务函数
{
while(1)
{
/*写具体的任务*/
}
}
```
####
接下来我们来引用一下正点原子的设计实验
1.设计实验
(1)本实验设计4个任务:start_task,key_task,task1_task和task2_task
start_task:用来创建其他三个任务。
key_task: 按键服务任务,检测按键的按下结果,根据不同的按键结果执行不同操作
task1_task:应用任务1
task2_task:应用任务2
#define START_TASK_PRIO 1//任务优先级(这里一般不设为0,因为系统开启需要一个空闲函数)
#define START_STK_SIZE 120//任务内存
void start_task(void*pvParameters);//任务函数
TaskHandle_t StartTask_Handler;//任务句柄
#define KEY_TASK_PRIO 2//任务优先级(这里一般不设为0,因为系统开启需要一个空闲函数)
#define KEY_STK_SIZE 120//任务内存
void KEY_task(void*pvParameters);//任务函数
TaskHandle_t KEYTask_Handler;//任务句柄
#define TASK1_TASK_PRIO 3//任务优先级(这里一般不设为0,因为系统开启需要一个空闲函数)
#define TASK1_STK_SIZE 120//任务内存
void task1_task(void*pvParameters);//任务函数
TaskHandle_t Task1Task_Handler;//任务句柄
#define TASK2_TASK_PRIO 4//任务优先级(这里一般不设为0,因为系统开启需要一个空闲函数)
#define TASK2_STK_SIZE 120//任务内存
void task2_task(void*pvParameters);//任务函数
TaskHandle_t Task2Task_Handler;//任务句柄
int main
{
xTaskCreate(
(TaskFunction_t)start_task,
(char* )"start_task",
(uint16_t )START_STK_SIZE,
(void* )NULL,
(UBaseType_t )START_TASK_PRIO,
(TaskHandle_t* )&StartTask_Handler,
);//创建任务环
vTaskStartScheduler();//开启任务调度
}
void start_task(void*pvParemeters)
{
taskENTER_CRITICAL();//进入临界区
xTaskCreate((TaskFunction_t)key_task,
(char* )"key_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEYTask_Handler,);
//创建任务一
xTaskCreate((TaskFunction_t)task1_task,
(char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&TASK1Task_Handler,);
//创建任务二
xTaskCreate((TaskFunction_t)task2_task,
(char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&TASK2Task_Handler,);
vTaskDelete(StartTask_Handler);//删除任务,注意要用该任务的任务句柄
taskEXIT_CRITICAL(); // 退出临界区
}
void key_task(void*pvParemeters)//这里的意思是动态创建任务函数
{
u8 key;
while(1)
{
key=KEY_Scan(0);
switch(key)
{
case WKUP_PRES:
vTaskSuspend(Task1Task_Handler);//挂起任务一
vTaskSuspend(Task2Task_Handler);//挂起任务二
break;
case KEY1_PRES:
vTaskResume(Task1Task_Handler);
break;
}
}
}
//这里我们写一个识别颜色的程序
void task1_task(void*pvParemeters)//这里的意思是动态创建任务函数
{
u8 task1_num=0;//系统运行次数,加到255次会清零。
Read_OpenData();//识别颜色外设(接收openmv的数据)
//假定读取颜色正确赋值为一,假定接收五次任务挂起
while(1)
{
if(green==1)
{
task1_num++;
if(task==5)
{
vTaskResume(Task2Task_Handler);
printf("green")
//vTaskSuspend();//挂起当前任务
}
}
if(red==1)
{
task1_num++;
if(red==5)
{
vTaskResume(Task2Task_Handler);
printf("red")
//vTaskSuspend();//挂起当前任务
}
}
if(blue==1)
{
task1_num++;
if(task==5)
{
vTaskResume(Task2Task_Handler);
printf("blue")
//vTaskSuspend();//挂起当前任务
}
}
}
}
void task2_task(void*pvParemeters)//这里的意思是动态创建任务函数
{
while(1)
{
move();
}
}
```
####