FreeRTOS任务优先级和系统心跳Tick |
您所在的位置:网站首页 › 查看心跳 › FreeRTOS任务优先级和系统心跳Tick |
1. FreeRTOS任务优先级介绍
当我们使用xTaskCreate() API函数创建一个任务的时候,会为任务赋予一个初始的优先级,当然这个优先级可以在调度器启动后,我们可以使用vTaskPrioritySet() API函数来进行优先级修改的。 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );其中xTask参数是传递进某个任务的句柄,NULL则表示修改自己的优先级。uxNewPriority参数表示新设置的优先级,取值范围0~(configMAX_PRIORITIES – 1)。 使用uxTaskPriorityGet来获得任务的优先级: UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask );xTask参数是某个任务句柄,NULL表示获取自己的优先级。返回值就是该任务的优先级。 优先级的取值范围是:0~(configMAX_PRIORITIES – 1),数值越大优先级越高。其中configMAX_PRIORITIES这个宏的值可以在FreeRTOSConfig.h 中设定。FreeRTOS虽然没有规定这个宏的最大值,但是实际开发中,我们应该尽量选择一个合适的取值,因为这个值越大,那么内核对内存的开销就越大。 FreeRTOS的调度器总是会确保: 在所有可以运行的任务中,选择其中具有最高优先级的任务运行;对于优先级相同的、可以运行的任务,轮流执行。 2. 系统心跳 — tick对于相同优先级的任务,FreeRTOS要轮流执行的话,就需要有系统心跳。系统心跳来源于SysTick系统定时器产生周期性中断,比如我们设置SysTick定时器10ms产生一次中断,那么FreeRTOS的心跳就是10ms。 如下图所示: 那么对于相同优先级的任务,他们是怎么轮流进行切换的呢?如下图可以概括: 使用系统心跳来进行延时: 很明显系统心跳—Tick可以用来衡量时间,自然我们就可以用它来实现延时。FreeRTOS提供了专门的API延时函数给我们使用,函数原型如下: void vTaskDelay( const TickType_t xTicksToDelay );该函数使用时会引起使用的任务进入阻塞态。其中,参数xTicksToDelay就是我们想要延时的时间长度,延时多长除了和该参数大小有关,还与设置的系统心跳频率有关。 用法如下: /* 假设configTICK_RATE_HZ=100, Tick周期时10ms, 那么等待2个Tick,也就是等待20ms */ vTaskDelay(2); /* 还可以使用pdMS_TO_TICKS宏把ms转换为tick */ vTaskDelay(pdMS_TO_TICKS(100)); // 等待100ms使用vTaskDelay函数时,建议以ms为单位,使用pdMS_TO_TICKS把时间转换为Tick。这样的代码就与configTICK_RATE_HZ无关,即使配置项configTICK_RATE_HZ改变了,我们也不用去修改代码。 3. 优先级示例代码示例代码创建2个任务。 任务1代码如下: /* Task1,Task2都不会进入阻塞或者暂停状态,根据优先级决定谁能运行*/ void vTask1( void *pvParameters ) { UBaseType_t uxPriority; /* 得到Task1自己的优先级 */ uxPriority = uxTaskPriorityGet( NULL ); for( ; ; ) { printf( "Task 1 is running\r\n" ); printf("About to raise the Task 2 priority\r\n" ); /* 提升Task2的优先级高于Task1,Task2会即刻执行 */ vTaskPrioritySet( xTask2Handle, ( uxPriority + 1 ) ); } }任务2代码如下: /* Task1,Task2都不会进入阻塞或者暂停状态,根据优先级决定谁能运行*/ void vTask2( void *pvParameters ) { UBaseType_t uxPriority; /* 得到Task2自己的优先级 */ uxPriority = uxTaskPriorityGet( NULL ); for( ; ; ) { printf( "Task 2 is running\r\n" ); printf("About to lower the Task 2 priority\r\n" ); /* 降低了Task2的优先级,使得它的优先级比Task1还小,那么Task1会马上得到运行 */ vTaskPrioritySet( xTask2Handle, ( uxPriority - 2 ) ); } }main函数 #include #include "bsp_usart.h" #include "FreeRTOS.h" #include "task.h" TaskHandle_t xTask2Handle; int main( void ) { USART_Config(); // 串口初始化 /* Task1的优先级更高, Task1先执行 */ xTaskCreate( vTask1, "Task 1", 1000, NULL, 2, NULL ); xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, &xTask2Handle ); /* 启动调度器 */ vTaskStartScheduler(); /* 如果程序运行到了这里就表示出错了, 一般是内存不足 */ return 0; }代码运行过程如下: 首先创建任务1和任务2,因为任务1优先级更高,所以任务1首先运行。为了让任务2有机会运行,在任务1中提升任务2的优先级高于任务1由于任务1提升了任务2的优先级,所以任务2此时在运行,然后任务2降低自己的优先级这时任务1优先级最高,任务1得以运行反复以上循环由于任务1和2都不会进入阻塞状态,所以空闲任务永远也不会得到执行如下图可直观了解整个运行过程: |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |