FreeRTOS任务挂起和恢复

挂起和恢复函数:

/*
	功能:挂起一个任务;
	参数: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);
}

测试结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值