FreeRTOS study notes - task suspension and recovery

1. Task suspend and resume API functions

In the project, we sometimes encounter certain tasks that need to be suspended for a period of time and then rerun after a period of time. Task suspension and resumption fulfills this need. When a task needs to be suspended for a period of time, it can be suspended. When you need to restart, just restore it. . The task suspension and recovery API functions of FreeRTOS are as follows

Task resume and suspend API functions

1.1 vTaskSuspend() function

The function of this function is to set a task to the pending state. Once a task enters the suspended state, it will never enter the running state. Unless the task recovery function vTaskResume() or xTaskResumeFromISR() is called. The task suspend function has the following input parameters

  • xTaskToSuspend
    The task handle of the task to suspend.如果需要挂起任务自身,该参数写NULL。

The task suspend function has no return value.

1.2 vTaskResume() function

The function of this function is to restore a task from the suspended state to the ready state. The task recovery function has the following input parameters

  • The task handle of the task that xTaskToResume
    needs to resume.

The task recovery function also has no return value.

1.3 xTaskResumeFromISR() function

The function of this function is to resume a task in the interrupt service function. The function has the following input parameters

  • xTaskToResume
    The task handle of the task to resume.

This function has the following return value


  • The task priority of the task resumed by pdTRUE is equal to or higher than that of the running task (the task interrupted by the interrupt), which means that a context switch must be performed after exiting the interrupt service function .
  • pdFALSE
    The task priority of the resumed task is lower than that of the currently running task (the task interrupted by the interrupt), which means that no context switch is required after exiting the interrupt service function.

2. Task suspend and resume

2.1 Task 1 suspends and unsuspends task 2

For task creation, see the previous article, task creation and deletion. Modify task 1 directly here. Task 1 is modified to suspend task 2 after running task 1 10 times. After running 10 more times, unhook task 2. The task 1 function is as follows

void taks1_task (void *pxCreatedTask)
{
    
    
	u8 task1Cunt = 0;   // 任务1运行次数计数变量
	
	while (1)
	{
    
    
		task1Cunt = task1Cunt + 1;   // task1运行次数加1
		
		Med_Led_StateReverse(LED0);   // LED0状态取反
		vTaskDelay(500);   // 延时500ms
		
		// 运行5次后
		if (task1Cunt == 10)
		{
    
    
			// 挂起任务2
			vTaskSuspend(TASK2Task_Handler);
		}
		if (task1Cunt == 20)
		{
    
    
			// 解挂任务2
			vTaskResume(TASK2Task_Handler);
		}
	}
}

2.2 Unsuspend task 1 during interruption

At the beginning, I tried to suspend and unsuspend task 1 in the external interrupt, and found that when task 1 was suspended, the program was abnormal. After querying, I found out, 在中断中不能使用挂起函数。so I adjusted it a bit. After task 2 runs 5 times, task 1 is suspended. Unhook task 1 through external interrupt.

Pay attention when unsuspending the task during the interrupt, you need to judge the return value of the function xTaskResumeFromISR(). 如果函数xTaskResumeFromISR()返回值为pdTRUE,那么说明要恢复的这个任务的任务优先级等于或者高于正在运行的任务(被中断打断的任务),所以在退出中断的时候一定要进行上下文切换.

The external interrupt program configuration is as follows

/*
 *==============================================================================
 *函数名称:Exit_Init
 *函数功能:初始化外部中断
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void Exit_Init (void)
{
    
    
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef  EXTI_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);   // 开启AFIO时钟

	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);   //选择GPIO管脚用作外部中断线路
	
	//EXTI0 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;   //EXTI0中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=6;   //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;   //子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	   //根据指定的参数初始化VIC寄存器
	
	EXTI_InitStructure.EXTI_Line=EXTI_Line0;   // EXIT0
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;   // 中断
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;   // 上升沿触发
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;   // 使能
	EXTI_Init(&EXTI_InitStructure);
}

The interrupt service function of the external interrupt is as follows

/*
 *==============================================================================
 *函数名称:EXTI0_IRQHandler
 *函数功能:外部中断0中断服务函数
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */

// 任务1的任务句柄
extern TaskHandle_t TASK1Task_Handler;

void EXTI0_IRQHandler(void)
{
    
    
	BaseType_t YieldRequired;	
	
	// 如果EXIT0中断标志位被置1
	if(EXTI_GetITStatus (EXTI_Line0)==1)
	{
    
    
		YieldRequired = xTaskResumeFromISR(TASK1Task_Handler);   // 恢复任务1
		
		if(YieldRequired == pdTRUE)
		{
    
    
			// 执行一次任务调度
			portYIELD_FROM_ISR(YieldRequired);
		}
	}
	EXTI_ClearITPendingBit (EXTI_Line0);   // 清除中断标志位
}

3. Supplementary content

3.1 FreeRTOS data types

In the portmacro.h header file, two data types are defined

  • TickType_t
    FreeRTOS interrupt count value type, which can be 16 bits or 32 bits. For 32-bit CPUs, TickType_t is preferably 32 bits.
  • BaseType_t
    enables the CPU to run the most efficient data type. For 32-bit CPUs, BaseType_t is uint32_t. A 16-bit CPU is uint16_t, and an 8-bit CPU is uint8_t.

3.2 Interrupt priority grouping

Priority grouping: The interrupt controller (NVIC) allows the bits defining the priority of each interrupt to be split into priority bits defining the interrupt and sub-priority bits defining the interrupt. For simplicity, all bits must be defined as preemptive priority bits . If this is not the case (if some bits indicate subpriority), the assertion below will fail.

简单来说,就是在设置优先级分组时,需要将全部的位都设置为抢占优先级。否则会导致程序异常。

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);   // 设置系统中断优先级分组4	

3.3 Error problem

When compiling, I found the following error message

Error message

该错误是因为“task.h”必须出现在“FreeRTOS.h”下面。

Guess you like

Origin blog.csdn.net/qq_45217381/article/details/131533531
Recommended