挂起和恢复函数:
/*
功能:挂起一个任务;
参数:xTaskToSuspend
xTaskToSuspend = xTaskCreate();
xTaskToSuspend = xTaskCreateStatic();
xTaskToSuspend = xTaskGetHandle();
或通过xTaskCreate & xTaskCreateStatic两个函数的最后一个形参
这四种方式获得要挂起任务的句柄。
若xTaskToSuspend = NULL 挂起任务本身
*/
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
/*
功能:从任务中恢复一个任务;
*/
void vTaskResume( TaskHandle_t xTaskToResume )
/*
功能:从中断中恢复一个任务;
pdTRUE:退出中断服务函数后,需要一次上下文切换
pdFALSE:退出中断服务函数后,不需要一次上下文切换
*/
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
在任务中恢复任务测试代码:
#include "gd32f30x.h"
#include "led.h"
#include "systick.h"
#include <stdio.h>
#include "SEGGER_RTT.h"
#include "FreeRTOS.h"
#include "task.h"
//任务优先级
#define START_TASK_PRIO ( tskIDLE_PRIORITY + 1 )
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务优先级
#define LED1_TASK_PRIO ( tskIDLE_PRIORITY + 2 )
//任务堆栈大小
#define LED1_STK_SIZE 128
//任务句柄
TaskHandle_t LED1_Task_Handler;
//任务优先级
#define LED2_TASK_PRIO ( tskIDLE_PRIORITY + 3 )
//任务堆栈大小
#define LED2_STK_SIZE 128
//任务句柄
TaskHandle_t LED2_Task_Handler;
//任务函数
void start_task(void *pvParameters);
void LED1_task(void *pvParameters);
void LED2_task(void * pvParameters);
int main(void)
{
/* configure 4 bits pre-emption priority */
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
GW_LedInit(LED1);
GW_LedInit(LED2);
xTaskCreate(
(TaskFunction_t ) start_task,
(const char* ) "start_task",
(configSTACK_DEPTH_TYPE ) START_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t* ) &StartTask_Handler
);
/* start scheduler */
vTaskStartScheduler();
while(1){
}
}
void start_task(void * pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
xTaskCreate(
(TaskFunction_t ) LED1_task,
(const char* ) "LED1_task",
(configSTACK_DEPTH_TYPE ) LED1_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) LED1_TASK_PRIO,
(TaskHandle_t* ) &LED1_Task_Handler
);
xTaskCreate(
(TaskFunction_t ) LED2_task,
(const char* ) "LED2_task",
(configSTACK_DEPTH_TYPE ) LED2_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) LED2_TASK_PRIO,
(TaskHandle_t* ) &LED2_Task_Handler
);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
uint16_t tmp_cnt=0;
void LED1_task(void * pvParameters)
{
for( ;; ){
/* toggle LED1 each 500ms */
GW_LedToggle(LED1);
SEGGER_RTT_printf(0,RTT_CTRL_RESET"LED1 Task!\r\n");
vTaskDelay(250);
}
}
void LED2_task(void * pvParameters)
{
for( ;; ){
tmp_cnt++;
/* toggle LED2 each 500ms */
GW_LedToggle(LED2);
SEGGER_RTT_printf(0,RTT_CTRL_RESET"LED2 Task!\r\n");
vTaskDelay(500);
if(tmp_cnt==3)
{
SEGGER_RTT_printf(0,RTT_CTRL_TEXT_RED"LED1 Task Suspend!\r\n");
vTaskSuspend(LED1_Task_Handler);//挂起LED1 task
}
if(tmp_cnt==5)
{
SEGGER_RTT_printf(0,RTT_CTRL_TEXT_YELLOW"LED1 Task Resume!\r\n");
vTaskResume(LED1_Task_Handler);//恢复LED1 task
tmp_cnt=0;
}
}
}
测试结果:
按键中断测试代码:
#include "gd32f30x.h"
#include "led.h"
#include "systick.h"
#include <stdio.h>
#include "SEGGER_RTT.h"
#include "FreeRTOS.h"
#include "task.h"
//任务优先级
#define START_TASK_PRIO ( tskIDLE_PRIORITY + 1 )
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务优先级
#define LED1_TASK_PRIO ( tskIDLE_PRIORITY + 2 )
//任务堆栈大小
#define LED1_STK_SIZE 128
//任务句柄
TaskHandle_t LED1_Task_Handler;
//任务优先级
#define LED2_TASK_PRIO ( tskIDLE_PRIORITY + 3 )
//任务堆栈大小
#define LED2_STK_SIZE 128
//任务句柄
TaskHandle_t LED2_Task_Handler;
//任务函数
void start_task(void *pvParameters);
void LED1_task(void *pvParameters);
void LED2_task(void * pvParameters);
void key_init(void);
int main(void)
{
/* configure 4 bits pre-emption priority */
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
GW_LedInit(LED1);
GW_LedInit(LED2);
key_init();
xTaskCreate(
(TaskFunction_t ) start_task,
(const char* ) "start_task",
(configSTACK_DEPTH_TYPE ) START_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t* ) &StartTask_Handler
);
/* start scheduler */
vTaskStartScheduler();
while(1){
}
}
void start_task(void * pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
xTaskCreate(
(TaskFunction_t ) LED1_task,
(const char* ) "LED1_task",
(configSTACK_DEPTH_TYPE ) LED1_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) LED1_TASK_PRIO,
(TaskHandle_t* ) &LED1_Task_Handler
);
xTaskCreate(
(TaskFunction_t ) LED2_task,
(const char* ) "LED2_task",
(configSTACK_DEPTH_TYPE ) LED2_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) LED2_TASK_PRIO,
(TaskHandle_t* ) &LED2_Task_Handler
);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
uint16_t tmp_cnt=0;
void LED1_task(void * pvParameters)
{
for( ;; ){
/* toggle LED1 each 500ms */
GW_LedToggle(LED1);
SEGGER_RTT_printf(0,RTT_CTRL_RESET"LED1 Task!\r\n");
vTaskDelay(250);
}
}
void LED2_task(void * pvParameters)
{
for( ;; ){
tmp_cnt++;
/* toggle LED2 each 500ms */
GW_LedToggle(LED2);
SEGGER_RTT_printf(0,RTT_CTRL_RESET"LED2 Task!\r\n");
vTaskDelay(500);
if(tmp_cnt==3)
{
SEGGER_RTT_printf(0,RTT_CTRL_TEXT_RED"LED1 Task Suspend!\r\n");
vTaskSuspend(LED1_Task_Handler);//挂起LED1 task
}
// if(tmp_cnt==5)
// {
// SEGGER_RTT_printf(0,RTT_CTRL_TEXT_YELLOW"LED1 Task Resume!\r\n");
// vTaskResume(LED1_Task_Handler);//恢复LED1 task
// tmp_cnt=0;
// }
}
}
void key_init(void)
{
/* enable the key clock */
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
/* configure button pin as input */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ,GPIO_PIN_0);
{
/* enable and set key EXTI interrupt to the lowest priority */
nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
/* connect key EXTI line to key GPIO pin */
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA,GPIO_PIN_SOURCE_0);
/* configure key EXTI line */
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_0);
}
}
void EXTI0_IRQHandler(void)
{
BaseType_t YieldRequired;
if(RESET != exti_interrupt_flag_get(EXTI_0)){
SEGGER_RTT_printf(0,RTT_CTRL_TEXT_YELLOW"LED1 Task Interrupt Resume!\r\n");
YieldRequired=xTaskResumeFromISR(LED1_Task_Handler);//恢复任务2
if(YieldRequired==pdTRUE)
{
/*如果函数xTaskResumeFromISR()返回值为pdTRUE,那么说明要恢复的这个
任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务),所以在
退出中断的时候一定要进行上下文切换!*/
portYIELD_FROM_ISR(YieldRequired);
}
tmp_cnt=0;
}
exti_interrupt_flag_clear(EXTI_0);
}
测试结果: