FreeRTOS — 系统时钟节拍和时间管理
以下内容转载自安富莱电子:http://forum.armfly.com/forum.php
1 、FreeRTOS 的 时钟 节拍
任何操作系统都需要提供一个时钟节拍,以供系统处理诸如延时、超时等与时间相关的事件。
时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳。中断之间的时间间隔取决于不同的应用,一般是 1ms – 100ms。时钟的节拍中断使得内核可以将任务延迟若干个时钟节拍,以及当任务等待事件发生时,提供等待超时等依据。时钟节拍率越快,系统的额外开销就越大。
FreeRTOS 的系统时钟节拍可以在配置文件 FreeRTOSConfig.h 里面设置:
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
如上所示的宏定义配置表示系统时钟节拍是 1KHz,即 1ms。
2 、FreeRTOS 的 时 间 管 理
时间管理功能是 FreeRTOS 操作系统里面最基本的功能,同时也是必须要掌握好的。
2.1 时间延迟
FreeRTOS 中的时间延迟函数主要有以下两个作用:
上面就是一个简单的任务运行状态的切换过程。
2.2 FreeRTOS 的时间相关函数
FreeRTOS 时间相关的函数主要有以下 4 个:
vTaskDelay ()
vTaskDelayUntil ()
xTaskGetTickCount()
xTaskGetTickCountFromISR()
下面我们对这 4 个函数依次进行说明:
2.3 函数 vTaskDelay
使用举例:
2.4 函数 vTaskDelayUntil
函数原型:
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, /* 存储任务上次处于非阻塞状态时刻的变量地址 */
const TickType_t xTimeIncrement ); /* 周期性延迟时间 */
函数描述:
函数 vTaskDelayUntil 用于周期性延迟。
第 1 个参数,存储任务上次处于非阻塞状态时刻的变量地址。
第 2 个参数,周期性延迟时间。
使用这个函数要注意以下问题:
1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_vTaskDelayUntil 1
2. 用户要注意此函数跟 vTaskDelay 的区别,2.7 小节详细讲解。
使用举例:
2.5 函 数 xTaskGetTickCount
函数原型:
volatile TickType_t xTaskGetTickCount( void );
函数描述:
函数 xTaskGetTickCount 用于获取系统当前运行的时钟节拍数。
使用这个函数要注意以下问题:
1. 此函数用于在任务代码里面调用,如果在中断服务程序里面调用的话,需要使用函数xTaskGetTickCountFromISR,这两个函数切不可混用。
使用举例:
2.6 函 数 xTaskGetTickCountFromISR
函数原型:
volatile TickType_t xTaskGetTickCountFromISR( void );
函数描述:
函数 xTaskGetTickCountFromISR 用于获取系统当前运行的时钟节拍数。
使用这个函数要注意以下问题:
1. 此函数用于在中断服务程序里面调用,如果在任务里面调用的话,需要使用函数 xTaskGetTickCount,
这两个函数切不可混用。
使用举例:
/* ********************************************************************************************************* * 函 数 名: TIM6_IRQHandler * 功能说明: TIM6 中断服务程序。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void TIM6_IRQHandler( void ) { TickType_t xTickCount; xTickCount = xTaskGetTickCountFromISR(); }
2.7 函数 vTaskDelay 和 vTaskDelayUntil 的区别
函数 vTaskDelayUntil 实现的是周期性延迟,而函数 vTaskDelay 实现的是相对性延迟,反映到实际
应用上有什么区别呢,下面就给大家举一个简单的例子。
运行条件:
有一个 bsp_KeyScan 函数,这个函数处理时间大概耗时 2ms。
有两个任务,一个任务 Task1 是用的 vTaskDelay 延迟,延迟 10ms,另一个任务 Task2 是用的
vTaskDelayUntil 延迟,延迟 10ms。
不考虑任务被抢占而造成的影响。
实际运行过程效果:
Task1:
bsp_KeyScan+ vTaskDelay (10) ---> bsp_KeyScan + vTaskDelay (10)
|----2ms + 10ms 为一个周期------| |----2ms + 10ms 为一个周期----|
这个就是相对性的含义
Task2:
bsp_KeyScan + vTaskDelayUntil ---------> bsp_KeyScan + vTaskDelayUntil
|----10ms 为一个周期(2ms 包含在 10ms 内)---| |----10ms 为一个周期------|
这就是周期性的含义。
下面我们通过函数 vTaskDelay 来实现 vTaskDelayUntil,会有一个更加全面的认识:
/* ********************************************************************************************************* * 函 数 名: vTaskMsgPro * 功能说明: 消息处理,这里是用作 LED 闪烁 * 形 参: pvParameters 是在创建该任务时传递的形参 * 返 回 值: 无 * 优 先 级: 3 ********************************************************************************************************* */ static void vTaskMsgPro(void *pvParameters) { TickType_t xDelay, xNextTime; const TickType_t xFrequency = 200; /* 获取 xFrequency 个时钟节拍后的时间 */ xNextTime = xTaskGetTickCount() + xFrequency; while(1) { bsp_LedToggle(3); /* 用 vTaskDelay 实现 vTaskDelayUntil() */ xDelay = xNextTime - xTaskGetTickCount(); xNextTime += xFrequency; if(xDelay <= xFrequency) { vTaskDelay(xDelay); } } }
3、实验 例程
实验目的:
1. 学习 FreeRTOS 的周期性延迟和相对性延迟函数。
2. 注意相对性延迟函数 vTaskDelay 和周期性延迟函数 vTaskDelayUntil 的区别。
实验内容:
1. K1 按键按下,串口打印任务执行情况(波特率 115200,数据位 8,奇偶校验位无,停止位 1)。
2. K2 键按下,串口打印系统时钟节拍数。
static void vTaskTaskUserIF(void *pvParameters) { uint8_t ucKeyCode; uint8_t pcWriteBuffer[500]; while(1) { ucKeyCode = bsp_GetKey(); if (ucKeyCode != KEY_NONE) { switch (ucKeyCode) { /* K1键按下 打印任务执行情况 */ case KEY_DOWN_K1: printf("=================================================\r\n"); printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n"); vTaskList((char *)&pcWriteBuffer); printf("%s\r\n", pcWriteBuffer); printf("\r\n任务名 运行计数 使用率\r\n"); vTaskGetRunTimeStats((char *)&pcWriteBuffer); printf("%s\r\n", pcWriteBuffer); break; /* K1键按下 打印系统时钟节拍数 */ case KEY_DOWN_K2: printf("当前的系统时钟节拍数 = %d\r\n", xTaskGetTickCount()); break; /* 其他的键值不处理 */ default: break; } } vTaskDelay(20); } }
欢迎加入作者的小圈子
扫描下方左边二维码加入QQ交流群,扫描下方右边二维码关注个人微信公众号并,获取更多隐藏干货,QQ交流群:859800032 微信公众号:Crystal软件学堂
作者:Liu_Jing bilibili视频教程地址:https://space.bilibili.com/5782182 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在转载文章页面给出原文连接。 如果你觉得文章对你有所帮助,烦请点个推荐,你的支持是我更文的动力。 文中若有错误,请您务必指出,感谢给予我建议并让我提高的你。 |