FreeRTOS任务管理、任务状态、任务优先级

任务状态

运行态

任务分为运行态和非运行态两种,在处理器运行过程中,任一时刻只能有一个任务处于运行态,非运行态又包含很多子态。

当任务处于非运行态时,任务处于休眠态(dormant),它的状态被保存,以便下一次调度程序决定它应该进入运行态。当一个任务恢复执行时,它从最后一次离开运行态之前将要执行的指令开始执行。

在这里插入图片描述

FreeRTOS调度器是唯一可以切换任务状态的实体。

非运行态

阻塞态

等待事件的任务处于阻塞态,任务会因等待两种不同的事件进入阻塞态

  1. 时间相关事件-此类事件要么是一个延时的相对时间,要么是一个要到达的绝对时间。例如,任务可能会进入阻塞态等待10ms通过
  2. 同步事件-此类事件源自另外一个任务或中断

FreeRTOS中消息队列、二值信号量、计数型信号量、互斥信号量、递归互斥信号量、时间标志组、任务通知都会产生同步事件

挂起态

调度器不能条用处于挂起状态的任务。进入挂起状态的唯一方法是通过调用vTaskSuspend() API函数,解除挂起状态的方法是通过调用vTaskResume()或xTaskResumeFromISR() API函数。大多数应用程序不使用挂起状态

就绪态

任务既不是运行态,也不是处于阻塞态或挂起态,则被认为是就绪态。这些任务能够运行,因此准备即将运行,但此时并未处在运行状态

在这里插入图片描述
创建 任务 到 就 绪 态 : 任务创建完成后进入就 绪 态,表明任务已准备就绪,只等待调度器进行调度即可运行。

就 绪 态 到 运行 态 :调度器发生任务切换 时,就绪列表中最高优先级的任务优先执行,进入运行态

运行 态 到 就 绪 态 : 创建或还原更高优先级的任务后,将进行任务调度 。 此 时 ,就 绪列表中优先级最高的任务将变为运行状态 。 然 后 , 原 始 正在 运行 的 任务 将 从运行 状态 更 改 为 就 绪 状 态 , 并 位 于 就 绪 列 表 中 。 更 高 优先 级 任务 运行 结束 后 ,继续运行原始任务。

运行 态 到 阻塞 态 : 正在 运行 的 任务 发 生 阻 塞(挂 起 、 延 时 、 读 信号 量 等 待 )时 , 该 任务 会 从 就 绪 列 表 中 删除 , 任 务 状态 由 运行 态 变 成 阻塞 态 , 然 后 发 生 任 务切换 , 运 行 就 绪 列 表 中 当前 最 高 优先 级 任务 。

阻塞 态 到 就 绪 态 : 阻塞 的 任务 被 恢复 后 (任务 恢复 、 延 时 时 间 超 时 、 读信号量 超 时 或 读 到 信号 量 等 ) 此 时 被 恢复 的 任务 会 被 加 入 就 绪 列 表 , 从 而 由 阻塞 态 变成就绪态;如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,将该任务将再次转换任务状态,由就绪态变成运行态。

就绪态、阻塞态、运行态到挂起态:任务可以通过调用vTaskSuspend()API函数可以将处于任何状态的任务挂起,被挂起的任务得不到CPU的使用权,也不会参与调度,除非它从挂起态中解除。

挂起态到就绪态:把一个挂起状态的任务恢复的唯一途径就是调用VTaskResume()或vTaskResumeFromISR()API函数,如果此时被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,将该任务将再次转换任务状态,由就绪态变成运行态。

创建任务

xTaskCreate() API

BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
					  const char * const pcName,
					  uint16_t usStackDepth,
					  void *pvParameters,
					  UBaseType_t uxPriority,
					  TaskHandle_t *pxCreatedTask );
Parameters Name Description
pvTaskCode 该参数是一个指向实现该任务的函数的指针(事实上,是函数名)
pcName 人为自定义的任务名称 (FreeRTOS.h中的宏定义 configMAX_TASK_NAME_LEN 定义了任务名的字符串最大长度,超过此长度,会被截断)
usStackDepth 该参数是任务堆栈空间的深度大小(任务在被创建时,由内核分配专属于自己的堆栈空间),单位是Words (字),而非Bytes(字节),例如32位宽的栈空间,usStackDepth=100,此堆栈空间分配400 字节(100 * 4 =400Bytes),堆栈深度*堆栈宽度的大小不得超过unit_16类型变量的最大值
pvParameters 传递给任务函数的值(void * 类型),若无参数传递,则为NULL
uxPriority 任务优先级,范围:0-----(configMAX_PRIORITIES – 1)
pxCreatedTask 任务句柄,可用于更改任务优先级或删除任务等,如果不使用任务句柄,可以设置为NULL
Returned value 返回pdPASS,表示任务创建成功,返回pdFALL,表示创建失败,可能是因为堆栈空间不够

例程

void vTask1( void *pvParameters )  //任务函数1
{
    
    
	const char *pcTaskName = "Task 1 is running\r\n";
	volatile uint32_t ul; /* volatile to ensure ul is not optimized away. */
	/* As per most tasks, this task is implemented in an infinite loop. */
	for( ;; )
	{
    
    
		/* Print out the name of this task. */
		vPrintString( pcTaskName );
		/* Delay for a period. */
		for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
		{
    
    
		}
	}
}

void vTask2( void *pvParameters )  //任务函数2
{
    
    
	const char *pcTaskName = "Task 2 is running\r\n";
	volatile uint32_t ul; /* volatile to ensure ul is not optimized away. */
	/* As per most tasks, this task is implemented in an infinite loop. */
	for( ;; )
	{
    
    
		/* Print out the name of this task. */
		vPrintString( pcTaskName );
		/* Delay for a period. */
		for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
		{
    
    
		}
	}
}

int main( void )
{
    
    
	xTaskCreate( vTask1, /* Pointer to the function that implements the task. */
				"Task 1",/* Text name for the task. This is to facilitatedebugging only. */
				1000, /* Stack depth - small microcontrollers will use muchless stack than this. */
				NULL, /* This example does not use the task parameter. */
				1, /* This task will run at priority 1. */
				NULL ); /* This example does not use the task handle. */
	/* Create the other task in exactly the same way and at the same priority. */
	xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
	vTaskStartScheduler();  //开启任务调度器

	for( ;; );
}

任务内创建任务

在一个任务中包含另外一个任务,Task1 任务函数中可以创建Task2任务。

void vTask1( void *pvParameters )
{
    
    
	const char *pcTaskName = "Task 1 is running\r\n";
	volatile uint32_t ul; /* volatile to ensure ul is not optimized away. */
	/*在进入死循环前,创建任务2*/		
	xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
	for( ;; )
	{
    
    
		/* Print out the name of this task. */
		vPrintString( pcTaskName );
		/* Delay for a period. */
		for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
		{
    
    
		}
	}
}

任务参数

使用任务函数参数传递要打印的文本

void vTask1( void *pvParameters )
{
    
    
	const char *pcTaskName = "Task 1 is running\r\n";
	volatile uint32_t ul; /* volatile to ensure ul is not optimized away. */
	xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
	for( ;; )
	{
    
    
		/* Print out the name of this task. */
		vPrintString( pcTaskName );
		/* Delay for a period. */
		for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
		{
    
    
		}
	}
}

static const char *pcTextForTask1 = "Task 1 is running\r\n";
static const char *pcTextForTask2 = "Task 2 is running\r\n";
int main( void )
{
    
    
	/* Create one of the two tasks. */
	xTaskCreate( vTaskFunction, /*任务函数名 */
				"Task 1", /* 任务名 */
				1000, /* 任务堆栈空间深度*/
				(void*)pcTextForTask1, /* 使用任务参数传递要打印的文本 */
				1, /* 任务优先级 */
				NULL ); /*此处未用任务句柄 */
	xTaskCreate( vTaskFunction, "Task 2", 1000, (void*)pcTextForTask2, 1, NULL );
	
	vTaskStartScheduler();  //开启任务调度

	for( ;; );
}

任务优先级

xTaskCreate() API函数为任务定义了一个初始优先级,这个优先级在调度器运行后可以使用vTaskPrioritySet() API函数来修改

任务优先级的取值范围为 0 ---- (configMAX_PRIORITIES – 1) ,但不同的任务可以使用共同的任务优先级

configMAX_PRIORITIES在FreeRTOS.h中定义

configMAX_PRIORITIES 的最大值取决于使用的方法:

  1. Generic Method(通用方法)

当使用此种方法,FreeRTOS并不限制configMAX_PRIORITIES可以设置的最大值。但是,它总是明智自动的保持configMAX_PRIORITIES取值不大,因为它的值越高,将消耗更多的RAM,最坏情况执行时间越长

如果在FreeRTOSConfig.h头文件中将 configUSE_PORT_OPTIMISED_TASK_SELECTION 设置为0,那么将使用泛型方法,或者configUSE_PORT_OPTIMISED_TASK_SELECTION未在头文件中定义,或者泛型方法是使用中的FreeRTOS端口提供的唯一方法

  1. Architecture Optimized Method (架构优化方法)

架构优化方法使用了少量的汇编代码,其比Generic Method 方法更快。如果使用架构优化的方法,那么configMAX_PRIORITIES不能大于32,与通用方法一样,建议将configMAX_PRIORITIES保持在必要的最小值,因为它的值越高,就越多RAM将被消耗。

如果在FreeRTOSConfig.h中将configUSE_PORT_OPTIMISED_TASK_SELECTION设置为1,那么将使用架构优化的方法

FreeRTOS调度器将始终确保能够运行的最高优先级任务是进入运行状态的任务。当多个相同优先级的任务能够运行时,调度器依次将每个任务转换到运行状态或转换出运行状态

猜你喜欢

转载自blog.csdn.net/weixin_44333597/article/details/107848257
今日推荐