三.Free RTOS任务

一.任务创建和删除

<一>.任务创建和删除的API函数

任务的创建和删除的本质就是调用FreeRTOS的API函数

API函数描述
xTaskCreate()动态方式创建任务
xTaskCreateStatic()静态方式创建任务
vTaskDelete()删除任务
  • 动态创建任务:任务的任务控制块以及任务的栈空间所需的内存,均由FreeRTOS从FreeRTOS管理的堆中分配;
  • 静态创建任务:任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供。 

1.动态创建函数 

动态创建任务函数:

返回值描述
pdPASS任务创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY任务创建失败

实现动态创建任务流程:

  1. 将宏configSUPPORT_DYNAMIC_ALLOCATION 配置为 1 ;
  2. 定义函数入口函数;
  3. 编写任务函数。

此函数创建的任务会立刻进入就绪态,由任务调度器调度运行。

动态创建任务函数内部实现:

  1. 申请堆栈内存&任务控制块内存;
  2. TCB结构体成员赋值;
  3. 添加新任务到就绪列表中。 

任务控制块结构体成员介绍: 

typedef struct  tskTaskControlBlock       
{
    	volatile StackType_t 		* pxTopOfStack; 					/* 任务栈栈顶,必须为TCB的第一个成员 */
   	ListItem_t 			xStateListItem;           					/* 任务状态列表项 */      
	ListItem_t 			xEventListItem;					/* 任务事件列表项 */     
    	UBaseType_t 			uxPriority;                					/* 任务优先级,数值越大,优先级越大 */
    	StackType_t 			* pxStack;						/* 任务栈起始地址 */
    	char 				pcTaskName[ configMAX_TASK_NAME_LEN ]; 	/* 任务名字 */		
	…
	省略很多条件编译的成员
} tskTCB;

 注意:

  • 任务栈栈顶,在任务切换时的任务上下文保存、任务恢复息息相关;
  • 每个任务都有属于自己的任务控制块,类似身份证。 

2.静态创建函数 

静态创建任务函数:

TaskHandle_t xTaskCreateStatic
(
    	TaskFunction_t		pxTaskCode,				/* 指向任务函数的指针 */
    	const char * const		pcName,				/* 任务函数名 */
    	const uint32_t			ulStackDepth, 			/* 任务堆栈大小注意字为单位 */
    	void * const			pvParameters, 			/* 传递的任务函数参数 */
    	UBaseType_t			uxPriority, 				/* 任务优先级 */
    	StackType_t * const		puxStackBuffer, 			/* 任务堆栈,一般为数组,由用户分配 */
    	StaticTask_t * const		pxTaskBuffer				/* 任务控制块指针,由用户分配 */
); 	
返回值描述
NULL用户没有提供相应的内存,任务创建失败
其他值任务句柄,任务创建成功

 静态创建任务使用流程:

3.任务删除函数 

void vTaskDelete(TaskHandle_t xTaskToDelete);

形参描述
xTaskToDelete待删除任务的任务句柄

用于删除已被创建的任务;

被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除。 

注意:

  • 当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务);
  • 空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄露 。 

 删除任务流程:

<二>.任务创建和删除(动态方法)

 demo.c

#include "demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.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 );

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO					2		 /* 定义任务优先级 */
#define TASK1_STACK_SIZE		128  /*创建任务堆栈大小*/
TaskHandle_t 										task1_handler; 	/* 定义任务句柄 */
void task1( void * pvParameters );

 /* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO					3		 /* 定义任务优先级 */
#define TASK2_STACK_SIZE		128  /*创建任务堆栈大小*/
TaskHandle_t 										task2_handler; 	/* 定义任务句柄 */
void task2( void * pvParameters );

 /* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO					25		 /* 定义任务优先级 */
#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,
								(const 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,
								(const char *								) 	 "task1", 
								(configSTACK_DEPTH_TYPE )	   TASK1_STACK_SIZE,
								(void * 								)		 NULL,
								(UBaseType_t 						)		 TASK1_PRIO,
								(TaskHandle_t * 				)		 &task1_handler );
								
 xTaskCreate(  (TaskFunction_t					)		 task2,
								(const char *								) 	 "task2", 
								(configSTACK_DEPTH_TYPE )	   TASK2_STACK_SIZE,
								(void * 								)		 NULL,
								(UBaseType_t 						)		 TASK2_PRIO,
								(TaskHandle_t * 				)		 &task2_handler );
								
 xTaskCreate(  (TaskFunction_t					)		 task3,
								(const char *								) 	 "task3", 
								(configSTACK_DEPTH_TYPE )	   TASK3_STACK_SIZE,
								(void * 								)		 NULL,
								(UBaseType_t 						)		 TASK3_PRIO,
								(TaskHandle_t * 				)		 &task3_handler );
								
 vTaskDelete(NULL);
	taskEXIT_CRITICAL();              /* 退出临界区 */
}

/* 任务一,实现LED0每500ms翻转一次 */
void task1( void * pvParameters )
{
	while(1)
	{
		printf("TASK1正在运行!\r\n");
		LED0_TOGGLE();
		vTaskDelay(500);
	}
}

/* 任务二,实现LED1每500ms翻转一次 */
void task2( void * pvParameters )
{
	while(1)
	{
		printf("TASK2正在运行!\r\n");
		LED1_TOGGLE();
		vTaskDelay(500);
	}
}

/* 任务三,判断按键KEY0,按下KEY0删除task1 */
void task3( void * pvParameters )
{
	
	while(1)
	{
		printf("TASK3正在运行!\r\n");
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11) == 1)
		{
			if(task1_handler != 0)
			{
				printf("删除TASK1!\r\n");
				vTaskDelete(task1_handler);
			}
		}
		vTaskDelay(10);
	}
}
	

demo.h

#ifndef _DEMO_H
#define _DEMO_H

void freertos_demo(void);

#endif

 main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "demo.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    usart_init(115200);                 /* 串口初始化为115200 */
    led_init();                         /* 初始化LED */

    
    freertos_demo();                    /* 运行FreeRTOS例程 */
}

临界区保护,就是保护哪些不想被打断的程序段。 

<三>.任务创建和删除(静态方法)

FreeRTOSConfig.h:设置静态申请内存为1

#include "demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.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; 	/* 定义任务句柄 */
StackType_t											start_task_stack[START_TASK_STACK_SIZE];
StaticTask_t										start_task_tcb;
void start_task( void * pvParameters );

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO					2		 /* 定义任务优先级 */
#define TASK1_STACK_SIZE		128  /*创建任务堆栈大小*/
TaskHandle_t 										task1_handler; 	/* 定义任务句柄 */
StackType_t											task1_stack[TASK1_STACK_SIZE];
StaticTask_t										task1_tcb;
void task1( void * pvParameters );

 /* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO					3		 /* 定义任务优先级 */
#define TASK2_STACK_SIZE		128  /*创建任务堆栈大小*/
TaskHandle_t 										task2_handler; 	/* 定义任务句柄 */
StackType_t											task2_stack[TASK2_STACK_SIZE];
StaticTask_t										task2_tcb;
void task2( void * pvParameters );

 /* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO					25		 /* 定义任务优先级 */
#define TASK3_STACK_SIZE		128  /*创建任务堆栈大小*/
TaskHandle_t 										task3_handler; 	/* 定义任务句柄 */
StackType_t											task3_stack[TASK3_STACK_SIZE];
StaticTask_t										task3_tcb;
void task3( void * pvParameters );

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

/* 空闲任务配置 */
StaticTask_t	idle_task_tcb;
StackType_t		idle_task_stack[configMINIMAL_STACK_SIZE];

/* 软件定时器任务配置 */
StaticTask_t	timer_task_tcb;
StackType_t		timer_task_stack[configTIMER_TASK_STACK_DEPTH];

/* 空闲任务内存分配 */
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                    StackType_t ** ppxIdleTaskStackBuffer,
                                    uint32_t * pulIdleTaskStackSize )
{
	* ppxIdleTaskTCBBuffer = &idle_task_tcb;									/* 空闲任务控制块 */
	* ppxIdleTaskStackBuffer = idle_task_stack;							/* 空闲任务的任务堆栈 */
	* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;			/* 空闲任务的任务堆栈大小 */
}

/* 软件定时器内存分配 */
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                     StackType_t ** ppxTimerTaskStackBuffer,
                                     uint32_t * pulTimerTaskStackSize )
{
	* ppxTimerTaskTCBBuffer = &timer_task_tcb;
	* ppxTimerTaskStackBuffer = timer_task_stack;
	* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
	start_task_handler = xTaskCreateStatic(   (TaskFunction_t )  				start_task,
																						( char * )							  "start_task", 
																						( uint32_t )							START_TASK_STACK_SIZE,
																						(void * ) 								NULL,
																						(UBaseType_t )					  START_TASK_PRIO,
																						(StackType_t * )				  start_task_stack,
																						(StaticTask_t * ) 				&start_task_tcb );
											
											
  vTaskStartScheduler();/* 开启任务调度器 */
}

void start_task( void * pvParameters )
{
	taskENTER_CRITICAL();				/* 进入临界区,关闭中断 */
 	task1_handler = xTaskCreateStatic(  (TaskFunction_t )  				task1,
																			( char * )							  "task1", 
																			( uint32_t )							TASK1_STACK_SIZE,
																			(void * ) 								NULL,
																			(UBaseType_t )					  TASK1_PRIO,
																			(StackType_t * )				  task1_stack,
																			(StaticTask_t * ) 				&task1_tcb );
											
		task2_handler = xTaskCreateStatic(  (TaskFunction_t )  			task2,
																				( char * )							  "task2", 
																				( uint32_t )							TASK2_STACK_SIZE,
																				(void * ) 								NULL,
																				(UBaseType_t )					  TASK2_PRIO,
																				(StackType_t * )				  task2_stack,
																				(StaticTask_t * ) 				&task2_tcb );
											
		task3_handler = xTaskCreateStatic(  (TaskFunction_t )  			task3,
																				( char * )							  "task3", 
																				( uint32_t )							TASK3_STACK_SIZE,
																				(void * ) 								NULL,
																				(UBaseType_t )					  TASK3_PRIO,
																				(StackType_t * )				  task3_stack,
																				(StaticTask_t * ) 				&task3_tcb );
								
		vTaskDelete(start_task_handler);
		taskEXIT_CRITICAL();              /* 退出临界区 */
}

/* 任务一,实现LED0每500ms翻转一次 */
void task1( void * pvParameters )
{
	while(1)
	{
		printf("TASK1正在运行!\r\n");
		LED0_TOGGLE();
		vTaskDelay(500);
	}
}

/* 任务二,实现LED1每500ms翻转一次 */
void task2( void * pvParameters )
{
	while(1)
	{
		printf("TASK2正在运行!\r\n");
		LED1_TOGGLE();
		vTaskDelay(500);
	}
}

/* 任务三,判断按键KEY0,按下KEY0删除task1 */
void task3( void * pvParameters )
{
	
	while(1)
	{
		printf("TASK3正在运行!\r\n");
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11) == 1)
		{
			if(task1_handler != 0)
			{
				printf("删除TASK1!\r\n");
				vTaskDelete(task1_handler);
			}
		}
		vTaskDelay(10);
	}
}
	

 main.c和demo.h文件和动态的一样,以后也最常使用动态创建任务。

 <四>.动态任务创建和删除的API函数解析(暂不学习)

二.FreeRTOS的任务挂起与恢复

<一>.任务的挂起与恢复的API函数

API函数描述
vTaskSuspend()挂起任务
vTaskResume()恢复被挂起的任务
xTaskResumeFromISR()在中断恢复被挂起的任务
  • 挂起:挂起任务类似暂停,可恢复;删除任务,无法恢复,类似“人死两清”;
  • 恢复:恢复被挂起的任务;
  • FromISR:带FromISR后缀是在中断函数中专用的API函数。

1.任务挂起函数介绍 

void vTaskSuspend(TaskHandle_t xTaskToSuspend)

形参描述
xTaskToSuspend待挂起任务的任务句柄
  • 此函数用于挂起任务,使用时需将宏 INCLUDE_vTaskSuspend  配置为 1;
  •  无论优先级如何,被挂起的任务都将不再被执行,直到任务被恢复 ;

注意:当传入的参数为NULL,则代表挂起任务自身(当前正在运行的任务)。

2.任务恢复函数介绍(任务中恢复) 

 任务中恢复被挂起函数:void vTaskResume(TaskHandle_t xTaskToResume)

形参描述
xTaskToResume 待恢复任务的任务句柄

使用该函数注意宏:INCLUDE_vTaskSuspend必须定义为 1;

 注意:任务无论被 vTaskSuspend() 挂起多少次,只需在任务中调用  vTakResume() 恢复一次,就可以继续运行。且被恢复的任务会进入就绪态!

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

中断中恢复被挂起函数: BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume) 

形参描述
xTaskToResume待恢复任务的任务句柄

函数:xTaskResumeFromISR返回值描述如下:

返回值描述
pdTRUE 任务恢复后需要进行任务切换
pdFALSE 任务恢复后不需要进行任务切换
  •  使用该函数注意宏:INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必须定义为 1;
  • 该函数专用于中断服务函数中,用于解挂被挂起任务;

注意:中断服务程序中要调用freeRTOS的API函数则中断优先级不能高于FreeRTOS所管理的最高优先级。

<二>.任务挂起与恢复实验

 demo.c

#include "demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.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 );

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO					2		 /* 定义任务优先级 */
#define TASK1_STACK_SIZE		128  /*创建任务堆栈大小*/
TaskHandle_t 										task1_handler; 	/* 定义任务句柄 */
void task1( void * pvParameters );

 /* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO					3		 /* 定义任务优先级 */
#define TASK2_STACK_SIZE		128  /*创建任务堆栈大小*/
TaskHandle_t 										task2_handler; 	/* 定义任务句柄 */
void task2( void * pvParameters );

 /* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO					25		 /* 定义任务优先级 */
#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,
								(const 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,
								(const char *								) 	 "task1", 
								(configSTACK_DEPTH_TYPE )	   TASK1_STACK_SIZE,
								(void * 								)		 NULL,
								(UBaseType_t 						)		 TASK1_PRIO,
								(TaskHandle_t * 				)		 &task1_handler );
								
 xTaskCreate(  (TaskFunction_t					)		 task2,
								(const char *								) 	 "task2", 
								(configSTACK_DEPTH_TYPE )	   TASK2_STACK_SIZE,
								(void * 								)		 NULL,
								(UBaseType_t 						)		 TASK2_PRIO,
								(TaskHandle_t * 				)		 &task2_handler );
								
 xTaskCreate(  (TaskFunction_t					)		 task3,
								(const char *								) 	 "task3", 
								(configSTACK_DEPTH_TYPE )	   TASK3_STACK_SIZE,
								(void * 								)		 NULL,
								(UBaseType_t 						)		 TASK3_PRIO,
								(TaskHandle_t * 				)		 &task3_handler );
								
 vTaskDelete(NULL);
	taskEXIT_CRITICAL();              /* 退出临界区 */
}

/* 任务一,实现LED0每500ms翻转一次 */
void task1( void * pvParameters )
{
	uint32_t task1_num = 0;
	while(1)
	{
		printf("task1_num:%d\r\n",++task1_num);
		LED0_TOGGLE();
		vTaskDelay(500);
	}
}

/* 任务二,实现LED1每500ms翻转一次 */
void task2( void * pvParameters )
{
	uint32_t task2_num = 0;
	while(1)
	{
		
		printf("task2_num:%d\r\n",++task2_num);
		LED1_TOGGLE();
		vTaskDelay(500);
	}
}

/* 任务三,判断按键KEY0,按下KEY0删除task1 */
void task3( void * pvParameters )
{
	
	while(1)
	{
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_11) == 1)
		{
				vTaskSuspend(task1_handler);
		}
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12) == 1)
		{
				vTaskResume(task1_handler);
		}
		vTaskDelay(10);
	}	
}

	

 demo.h 和 main.c和之前的一样。

<三>.任务挂起和恢复API函数解析(暂不学习)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值