FreeRTOS笔记(二)

FreeRTOS笔记(二)—静态任务

一、任务定义

​ 在多任务系统中,我们根据功能的不同,把整个系统分割 成一个个独立的且无法返回的函数,这个函数我们称为任务。

二、任务创建

2.1 定义任务栈

​ 写一个 RTOS,对于全局变量与局部变量这些种种环境参数,我们必须弄清楚他们是如何存储的。

​ 在裸机系统 中,他们统统放在一个叫的地方,栈是单片机 RAM 里面一段连续的内存空间,栈的大小一般在启动文件或者链接脚本里面指定,最后由C库函数_main进行初始化

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

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

示例 1 定义任务栈

/* 
 #define portSTACK_TYPE uint32_t
 typedef portSTACK_TYPE StackType_t;
*/
#define TASK1_STACK_SIZE 128 
StackType_t Task1Stack[TASK1_STACK_SIZE];
#define TASK2_STACK_SIZE 128
StackType_t Task2Stack[TASK2_STACK_SIZE];
2.2 定义任务函数

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

示例 2 任务函数定义

/* 软件延时 */
void delay (uint32_t count)
{
   
	for(; count!=0; count--);
}
/* 任务1 */
void Task1_Entry( void *p_arg )
{
   
	for( ;; )
	{
   
		flag1 = 1;
		delay( 100 );		
		flag1 = 0;
		delay( 100 );

	}
}

/* 任务2 */
void Task2_Entry( void *p_arg )
{
   
	for( ;; )
	{
   
		flag2 = 1;
		delay( 100 );		
		flag2 = 0;
		delay( 100 );
		
	}
}
2.3 定义任务控制块
  • 在裸机系统中,程序的主体是 CPU 按照顺序执行的。而在多任务系统中,任务的执行是由系统调度的。

  • 系统为了顺利的调度任务,为每个任务都额外定义了一个任务控制块, 这个任务控制块就相当于任务的身份证,里面存有任务的所有信息,比如任务的栈指针任务名称任务的形参等。

  • 有了这个任务控制块之后,以后系统对任务的全部操作都可以通过这个任务控制块来实现。

示例 3 任务控制块数据类型声明

typedef struct tskTaskControlBlock
{
   
	volatile StackType_t    *pxTopOfStack;    /* 栈顶 */

	ListItem_t			    xStateListItem;   /* 任务节点 一个内置在 TCB 控制块中的链表节点,通过				这个节点,可以将任务控制块挂接到各种链表中。这个节点就类似晾衣架的钩子,TCB 就是衣服。*/
    
    StackType_t             *pxStack;         /* 任务栈起始地址 */
	                                          
	char                    pcTaskName[ configMAX_TASK_NAME_LEN ]; /* 任务名称,字符串形式 */
} tskTCB;
typedef tskTCB TCB_t;
2.4 实现任务创建函数

示例 4 任务创建函数xTaskCreateStatic()函数

/*
	//任务句柄void指针
typedef void * TaskHandle_t;

	//TaskFunction_t类型的pxTaskCode为函数指针,指向任务函数的入口。任务永远不会返回(位于死循环内)。
typedef void (*TaskFunction_t)( void * );//参数为void指针类型并返回void类型。

	//
#define portSTACK_TYPE	uint32_t
typedef portSTACK_TYPE StackType_t;
*/

TaskHandle_t xTaskCreateStatic(	TaskFunction_t pxTaskCode,           /* 任务入口 */
					            const char * const pcName,           /* 任务名称,字符串形式 ,字符串的最大长度(包括字符串结束字符)由宏configMAX_TASK_NAME_LEN指定,该宏位于FreeRTOSConfig.h文件中。*/
					            const uint32_t ulStackDepth,         /* 任务栈大小,单位为字,不是字节数,在16位宽度的堆栈下,usStackDepth定义为100,则实际使用200字节堆栈存储空间。1字=2字节=16位 */
					            void * const pvParameters,           /* 任务形参,当任务创建时,作为一个参数传递给任务。*/
					            StackType_t * const puxStackBuffer,  /* 任务栈起始地址 */
					            TCB_t * const pxTaskBuffer )         /* 任务控制块指针 */
{
   
	TCB_t *pxNewTCB;
	TaskHandle_t xReturn;//定义一个任务句柄 xReturn,任务句柄用于指向任务的 TCB。
	
    /*任务控制块指针与任务栈起始地址均非空时,形参赋值*/
	if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
	{
   		
		pxNewTCB = ( TCB_t * ) pxTaskBuffer; 
		pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;

		/* 创建新的任务 */
		prvInitialiseNewTask( pxTaskCode,        /* 任务入口 */
                              pcName,            /* 任务名称,字符串形式 */
                              ulStackDepth,      /* 任务栈大小,单位为字 */ 
                              pvParameters,      /* 任务形参 */
                              &xReturn,          /* 任务句柄 */ 
                              pxNewTCB);         /* 任务栈起始地址 */      

	}
	else
	{
   
		xReturn = NULL;
	}

	/* 返回任务句柄,如果任务创建成功,此时xReturn应该指向任务控制块 */
    return xReturn;
}

示例 5 创建新任务prvInitialiseNewTask()函数

/*
typedef unsigned long UBaseType_t;
*/
static void prvInitialiseNewTask( 	TaskFunction_t pxTaskCode,              /* 任务入口 */
									const char * const pcName,              /* 任务名称,字符串形式 */
									const uint32_t ulStackDepth,            /* 任务栈大小,单位为字 */
									void * const pvParameters,              /* 任务形参 */
									TaskHandle_t * const pxCreatedTask,     /* 任务句柄 */
									TCB_t *pxNewTCB )                       /* 任务控制块指针 */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值