FreeRtos任务恢复与挂起
本篇内容分享的是FreeRtos中的任务恢复与挂起。 有时候我们需要将暂停某个任务的运行,过一段时间以后在重新运行。这个时候是要适应任务删除和重建的方法的话那么任务中变量保存的值肯定丢了!FreeRtos给我们提供了解决这种问题的方法,那就是任务的恢复与挂起,当莫个任务要停止运行一段时间的话就将这个任务挂起,当要重新运行这个任务的话就恢复这个任务的运行,FreeRtos的任务挂起与恢复API函数如下:
vTaskSuspend()函数
此函数用于将某个任务设置为挂起态,进入挂起态的任务永远都不会进入运行态。退出挂起态的唯一方法就是调用任务恢复函数 vTaskResume()xTaskResumeFromISR()
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
要挂起的任务的任务句柄,创建任务的时候会为每个任务分配一个任务句柄。如果使用函数 xTaskCreate()创建任务的话那么函数的参数pxCreatedTask 就是此任务的任务句柄,如果使用函数 xTaskCreateStatic()创建任务的话那么函数的返回值就是此任务的任务句柄。也可以通过函数 xTaskGetHandle()来根据任务名字来获取某个任务的任务句柄。 注意!如果参数为 NULL 的话表示挂起任务自己。
vTaskResume()
void vTaskResume( TaskHandle_t xTaskToResume )
将一个任务从挂起态恢复到就绪态,只有通过函数 vTaskSuspend()设置为挂起态的任务才可以使用 vTaskRexume()恢复。
xTaskResumeFromISR()
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume)
此函数是 vTaskResume()的中断版本,用于在中断服务函数中恢复一个任务 返回值: pdTrue:恢复运行的任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务),这意味着在退出中断服务函数以后必须进行一次上下文切换。 pdFALSE: 恢复运行的任务的任务优先级低于当前正在运行的任务(被中断打断的 任务),这意味着在退出中断服务函数的以后不需要进行上下文切换。
实验需求
通过两个按键来控制LED0的挂起与恢复
key.h
#ifndef _KEY_H_
#define _KEY_H_
#include "stm32f10x.h"
#include "delay.h"
#define GPIO_PORT GPIOB
#define GPIO_PIN GPIO_Pin_4|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9
#define KEY0 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_9)
#define KEY1 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_8)
#define KEY2 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_7)
#define KEY3 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_6)
#define KEY4 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_4)
#define KEY_ON 0
#define KEY_OFF -1
#define KEY0_Value 1
#define KEY1_Value 2
#define KEY2_Value 3
#define KEY3_Value 4
#define KEY4_Value 5
#define Error -2
void KEY_GPIO_INIT(void);
unsigned char KEY_Scan(void);
#endif
key.c
void KEY_GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
unsigned char KEY_Scan(void)
{
if(KEY0==0||KEY1==0||KEY2==0||KEY3==0)
{
delay_ms(20);
if(KEY0==0)
{
while(KEY0 == 0);
return KEY0_Value;
}
else if(KEY1==0)
{
while(KEY1 == 0);
return KEY1_Value;
}
else if(KEY2==0)
{
while(KEY2 == 0);
return KEY2_Value;
}
else if(KEY3==0)
{
while(KEY3 == 0);
return KEY3_Value;
}
else if(KEY4==0)
{
while(KEY4 == 0);
return KEY4_Value;
}
}
return 0;
}
主函数
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"
#define START_TASK_PRIO 1
#define START_STK_SIZE 128
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
#define LED0_TASK_PRIO 4
#define LED0_STK_SIZE 50
TaskHandle_t LED0Task_Handler;
void led0_task(void *pvParameters);
#define LED1_TASK_PRIO 3
#define LED1_STK_SIZE 50
TaskHandle_t LED1Task_Handler;
void led1_task(void *pvParameters);
#define KEY_TASK_PRIO 2
#define KEY_STK_SIZE 50
TaskHandle_t KEYTask_Handler;
void key_task(void *pvParameters);
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
delay_init();
uart_init(115200);
LED_Init();
KEY_GPIO_INIT();
xTaskCreate((TaskFunction_t )start_task,
(const char* )"start_task",
(uint16_t )START_STK_SIZE,
(void* )NULL,
(UBaseType_t )START_TASK_PRIO,
(TaskHandle_t* )&StartTask_Handler);
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t )led0_task,
(const char* )"led0_task",
(uint16_t )LED0_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED0_TASK_PRIO,
(TaskHandle_t* )&LED0Task_Handler);
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
xTaskCreate((TaskFunction_t )key_task,
(const char* )"key_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEYTask_Handler);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
void led0_task(void *pvParameters)
{
while(1)
{
LED0=~LED0;
vTaskDelay(500);
printf("led1 is running\r\n");
}
}
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
printf("led2 is running\r\n");
}
}
void key_task(void *pvParameters)
{
while(1)
{
if(GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_9) == 0)
{
delay_ms(20);
while(GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_9) == 0);
vTaskDelay(100);
vTaskSuspend(LED0Task_Handler);
printf("Task0 is Suspend\r\n");
}
if(GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_8) == 0)
{
delay_ms(20);
while(GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_8) == 0);
vTaskDelay(100);
vTaskResume(LED0Task_Handler);
printf("Task0 is Resume\r\n");
}
}
}
实验结果
|