freeRTOS总结(三)任务挂起和恢复

1,任务的挂起与恢复的API函数(熟悉)

freeRTOS总结(三)任务挂起和恢复_第1张图片
任务挂起和恢复的区别
挂起还能被恢复,删除任务后无法恢复。
带FromISR后缀是在中断函数中专用的API函数

1.1任务挂起函数介绍

void vTaskSuspend(TaskHandle_t xTaskToSuspend)
xTaskToSuspend 待挂起任务的任务句柄
此函数用于挂起任务,使用时需将宏 INCLUDE_vTaskSuspend 配置为 1。
无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复 。
注意:当传入的参数为NULL,则代表挂起任务自身(当前正在运行的任务)

1.2任务恢复函数介绍(任务中恢复)

void vTaskResume(TaskHandle_t xTaskToResume)
xTaskToResume 待恢复任务的任务句柄
使用该函数注意宏:INCLUDE_vTaskSuspend必须定义为 1
注意:任务无论被 vTaskSuspend() 挂起多少次,只需在任务中调用 vTakResume() 恢复一次,就可以继续运行。且被恢复的任务会进入就绪态!

1.3任务恢复函数介绍(中断中恢复)

BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume)
xTaskToResume 待恢复任务的任务句柄

xTaskResumeFromISR返回值描述如下:
pdTRUE 任务恢复后需要进行任务切换(被恢复任务优先级>当前任务优先级)
pdFALSE 任务恢复后不需要进行任务切换
使用该函数注意宏:INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必须定义为 1
注意:中断服务程序中要调用freeRTOS的API函数则中断优先级不能高于FreeRTOS所管理的最高优先级

2实验

2.1实验目的

freeRTOS总结(三)任务挂起和恢复_第2张图片

2.2实验实现过程

首先打开宏
freeRTOS总结(三)任务挂起和恢复_第3张图片
freeRTOS总结(三)任务挂起和恢复_第4张图片
freeRTOS总结(三)任务挂起和恢复_第5张图片
设置NVIC分组为4

/**
 ****************************************************************************************************
 * @file        freertos.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.4
 * @date        2022-01-04
 * @brief       FreeRTOS 移植实验
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 F407电机开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO         1
#define START_TASK_STACK_SIZE   128
TaskHandle_t    start_task_handler;
void start_task( void * pvParameters );



#define TASK1_PRIO         2
#define TASK1_STACK_SIZE   128
TaskHandle_t   task1_handler;
void task1( void * pvParameters );


#define TASK2_PRIO         3
#define TASK2_STACK_SIZE   128
TaskHandle_t   task2_handler;
void task2( void * pvParameters );


#define TASK3_PRIO         4
#define TASK3_STACK_SIZE   128
TaskHandle_t   task3_handler;
void task3( void * pvParameters );


/******************************************************************************************************/


/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
	xTaskCreate((TaskFunction_t) start_task,
							(char *)	"start_task",
							(configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,
							(void *) NULL,
							(UBaseType_t) START_TASK_PRIO,
							(TaskHandle_t *)&start_task_handler
	
	);
	//开启任务调度
	vTaskStartScheduler();

}
void start_task( void * pvParameters )
{
	 taskENTER_CRITICAL();               /* 进入临界区  任何任务和中断都不能打断当前程序运行*/
		xTaskCreate((TaskFunction_t) task1,
							(char *)	"task1",
							(configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,
							(void *) NULL,
							(UBaseType_t) TASK1_PRIO,
							(TaskHandle_t *)&task1_handler	);
		 xTaskCreate((TaskFunction_t) task2,
							(char *)	"task2",
							(configSTACK_DEPTH_TYPE) TASK2_STACK_SIZE,
							(void *) NULL,
							(UBaseType_t) TASK2_PRIO,
							(TaskHandle_t *)&task2_handler	);					
			xTaskCreate((TaskFunction_t) task3,
							(char *)	"task3",
							(configSTACK_DEPTH_TYPE) TASK3_STACK_SIZE,
							(void *) NULL,
							(UBaseType_t) TASK3_PRIO,
							(TaskHandle_t *)&task3_handler	);
	vTaskDelete(NULL);//删除当前任务也就是开始任务
	taskEXIT_CRITICAL();
							
	

}

void task1( void * pvParameters )
{
	uint32_t task1_num=0;
	while(1)
	{
		task1_num++;
		printf("task1_num= %d \n",task1_num);
		LED0_TOGGLE();
		vTaskDelay(500);
	
	
	}
}

void task2( void * pvParameters )
{

	uint32_t task2_num=0;
	while(1)
	{
		task2_num++;
		printf("task2_num= %d \n",task2_num);
		LED1_TOGGLE();
		vTaskDelay(500);
	
	
	}
}


void task3( void * pvParameters )
{
	//静态变量在程序运行期间只会被初始化一次,即使经过多次函数调用或程序执行。因此,在程序下次运行时,静态变量的值将保持上一次程序运行结束时的值,并不会重新赋初值。
	//如果未显式指定初始值,则静态变量将根据其类型自动初始化为默认值。例如,静态变量 uint8_t key_up 初始值为 0。
	static uint8_t key =0;

	while(1)
	{
	
		key = key_scan(0);
		if(key==KEY0_PRES)
		{
			/*挂起任务1*/
			vTaskSuspend(task1_handler);
			
		}
		else if(key==KEY1_PRES)
		{
			/*恢复任务1*/
			vTaskResume(task1_handler);
		
		}
		 vTaskDelay(10);
	
	}
}



外部中断触发函数

void KEY2_INT_IRQHandler(void)
{ 
    HAL_GPIO_EXTI_IRQHandler(KEY2_INT_GPIO_PIN);        /* 调用中断处理公用函数 清除KEY2所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN);        /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}


/**
 * @brief       中断服务程序中需要做的事情
 *              在HAL库中所有的外部中断服务函数都会调用此函数
 * @param       GPIO_Pin:中断引脚号
 * @retval      无
 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(20);      /* 消抖 */
 
    BaseType_t xYieldRequired;
     if (KEY2 == 0)
     {
			 	xYieldRequired = xTaskResumeFromISR(task1_handler);
				
     }
		 if(xYieldRequired==pdTRUE)
		 {
				portYIELD_FROM_ISR(xYieldRequired );
		 }

    
}

/**
 * @brief       外部中断初始化程序
 * @param       无
 * @retval      无
 */
void extix_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    key_init();  
    gpio_init_struct.Pin = KEY2_INT_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下降沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &gpio_init_struct);    /* KEY2配置为下降沿触发中断 */
    


    HAL_NVIC_SetPriority(KEY2_INT_IRQn, 6,0);               /* 抢占2,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY2_INT_IRQn);                       /* 使能中断线2 */

}

注意NVIC配置HAL_NVIC_SetPriority(KEY2_INT_IRQn, 6,0);优先级要在5-15之间
官方参考链接
https://www.freertos.org/zh-cn-cmn-s/taskresumefromisr.html

你可能感兴趣的:(freeRTOS,嵌入式硬件,单片机)