FreeRTOS学习笔记 & FreeRTOS任务创建

任务创建

什么是任务 ?

在裸机系统中,系统的主体就是 main 函数里面顺序执行的无限循环,这个
无限循环里面 CPU 按照顺序完成各种事情。
在多任务系统中,我们根据功能的不同,把整个系统分割成一个个独立的且无法返回的函数,这个函数我们称为任务

任务的大概形式具体代码如下所示:

void Application_Task_1(void *pvParameters)
{
	while(1)
	{
		void vTaskDelay( const TickType_t xTicksToDelay );
	}
}

任务的实现过程

任务栈

在多任务系统中,每个任务都是独立的,互不干扰的,所以要为每个任务都分配独立的栈空间,这个栈空间通常是一个预先定义好的全局数组,也可以是动态分配的一段内存空间,但它们都存在于 RAM 中

在多任务系统中,有多少个任务就需要定义多少个任务栈

任务函数

任务是一个独立的函数,函数主体无限循环且不能返回

//任务 1 函数
void task1_task(void *pvParameters)
{
	while(1)
	{
		LED1=0;
		vTaskDelay(200);
		LED1=1;
		vTaskDelay(800);
	}
}
//任务 2 函数
void task2_task(void *pvParameters)
{
	while(1)
	{
		LED2=0;
		vTaskDelay(800);
		LED2=1;
		vTaskDelay(200);
	}
}

任务控制块

在裸机系统中,程序的主体是 CPU 按照顺序执行的。
而在多任务系统中,任务的执行是由系统调度的。系统为了顺利的调度任务,为每个任务都额外定义了一个任务控制块,这个任务控制块就相当于任务的身份证,里面存有任务的所有信息,比如任务的栈指针,任务名称,任务的形参等。
有了这个任务控制块之后,以后系统对任务的全部操作都可以通过这个任务控制块来实现

typedef struct tskTaskControlBlock
{
	volatile StackType_t *pxTopOfStack; /* 栈顶 */ (1)
	ListItem_t xStateListItem; /* 任务节点 */ (2)
	StackType_t *pxStack; /* 任务栈起始地址 */ (3)
	/* 任务名称,字符串形式 */(4)
	char pcTaskName[ configMAX_TASK_NAME_LEN ];
} tskTCB;
typedef tskTCB TCB_t;

实现任务创建API函数

FreeRTOS提供2种任务创建的方式

动态方式创建 (推荐)

静态方式创建

任务创建-动态方法

动态方式创建首先配置下面2个宏定义

//支持动态内存申请
#define configSUPPORT_DYNAMIC_ALLOCATION        1

//系统所有总的堆大小
#define configTOTAL_HEAP_SIZE					((size_t)(36*1024))

动态创建任务函数

//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数 (1)
			(const char* )"start_task", //任务名称 (2)
			(uint16_t )START_STK_SIZE, //任务堆栈大小 (3)
			(void* )NULL, //传递给任务函数的参数 (4)
			(UBaseType_t )START_TASK_PRIO, //任务优先级 (5)
			(TaskHandle_t* )&StartTask_Handler); //任务句柄 (6)

代码(1):任务入口函数,即任务函数的名称,需要我们自己定义并且实现。
代码(2):任务名字,字符串形式,最大长度由 FreeRTOSConfig.h 中定义的 configMAX_TASK_NAME_LEN 宏指定,多余部分会被自动截掉,这里任务名字最好要与任务函数入口名字一致,方便进行调试。
代码(3):任务堆栈大小,单位为字,在 32 位的处理器下(STM32),一个字等于 4 个字节,那么任务大小就为 128 * 4 字节。
代码(4):任务入口函数形参,不用的时候配置为 0 或者 NULL 即可
代码(5):任务的优先级。优先级范围根据 FreeRTOSConfig.h 中的宏configMAX_PRIORITIES 决定,如果使能configUSE_PORT_OPTIMISED_TASK_SELECTION,这个宏定义,则最多支持 32 个优先级;如果不用特殊方法查找下一个运行的任务,那么则不强制要求限制最大可用优先级数目。在 FreeRTOS 中,数值越大优先级越高,0 代表最低优先级。
代码(6):任务控制块指针,在使用内存的时候,需要给任务初始化函数xTaskCreateStatic()传递预先定义好的任务控制块的指针。在使用动态内存的时候,任务创建函数 xTaskCreate()会返回一个指针指向任务控制块,该任务控制块是 xTaskCreate()函数里面动态分配的一块内存

动态创建任务例程

//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

int main()
{
	//创建开始任务
	xTaskCreate((TaskFunction_t )start_task, //任务函数
	(const char* )"start_task", //任务名称
	(uint16_t )START_STK_SIZE, //任务堆栈大小
	(void* )NULL, //传递给任务函数的参数
	(UBaseType_t )START_TASK_PRIO, //任务优先级
	(TaskHandle_t* )&StartTask_Handler); //任务句柄
	vTaskStartScheduler(); //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
	while(1)
	{
		vTaskDelay(200);
	}
}

任务创建-静态方法

当我们使用了静态创建任务的时候,configSUPPORT_STATIC_ALLOCATION 这个宏定义必须为 1(在 FreeRTOSConfig.h 文件中),
并且我们需要实现两个函数:
vApplicationGetIdleTaskMemory()与vApplicationGetTimerTaskMemory(),
这两个函数是用户设定的空闲(Idle)任务与定时器(Timer)任务的堆栈大小,必须由用户自己分配,而不能是动态分配

//支持静态内存
#define configSUPPORT_STATIC_ALLOCATION					1

//下面代码写在.C文件中
/*tasks.c会引用外部函数
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
	extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
#endif
*/
/* 空闲任务任务堆栈 */
static StackType_t Idle_Task_Stack[configMINIMAL_STACK_SIZE];
/* 定时器任务堆栈 */
static StackType_t Timer_Task_Stack[configTIMER_TASK_STACK_DEPTH];
/* 空闲任务控制块 */
static StaticTask_t Idle_Task_TCB;
/* 定时器任务控制块 */
static StaticTask_t Timer_Task_TCB;

//ppxIdleTaskTCBBuffer:任务控制块内存
//ppxIdleTaskStackBuffer:任务堆栈内存
//pulIdleTaskStackSize:任务堆栈大小
void vApplicationGetIdleTaskMemory(StaticTask_t**ppxIdleTaskTCBBuffer,
								StackType_t **ppxIdleTaskStackBuffer,
									uint32_t *pulIdleTaskStackSize)
{
		*ppxIdleTaskTCBBuffer=&Idle_Task_TCB;
		*ppxIdleTaskStackBuffer=Idle_Task_Stack;
		*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
//ppxTimerTaskTCBBuffer : 任务控制块内存
//ppxTimerTaskStackBuffer: 任务堆栈内存
//pulTimerTaskStackSize : 任务堆栈大小
void vApplicationGetTimerTaskMemory(StaticTask_t**ppxTimerTaskTCBBuffer,
									StackType_t **ppxTimerTaskStackBuffer,
									uint32_t *pulTimerTaskStackSize)
{
		*ppxTimerTaskTCBBuffer=&Timer_Task_TCB;/* 任务控制块内存 */
		*ppxTimerTaskStackBuffer=Timer_Task_Stack;/* 任务堆栈内存 */
		*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;/* 任务堆栈大小*/
}

静态创建任务函数

//创建开始任务
xTaskCreateStatic((TaskFunction_t )start_task, //任务函数 (1)
									(const char* )"start_task",//任务名称 (2)
									(uint32_t )START_STK_SIZE,//任务堆栈大小(3)
									(void* )NULL,//传递给任务函数的参数 (4)
									(UBaseType_t )START_TASK_PRIO, //任务优先级 (5)
									(StackType_t* )StartTaskStack,//任务堆栈 (6)
									(StaticTask_t* )&StartTaskTCB);//任务控制块 (7)

代码(1):任务入口函数,即任务函数的名称,需要我们自己定义并且实现。
代码(2):任务名字,字符串形式,最大长度由 FreeRTOSConfig.h 中定义的 configMAX_TASK_NAME_LEN 宏指定,多余部分会被自动截掉,这里任务名字最好要与任务函数入口名字一致,方便进行调试。
代码(3):任务堆栈大小,单位为字,在 32 位的处理器下(STM32),一个字等于 4 个字节,那么任务大小就为 128 * 4 字节。
代码(4):任务入口函数形参,不用的时候配置为 0 或者 NULL 即可。
代码(5):任务的优先级。优先级范围根据 FreeRTOSConfig.h 中的宏configMAX_PRIORITIES 决定,如果使能
configUSE_PORT_OPTIMISED_TASK_SELECTION,这个宏定义,则最多支持 32 个优先级;如果不用特殊方法查找下一个运行的任务,那么则不强制要求限制最大可用优先级数目。在 FreeRTOS 中,数值越大优先级越高,0 代表最低优先级。
代码(6):任务栈起始地址,只有在使用静态内存的时候才需要提供,在使用动态内存的时候会根据提供的任务栈大小自动创建。
代码(7):任务控制块指针,在使用静态内存的时候,需要给任务初始化函数 xTaskCreateStatic()传递预先定义好的任务控制块的指针。在使用动态内存的时候,任务创建函数 xTaskCreate()会返回一个指针指向任务控制块,该任务控制块是 xTaskCreate()函数里面动态分配的一块内存。

静态创建任务例程

//任务堆栈大小
#define TASK1_STK_SIZE 128
//任务优先级
#define TASK1_PRIO 1
//任务堆栈
StackType_t Task1TaskStack[TASK1_STK_SIZE];
//任务控制块
StaticTask_t Task1TaskTCB;
//任务句柄
TaskHandle_t Task1_Handler;
//任务函数
void task1_task(void *pvParameters);

int main(void)
{
	//创建任务
	Task1_Handler=xTaskCreateStatic((TaskFunction_t )task1_task,//任务函数
	(const char* )"task1_task",//任务名称
	(uint32_t )TASK1_STK_SIZE , //任务堆栈大小
	(void* )NULL, //传递给任务函数的参数
	(UBaseType_t )TASK1_PRIO ,//任务优先级
	(StackType_t* )Task1TaskStack,//任务堆栈
	(StaticTask_t* )&Task1TaskTCB;//任务控制块
	
	vTaskStartScheduler(); //开启任务调度
}

void task1_task(void *pvParameters);
{
	while(1{
		vTaskDelay(100);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值