延时函数

vTaskDelay()

相对延时函数,在文件task.c中定义的,要使用的话宏INCLUDE_vTaskDelay必须设置为1;

void vTaskDelay( const TickType_t xTicksToDelay )
{
BaseType_t xAlreadyYielded = pdFALSE; /* A delay time of zero just forces a reschedule. */
if( xTicksToDelay > ( TickType_t ) 0U )
{
configASSERT( uxSchedulerSuspended == 0 );
vTaskSuspendAll();
{
traceTASK_DELAY();
prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
}
xAlreadyYielded = xTaskResumeAll();
}
else
{
mtCOVERAGE_TEST_MARKER();
} if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
  • 延时参数xTicksToDelay为要延时的时间节拍数,肯定要大于0,否则相当于直接调用函数portYIELD()进行任务切换;
  • 调用vTaskSuspendAll()挂起任务调度器;
  • 调用函数prvAddCurrentTaskToDelayedList()将要延时的任务添加到延时列表中;
  • 调用xTaskResumeAll()恢复任务调度器,并在之后检测xTaskResumeAll()返回参数,如果没进行任务调度的话,那么调用portYIELD_WITHIN_API()进行任务调度;

函数prvAddCurrentTaskToDelayedList()分析

static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
{
TickType_t xTimeToWake;
const TickType_t xConstTickCount = xTickCount; #if( INCLUDE_xTaskAbortDelay == 1 )
{
pxCurrentTCB->ucDelayAborted = pdFALSE;
}
#endif if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
} #if ( INCLUDE_vTaskSuspend == 1 )
{
if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
{
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
xTimeToWake = xConstTickCount + xTicksToWait;
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
if( xTimeToWake < xConstTickCount )
{
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
}
#else /* INCLUDE_vTaskSuspend */
{
xTimeToWake = xConstTickCount + xTicksToWait;
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); if( xTimeToWake < xConstTickCount )
{
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
} ( void ) xCanBlockIndefinitely;
}
#endif /* INCLUDE_vTaskSuspend */
}
  • 读取进入该函数的时间点并保存在xConstTickCount中,后面在计算唤醒时间点的时候要用到,xTickCount是时钟节拍计数器,每个滴答定时器中断xTickCount都会加一
  • 将当前任务从就绪表中移除;
  • 取消当前任务在uxTopReadyPriority中的就绪标记,即将相应的bit清0;
  • 如果延时时间为最大值portMAX_DELAY并且xCanBlockIndefinitely不为pdFALSE(即表示允许阻塞任务),那么直接将当前任务添加到挂起列表中,任务就不用添加到延时列表中了;
  • 计算唤醒的时间点,之后将唤醒时间点值写入到任务列表中状态列表项的相应字段中;
  • 如果计算得到的唤醒时间点小于xConstTickCount说明发生了溢出,FreeRTOS针对此现象专门做了处理,定义了两个延时列表xDelayedTaskList1和xDelayedTaskList2,也定义了两个指针pxDelayedTaskList和pxOverflowDelayedTaskList来访问这两个列表,在初始化列表函数中分别进行了初始化;
  • xNextTaskUnblockTime是个全局变量,保存着距离下一个要取消阻塞的任务最小时间点值,当计算的唤醒时间点xTimeToWake小于xNextTaskUnblockTime,就更新替换;

vTaskDelayUntil()

绝对延时函数,该函数会阻塞任务,阻塞时间是一个绝对时间,如果是一些需要按照一定的频率运行的任务可以使用该函数;

函数定义如下:

void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
  • pxPreviousWakeTime,上一次任务延时结束被唤醒的时间点,任务中第一次调用该函数时需要将pxPreviousWakeTime初始化进任务的while()循环体的时间点值,之后的运行中该函数会自动更新pxPreviousWakeTime的值;
  • xTimeIncrement,任务需要延时的时间节拍数;

使用模板如下:

void test_task(void *pvParameters)
{
TickType_t PreviousWakeTime; //延时50ms,将延时时间转换成节拍数
const TickType_t TimeIncrement = pdMS_TO_TICKS(50);
PreviousWakeTime = xTaskGetTickCount(); //获取当前的系统节拍值
for( ; ; )
{
/* 任务主体 */ /* 调用延时函数 */
vTaskDelayUntil(&PreviousWakeTime, TimeIncrement);
}
}

注意:使用函数vTaskDelayUntil()延时的任务也不一定就能周期性的运行,只能保证按照一定的周期取消阻塞,进入就绪态,如果有更高优先级或者中断的话,还是要等待其他更高优先级任务或者中断服务函数运行完成后才能运行;

FreeRTOS时间管理的更多相关文章

  1. uC/OS-III 时钟节拍,时间管理,时间片调度

    uC/OS-III 时钟节拍,时间管理,时间片调度   时钟节拍 时钟节拍可谓是 uC/OS 操作系统的心脏,它若不跳动,整个系统都将会瘫痪. 时钟节拍就是操作系统的时基,操作系统要实现时间上的管理, ...

  2. FreeRTOS-04-内核控制函数+时间管理函数

    说明 本文仅作为学习FreeRTOS的记录文档,作为初学者肯定很多理解不对甚至错误的地方,望网友指正. FreeRTOS是一个RTOS(实时操作系统)系统,支持抢占式.合作式和时间片调度.适用于微处理 ...

  3. PMP备考_第六章_项目时间管理

    项目时间管理 前言 项目时间管理是项目管理中最难的一个环节,与个人时间管理类似,团体的效率如果管理不当,是低于个人效率的,为了管理好时间,从预估,执行到反馈均需要严格的分析和处理.如果制定的计划是无法 ...

  4. Google内部邮件:如何进行高效的时间管理能量波动图

    Google内部邮件:如何进行高效的时间管理能量波动图 发布时间: 2015-12-16 22:16:50| 阅读数:462 views 最近,我给团队内部写了一封简单的邮件.主要内容是征询他们,如何 ...

  5. linux 时间管理——概念、注意点(一)【转】

    转自:http://www.cnblogs.com/openix/p/3324243.html 参考:1.http://bbs.eyeler.com/thread-69-1-1.html        ...

  6. μC/OS-Ⅲ系统的时间管理函数和定时器

    一.时间管理函数 μC/OS-Ⅲ系统提供一些列时间管理服务函数: 1.OSTimeDly():任务延时n个时钟节拍. 2.OSTimeDlyHMSM():任务延时指定的时间,采用“时:分:秒:毫秒”方 ...

  7. 时间管理的若干Tips

    时间管理的若干Tips 记下来 再好的记性也不如一支笔与一个本子. 买一支好点的笔于一个好点的本子,让自己有书写的欲望,将todo事项记下来. 小目标 太大太远的目标会使人气馁.通过将大目标分解再分解 ...

  8. 4D时间管理

    时间管理的4D原则   时间矩阵:每个人,每天要做的事情大致分为四类:一类:必须做的,不做会产生不良后果的二类:需要做的,为将来或者今后阶段做准备工作的三类:可以不做,但又不得不做的,例如通过简约形式 ...

  9. 【uTenux实验】时间管理(系统时间/周期性处理/警报处理)

    1.系统时间管理 系统时间管理函数用来对系统时间进行操作,是OS的一个基础性的东西.个人认为,设置系统时间和获取系统时间对OS来说基本是可有可无的. uTenux提供了三个系统时间相关API.分别用于 ...

随机推荐

  1. Matlab批量获取子文件夹与文件名

    批量得到父文件夹下所有子文件夹的路径的MATLAB函数. function [SubFolders] = GetFolders(ParentFolder) %GetFolders % 函数功能为获取父 ...

  2. Memcached内存调优及建议

    一.Memcached调优 目标: 提高内存命中率 减少内存浪费 增加内存重复利用率 问题: 存不满Chunk 内存数据大量堆积 slab不能被page整除 page不能被Chunk整除 方向: 调整 ...

  3. golang 中 map 转 struct

    golang 中 map 转 struct package main import ( "fmt" "github.com/goinggo/mapstructure&qu ...

  4. windows安装redis并为php5.4添加redis扩展

    第一步 安装包下载 首先下载php5.4对应版本的php_igbinary.dll,php_redis.dll扩展.(php7以后可不需要php_igbinary.dl这个文件了) 链接:https: ...

  5. python Django基础操作

    Django常用命令 创建Django项目 Django-admin startprotect  mysite 创建项目以后,以下生成的文件 最外层的file:mysite/ 根目录只是你的项目的容器 ...

  6. Foxmail7.2的账号密码的备份与恢复

    1:备份: 1.0 找到Foxmail7.2的安装的位置,例如我的就是 D:\Program Files\Foxmail 7.2; 然后在路径下找到Storage文件夹然后备份里边的内容; 邮箱账号备 ...

  7. tomcat端口号被占用问题

    1  netstat -ano| findstr 8761 2 taskkill /f/t/im 5156

  8. awesome-javascript

    一系列令人敬畏的浏览器端JavaScript库,资源和闪亮的东西. 令人敬畏的JavaScript 包管理员 装载机 捆扎机 测试框架 QA工具 MVC框架和库 基于节点的CMS框架 模板引擎 文章/ ...

  9. [前端]多线程在前端的应用——Javascript的线程

    JavaScript 是单线程.异步.非阻塞.解释型脚本语言.JavaScript 的设计就是为了处理浏览器网页的交互(DOM操作的处理.UI动画等),决定了它是一门单线程语言.如果有多个线程,它们同 ...

  10. Spring 后台方法 重定向 与 转发

    一.重定向:重定向是客户端行为,在使用时,务必使用全路径,否则可能因为外部环境导致错误 1.URL改变为重定向的URL地址 2.前台页面不能使用Ajax请求提交, 应该使用form表单提交 方法一.参 ...