FreeRTOS第二节——了解FreeRTOS的任务

1.FreeRTOS任务特点
FreeRTOS的任务使用是比较简单的,任务的数量是没有限制的,可以设置优先级,支持抢占,每个任务都有一个堆栈,用来保存任务的数据,任务多的话,内存的心态就会崩溃,如果抢占要考虑重新进入的问题。

2.为什么任务需要优先级和堆栈
首先什么是优先级,优先级呢就像是VIP,谁的级别高谁就牛,而且越高越牛,所以在FreeRTOS中最LOW的就是0级任务,空闲任务就是0级的。我们可以这样理解,假如一个优先级为2的任务正在一个餐馆点菜(执行),刚点了一个菜,这个时候突然来了一个优先级为3的任务,这个任务也要点菜,如果这家店的服务员只有一个,服务员(系统)就会把优先级为2 的任务点的菜单先放起来(存进它的堆栈),让优先级为3的任务进行点菜,当优先级为3的任务点好了以后,这个时候在从一边(2的堆栈)拿起菜单(读取保存的数据),继续让优先级为2的任务点餐(继续执行)。

堆栈的左右就是用来保存任务现场的,而优先级决定了哪个任务先进行

任务创建的时候需要指定任务堆栈,任务堆栈的单位是被指定的,单位的大小是uint32_t,当然这个也是可以设置的,设置的位置在portmacro.h中有如下的定义

#define portSTACK_TYPE	uint32_t
#define portBASE_TYPE	long

typedef portSTACK_TYPE StackType_t;

所以加入任务堆栈设置的大小是100,那么实际占用的内存大小是100*(32/8)=400B,看一个任务还不到1KB

优先级的范围是0~configMAX_PRIORITIES-1

3.任务状态
任务的状态一工有四种:
运行态:任务正在运行
就绪态:准备好可以运行了
阻塞态:等待中,等待某个东东
挂起态:暂停运行
状态之间的转换都可以通过调用相关的函数进行实现
任务状态

4.任务实现
任务该怎么写呢?我们来瞅一瞅代码,下面的代码是一个定时输出一个数的值的任务
这是一个函数,函数的函数体,也就是任务的任务体

void float_task(void *pvParameters)
{
	static float float_num=0.00;
	while(1)
	{
		float_num+=0.01f;
		printf("float_num=: %.4f\r\n",float_num);
   		 vTaskDelay(1000);				//1000ms = 1s 每一秒钟输出一次float_num的数值
	}
	vTaskDelete(NULL);   //退出之后把任务删除
}

5.创建任务

    xTaskCreate((TaskFunction_t )float_task,     			//任务函数,把刚刚的那个函数传进去
                (const char*    )"float_task",   			//任务名称,一个字符串
                (uint16_t       )FLOAT_STK_SIZE, 			//任务的堆栈大小
                (void*          )NULL,						//任务函数参数
                (UBaseType_t    )FLOAT_TASK_PRIO,			//任务的优先级
                (TaskHandle_t*  )&FLOATTask_Handler);  		//任务的句柄,通过句柄可以找到任务

6.任务控制块

任务控制块,就是描述任务属性的数据结构称为任务控制块 TCB_t
我们来一起看一下源码:

/*
 * Task control block.  A task control block (TCB) is allocated(分配) for each task,
 * 任务控制块,任务控制块是被分配给每个任务并且存储任务状态信息,包括任务的上下文指针,
 * and stores task state information, including a pointer to the task's context
 * (the task's run time environment, including register values)
 */
typedef struct tskTaskControlBlock
{
	//这个是任务堆栈的栈顶
	volatile StackType_t	*pxTopOfStack;	/*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */

	//内存处理单元的条件编译
	#if ( portUSING_MPU_WRAPPERS == 1 )
		xMPU_SETTINGS	xMPUSettings;		/*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
	#endif

	//状态列表
	ListItem_t			xStateListItem;	/*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
	//事件列表
	ListItem_t			xEventListItem;		/*< Used to reference a task from an event list. */
	//任务优先级
	UBaseType_t			uxPriority;			/*< The priority of the task.  0 is the lowest priority. */
	//任务堆栈
	StackType_t			*pxStack;			/*< Points to the start of the stack. */
	char				pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */

	#if ( portSTACK_GROWTH > 0 )
		StackType_t		*pxEndOfStack;		/*< Points to the end of the stack on architectures where the stack grows up from low memory. */
	#endif

	#if ( portCRITICAL_NESTING_IN_TCB == 1 )
		UBaseType_t		uxCriticalNesting;	/*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t		uxTCBNumber;		/*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */
		UBaseType_t		uxTaskNumber;		/*< Stores a number specifically for use by third party trace code. */
	#endif

	#if ( configUSE_MUTEXES == 1 )
		UBaseType_t		uxBasePriority;		/*< The priority last assigned to the task - used by the priority inheritance mechanism. */
		UBaseType_t		uxMutexesHeld;
	#endif

	#if ( configUSE_APPLICATION_TASK_TAG == 1 )
		TaskHookFunction_t pxTaskTag;
	#endif

	#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
		void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
	#endif

	#if( configGENERATE_RUN_TIME_STATS == 1 )
		uint32_t		ulRunTimeCounter;	/*< Stores the amount of time the task has spent in the Running state. */
	#endif

	#if ( configUSE_NEWLIB_REENTRANT == 1 )
		/* Allocate a Newlib reent structure that is specific to this task.
		Note Newlib support has been included by popular demand, but is not
		used by the FreeRTOS maintainers themselves.  FreeRTOS is not
		responsible for resulting newlib operation.  User must be familiar with
		newlib and must provide system-wide implementations of the necessary
		stubs. Be warned that (at the time of writing) the current newlib design
		implements a system-wide malloc() that must be provided with locks. */
		struct	_reent xNewLib_reent;
	#endif

	#if( configUSE_TASK_NOTIFICATIONS == 1 )
		volatile uint32_t ulNotifiedValue;
		volatile uint8_t ucNotifyState;
	#endif

	/* See the comments above the definition of
	tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
	#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
		uint8_t	ucStaticallyAllocated; 		/*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
	#endif

	#if( INCLUDE_xTaskAbortDelay == 1 )
		uint8_t ucDelayAborted;
	#endif

} tskTCB;

/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
below to enable the use of older kernel aware debuggers. */
typedef tskTCB TCB_t;

差不多就到这里了,阅读源码是挺重要的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值