FreeRTOS 系统时钟节拍和时间管理
以下转载自安富莱电子: http://forum.armfly.com/forum.php
FreeRTOS 的时钟节拍
任何操作系统都需要提供一个时钟节拍,以供系统处理诸如延时、 超时等与时间相关的事件。
时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳。 中断之间的时间间隔取决于不同的应
用,一般是 1ms – 100ms。时钟的节拍中断使得内核可以将任务延迟若干个时钟节拍,以及当任务等待
事件发生时,提供等待超时等依据。时钟节拍率越快,系统的额外开销就越大。
对于 Cortex-M3 内核的 STM32F103 和 Cortex-M4 内核的 STM32F407 以及 F429,教程配套的例
子都是用滴答定时器来实现系统时钟节拍的。
滴答定时器 Systick
SysTick 定时器被捆绑在 NVIC 中,用于产生 SysTick 异常(异常号: 15), 滴答定时器是一个 24 位
的递减计数器,支持中断。 使用比较简单, 专门用于给操作系统提供时钟节拍。
FreeRTOS 的系统时钟节拍可以在配置文件 FreeRTOSConfig.h 里面设置:
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
如上所示的宏定义配置表示系统时钟节拍是 1KHz,即 1ms。
时间延迟
FreeRTOS 中的时间延迟函数主要有以下两个作用:
为周期性执行的任务提供延迟。
对于抢占式调度器,让高优先级任务可以通过时间延迟函数释放 CPU 使用权,从而让低优先级任务可以得到执行。
下面我们通过如下的框图来说明一下延迟函数对任务运行状态的影响,让大家有一个形象的认识。
运行条件:
仅对任务 Task1 的运行状态做说明。
调度器支持时间片调度和抢占式调度。
运行过程描述如下:
起初任务 Task1 处于运行态,调用 vTaskDelay 函数后进入到阻塞状态,也就是 blocked 状态。
vTaskDelay 函数设置的延迟时间到,由于任务 Task1 不是当前就绪的最高优先级任务,所以不能进
入到运行状态,只能进入到就绪状态,也就是 ready 状态。
一段时间后, 调度器发现任务 Task1 是当前就绪的最高优先级任务,从而任务从就绪态切换到运行态。
由于时间片调度,任务 Task1 由运行态切换到就绪态。
FreeRTOS 的时间相关函数
FreeRTOS 时间相关的函数主要有以下 4 个:
vTaskDelay ()
vTaskDelayUntil ()
xTaskGetTickCount()
xTaskGetTickCountFromISR()
函数 xTaskGetTickCount
函数原型:
volatile TickType_t xTaskGetTickCount( void );
函数描述:
函数 xTaskGetTickCount 用于获取系统当前运行的时钟节拍数。
使用这个函数要注意以下问题:
1. 此函数用于在任务代码里面调用,如果在中断服务程序里面调用的话,需要使用函数
xTaskGetTickCountFromISR,这两个函数切不可混用。
eg:
函数 xTaskGetTickCountFromISR
函数原型:
volatile TickType_t xTaskGetTickCountFromISR( void );
函数描述:
函数 xTaskGetTickCountFromISR 用于获取系统当前运行的时钟节拍数。
使用这个函数要注意以下问题:
1. 此函数用于在中断服务程序里面调用, 如果在任务里面调用的话, 需要使用函数 xTaskGetTickCount,
这两个函数切不可混用。
eg:
void TIM6_IRQHandler( void )
{
TickType_t xTickCount;
xTickCount = xTaskGetTickCountFromISR();
}
函数 vTaskDelay
函数原型:
void vTaskDelay(const TickType_t xTicksToDelay ); /* 延迟时间长度 */
函数描述:
函数 vTaskDelay 用于任务的延迟。
参数 xTicksToDelay 用于设置延迟的时钟节拍个数,范围 1- 0xFFFFFFFF。 延迟时间的最大值在
portmacro.h 文件里面有定义:
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t )0xffffffffUL
即延迟时间的范围是:1- 0xFFFFFFFF
函数 vTaskDelayUntil
函数原型:
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, /* 存储任务上次处于非阻塞状态时刻的变量地址 */
const TickType_t xTimeIncrement ); /* 周期性延迟时间 */
函数描述:
函数 vTaskDelayUntil 用于周期性延迟。
第 1 个参数,存储任务上次处于非阻塞状态时刻的变量地址。
第 2 个参数,周期性延迟时间。
使用这个函数要注意以下问题:
1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_vTaskDelayUntil 1
函数 vTaskDelay 和 vTaskDelayUntil 的区别
函数 vTaskDelayUntil 实现的是周期性延迟,而函数 vTaskDelay 实现的是相对性延迟,反映到实际
应用上有什么区别呢,下面就给大家举一个简单的例子。
运行条件:
有一个 bsp_KeyScan 函数,这个函数处理时间大概耗时 2ms。
有两个任务,一个任务 Task1 是用的 vTaskDelay 延迟,延迟 10ms,另一个任务 Task2 是用的
vTaskDelayUntil 延迟,延迟 10ms。
不考虑任务被抢占而造成的影响
eg1:绝对延时vTaskDelayUntil函数实现
static void vTaskLED(void *pvParameters)
{
TickType_t xLastWakeTime;
const TickType_t xFrequency = 200; /* 获取当前的系统时间 */
xLastWakeTime = xTaskGetTickCount(); while()
{
bsp_LedToggle(); /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
vTaskDelayUntil(&xLastWakeTime, xFrequency);
}
}
eg2:绝对延时vTaskDelay函数实现
static void vTaskMsgPro(void *pvParameters)
{
TickType_t xDelay, xNextTime;
const TickType_t xFrequency = 200; /* 获取xFrequency个时钟节拍后的时间 */
xNextTime = xTaskGetTickCount() + xFrequency; while()
{
bsp_LedToggle(); /* 用vTaskDelay实现vTaskDelayUntil() */
xDelay = xNextTime - xTaskGetTickCount();
xNextTime += xFrequency; if(xDelay <= xFrequency)
{
vTaskDelay(xDelay);
}
}
}
要理解eg2需要破费心思。
想要用相对延时的方式实现绝对延时,我们首先获取当前系统节拍,并且加上200个节拍,在我的测试例子中,一个节拍是1ms。这说明我是想要实现一个200ms的周期性任务。在执行完led翻转之后,我获取当前节拍数,用之前保存的想要延时数xNextTime减去当前节拍,得到的这个节拍就应该是我们用相对延时vTaskDelay去延时的时间。但是为什么程序实现中还要加上xNextTime += xFrequency;和一个if判断if(xDelay <= xFrequency)呢?(当xNextTime 减去xTaskGetTickCount()减得够的时候,if条件是肯定满足的,而此时xNextTime += xFrequency是为了给下一个周期的nexttime赋值一个固定的时钟节拍,这里是200).但是,有个问题需要注意,要是我的不是一个简单的led任务,而是一段运行时间超过200ms的程序呢?这样会导致 xNextTime - xTaskGetTickCount();得到一个小于0的数,但是定义的无符号类型,会发生有符号到无符号的转换,这个时候,程序就会出错(此时的delay函数不再准确),和其他任何定时器任务一样,周期性任务设计的时候,应该确保在周期内完成任务工作。
FreeRTOS 系统时钟节拍和时间管理的更多相关文章
- RTX——第12章 系统时钟节拍和时间管理
以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 RTX 操作系统的时钟节拍和时间管理函数,其中时间管理函数是 RTX 的基本函数,初学 ...
- uC/OS-III 时钟节拍,时间管理,时间片调度
uC/OS-III 时钟节拍,时间管理,时间片调度 时钟节拍 时钟节拍可谓是 uC/OS 操作系统的心脏,它若不跳动,整个系统都将会瘫痪. 时钟节拍就是操作系统的时基,操作系统要实现时间上的管理, ...
- FreeRTOS学习笔记4:时间管理
绝对时间:abs Time相对时间:百分比% time IDLE是空闲任务. RUN_Time_State:port...()初始化一个外设提供时基单元 //具体初始化要自己操作这个定时器的分辨率高于 ...
- FreeRTOS-04-内核控制函数+时间管理函数
说明 本文仅作为学习FreeRTOS的记录文档,作为初学者肯定很多理解不对甚至错误的地方,望网友指正. FreeRTOS是一个RTOS(实时操作系统)系统,支持抢占式.合作式和时间片调度.适用于微处理 ...
- liteos时间管理(九)
1. 时间管理 1.1 概述 1.1.1 概念 时间管理以系统时钟为基础.时间管理提供给应用程序所有和时间有关的服务. 系统时钟是由定时/计数器产生的输出脉冲触发中断而产生的,一般定义为整数或长整数. ...
- uC/OS-III 时间管理(二)
时间管理就是一种建立在时钟节拍上,对操作系统任务的运行实现时间上管理的一种系统内核机制. 常用以下五个函数: OSTimeDly() OSTimeDlyHMSM() OSTimeDlyResume() ...
- RT-thread内核之系统时钟
一.系统时钟 rt-thread的系统时钟模块采用全局变量rt_tick作为系统时钟节拍,该变量在系统时钟中断函数中不断加1.而系统时钟中断源和中断间隔一般由MCU硬件定时器(如stm32的嘀嗒定时器 ...
- FreeRTOS时间管理
延时函数 vTaskDelay() 相对延时函数,在文件task.c中定义的,要使用的话宏INCLUDE_vTaskDelay必须设置为1: void vTaskDelay( const TickTy ...
- 【uTenux实验】时间管理(系统时间/周期性处理/警报处理)
1.系统时间管理 系统时间管理函数用来对系统时间进行操作,是OS的一个基础性的东西.个人认为,设置系统时间和获取系统时间对OS来说基本是可有可无的. uTenux提供了三个系统时间相关API.分别用于 ...
随机推荐
- BeagleBone折腾记(一):连接你的狗板
BeagleBone折腾记一连接你的狗板 准备 了解BeagleBone BeagleBone社区 所需软硬件 USB连接 TTL连接 结语 准备 了解BeagleBone BeagleBone可能一 ...
- [转]nginx折腾记(HTTP性能能测试,与Apache对比)
话说nginx在大压力的环境中比apache的表现要好,于是下载了一个来折腾一下. 下载并编译安装,我的编译过程有点特别: 1.去除调试信息,修改$nginx_setup_path/auto/cc ...
- vue-router路由元信息详解
一.官方文档 路由元信息:定义路由的时候可以配置 meta 字段 const router = new VueRouter({ routes: [ { path: '/foo', component: ...
- [JS Compose] 3. Use chain for composable error handling with nested Eithers (flatMap)
We refactor a function that uses try/catch to a single composed expression using Either. We then int ...
- 国内站点经常使用的一些 CDN 静态资源公共库加速服务
web开发人员们的福利来了..旨在为大家提供更快很多其它更好的静态资源库的CDN载入库方案! CDN公共库是指将经常使用的JS库存放在CDN节点,以方便广大开发人员直接调用. 与将JS库存放在serv ...
- 最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4568 题目大意: 给一个矩阵 n*m (n m<=200),方格里如果是0~9表示通过它时要花 ...
- python3 http.client 网络请求
python3 http.client 网络请求 一:get 请求 ''' Created on 2014年4月21日 @author: dev.keke@gmail.com ''' import h ...
- Visual studio中后期生成事件命令使用
在做项目是总要把发布后的一些dll拷贝的根网站的bin目录下,为了避免每次都需要手动拷贝可以在 项目的生成事件中写入bat命令,下面的命令只在项目使用的发布配置时执行拷贝, (在生成->配置管理 ...
- QtGui.QSlider
A QtGui.QSlider is a widget that has a simple handle. This handle can be pulled back and forth. This ...
- 对象 get和set方法
1.用途 用户定义的对象定义 getter 和 setter 以支持新增的属性. 示例:obj创建一个伪属性latest,它会返回log数组的最后一个元素. var obj = { log: ['ex ...