0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

剖析毫秒级延时防溢出的原理

Linux阅码场 来源:RTThread物联网操作系统 作者:RTThread物联网操作 2021-08-02 17:38 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

前文指出了基于系统滴答计数实现的毫秒级延时的问题。

uint32_t comm_get_ms(void)

{

return sys_tick_get();

}

void comm_delay(uint32_t ms)

{

uint32_t timeout = comm_get_ms() + ms;

while(comm_get_ms() 《 timeout);

}

comm_get_ms返回当前系统时间(系统滴答计数),即系统从启动到现在经过了多少毫秒。comm_delay先获取当前时间,加上延时时间以计算出到期时间timeout,之后循环等待当前时间超过timeout以完成延时。

系统时间使用uint32_t变量来记录,经过49.71天后将达到最大值UINT32_MAX(0xffffffff),溢出后回到0重新累加。不仅是当前时间会溢出,在接近49.71天时,计算的timeout将会更先一步溢出,从而使延时判断失效。

前文在结尾给出了解决方案:

void comm_delay(uint32_t ms)

{

uint32_t timeout = comm_get_ms() + ms;

while(comm_get_ms() - timeout 》 UINT32_MAX / 2);

}

其实改动很小,仅仅修改了判断超时的条件。为什么要用两个时间差去与UINT32_MAX / 2比较?判断条件为什么是大于?

了解其中的原理是有必要的。因为延时的条件如上,而如果想实现定时的话,条件就会倒过来。知其所以然,方能灵活运用。

定时任务:

uint32_t timeout = 0;

while (1)

{

if (comm_get_ms() - timeout 《 UINT32_MAX / 2)

{

printf(“hello

”);

timeout = comm_get_ms() + 1000;

}

}

主要矛盾

无论是延时还是定时,我们都是在进行时间的比较。先根据延时或定时时长计算出到期时间timeout,之后不停的判断当时时间有没有超过这个timeout。

所有的时间变量都是uint32_t,由于它的最大值非常大,为了方便讲解,我们假设所有的变量都是uint8_t,即8位无符号整型,取值范围为0-255。同样为方便叙述,以cur_time表示当前时间,以timeout表示目标到期时间。

现在的任务也非常清楚了,在各种场景下比较cur_time是否超过了timeout。比如:

起始cur_time为10,延时目标为5,则timeout为10 + 5 = 15。判断依据非常简单,cur_time 《 15时视为未超过timeout,或者说cur_time 《 timeout视为未超过timeout。

起始cur_time为250,延时目标为10,则timeout为250 + 10 = 260 = 4。此时cur_time 《 timeout不再适用。

张三和李四谁跑的快

既然时间溢出问题让我们头疼,那我们先来看一个简单的问题,一个任何人都可以不假思索得出答案的问题:判断跑道上的张三和李四谁跑的快,或者说谁跑在前面。

如下图,张三(A)和李四(B)在跑道上跑步,沿逆时针方向跑。蓝色是起跑线,不过他们并不只跑一圈,假设跑三圈。并且我们知道,张三和李四的水平相差不大,短短的三圈不足以让他们拉快过长的距离,更不可能出现套圈。

假设这个跑道长256米,从起点开始沿逆时针方向(即跑步的方向)标注坐标。那么A和B在坐标轴的位置大致如下:

77309ec8-e032-11eb-9e57-12bb97331649.png

假设A为10,B为240,A 《 B,但是从跑道的图中大家不假思索就得出A跑在前面。这是为什么呢?

大家在判断谁在前面时,其实根本没去管那根蓝色的线(起点或终点)。因为跑道首尾相连,而且张三和李四要跑好几圈,必将多次经过起终点,所以起终点没有任何判断价值。

人脑是怎么判断的

笔者反复自我剖析,觉得可能是这样判断的:

人脑会做两种假设,张三(A)快,或者李四(B)快。最终选择一个最合理的假设。

假设张三(A)快,那么A沿顺时针跑回B(逆时针是前进方向,往回跑就是顺时针)的距离即为A超前B的距离,如下图的红色箭头,相对于一圈的长度而言是一个较小的距离。假设李四(B)快,则B沿顺时针方向需要跑大半圈才能遇到张三(A)。如果李四确实比张三快的话,那么快了不只一点点,而是超前大半圈。先前说过,张三和李四的水平相差不大,短短的三圈不足以让他们拉快过长的距离。所以我们更愿意相信第一种假设成立,即张三(A)比李四(B)跑的快。

人脑做上述判断的时候,并没有给跑道建立坐标系,也不是判断张三和李四的坐标值哪个大,而是判断张三和李四的距离。这个距离是有方向性的。

假设张三(A)快,则目测A跑回B的距离L(A-B)。这个距离比较小,所以判断成立,A确实在B前面。

假设李四(B)快,则目测B跑回A的距离L(B-A)。这个距离比较大,所以判断不成立,B其实在A的后面。

其实根本不需要验证两种假设,只需要验证一个就行了,因为它们是对立的。

回归代码

人脑通过视觉来估测张三与李四的距离,但是计算机不行,它需要一个明确的方法,还是需要坐标系的。

还是假设这个跑道长256米,从起点开始沿逆时针方向(即跑步的方向)标注坐标。

简单情况

先看简单的情况,即A和B在起点的同侧。对应到坐标系上为:

77be2e96-e032-11eb-9e57-12bb97331649.png

A在40米处(记为Xa),B在20米处(记为Xb)。A返回到B的距离为

L = Xa - Xb = 40 - 20 = 20

这个距离远小于256,所以A在B的前面。

溢出情况

再来看看复杂的溢出情况,即A和B在起点两侧。

对应在坐标系上时,为方便绘制,将A、B与起终点的距离拉远一点。Xa=30,Xb=220。A返回到B的距离为:

L = L1 + L2 = (Xa - 0) + (256 - Xb) = 30 + (256 - 220) = 66

66也是远小于256的,所以A还是在B的前面。

归一

有没有发现什么不对?刚才讨论区分简单情况和溢出情况,在计算L时的公式是不同的,这可有点小麻烦。如果有统一的公式就好了。

让我们再看一眼溢出情况的公式:

L = L1 + L2

= (Xa - 0) + (256 - Xb)

= Xa - Xb + 256 = Xa - Xb

这么一调整就和简单情况一样了吧。为什么把加256给去掉了?因为我们讨论Xa和Xb是uint8_t,加256和没加是一样的。

验证

还是上一个例子的场景,我们来假设B在A前面。B返回到A的距离为:

L = Xb - Xa = 220 - 30 = 190

190比较接近256,所以假设不成立,B并不在A前面,而是A在B前面。

我们在判断距离时,用了两种标准:

L远小于256

L比较接近256

对于计算机而言,这是无法实现的,它需要一个明确的标准。那是什么呢?就一刀切吧,以256 / 2为阈值。

L 《 256 / 2:假设成立

L 》 256 / 2:假设失败至于L == 256 / 2的情况,随便归入哪个都行。

再看时间判断

void comm_delay(uint32_t ms)

{

uint32_t timeout = comm_get_ms() + ms;

while(comm_get_ms() - timeout 》 UINT32_MAX / 2);

}

再看这时间判断,有没有豁然开朗呢?comm_get_ms()是张三,timeout是李四,变量范围由uint8_t变成了uint32_t,仅此而已。

后记

这种超时判断方法并非由笔者想出,是笔者在阅读RT-Thead操作系统的timer源码时发现的。rt_timer是RT-Thread定时器模块,提供基于系统滴答计数的定时功能,其计数值就是32位无符号整型uint32_t,时间久了必然溢出。

笔者之前也为溢出问题感到头疼,而RT-Thread号称不惧溢出,于是笔者怀着好奇的心态挖掘了其解决方法。在rt_timer中,有多处这样的判断,现在看起来是不是感觉很亲切呢?

/*

* It supposes that the new tick shall less than the half duration of

* tick max.

*/if ((current_tick - t-》timeout_tick) 《 RT_TICK_MAX / 2)

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 延时
    +关注

    关注

    0

    文章

    110

    浏览量

    26226

原文标题:从rtthread timer模块中找到裸机定时问题的解决方案

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    使用系统定时器SysTick来实现精确延时微秒和毫秒函数

    );//定时1ms即SysTick定时器每1ms中断一次,如果我们定义全局变量,然后在中断函数中,让此变量递减,而在延时函数中,一直判断此变量是否减到了0,那么这样就实现了一个延时毫秒的函数。同理改变定时器
    发表于 11-20 07:12

    数据采集 “延迟高”?5G + 实时采集,毫秒同步无卡顿

    对于企业而言,数据采集的 “快” 与 “准”,不再是可选的加分项,而是生存的必修课。5G + 实时采集,正在让 “毫秒同步” 从技术概念变为可落地的价值创造,为工业数字化转型按下 “加速键”。
    的头像 发表于 11-19 14:05 182次阅读
    数据采集 “延迟高”?5G + 实时采集,<b class='flag-5'>毫秒</b><b class='flag-5'>级</b>同步无卡顿

    感知再进化,新增“触发延时”功能!

    在智能感知的世界里,毫秒的判断往往决定了用户体验的成败。我们公司始终致力于打磨产品的每一个细节。今天,我们自豪地宣布,明星产品HLK-LD2410B24GHz人体存在感应模组迎来重磅功能更新
    的头像 发表于 11-10 11:05 302次阅读
    感知再进化,新增“触发<b class='flag-5'>延时</b>”功能!

    数字毫秒表存在意义、用途及挑选指南 存储式数字毫秒计、数字毫秒

    在追求精准计时的现代社会,电秒表与智能毫秒计凭借其独特的性能,成为多个领域不可或缺的工具。它们不仅解决了传统计时方式精度不足的问题,更随着技术发展不断升级,为各行业的高效运转与创新研究提供有力支撑
    的头像 发表于 11-04 18:20 1863次阅读
    数字<b class='flag-5'>毫秒</b>表存在意义、用途及挑选指南 存储式数字<b class='flag-5'>毫秒</b>计、数字<b class='flag-5'>毫秒</b>计

    如何利用蜂鸟HbirdV2-SoC自带外设PWM进行毫秒延时和计时

    1 队伍介绍 本篇主要介绍如何利用蜂鸟HbirdV2-SoC自带外设PWM进行毫秒延时和计时。 2 TIM0配置 在上一个帖子中,介绍了HbirdV2-SoC自带外设PWM的寄存器
    发表于 10-30 07:47

    手持机是什么?工业手持机抗摔能力怎么样?

    手持机是什么?本文深入解析工业手持机的防水、防尘、摔性能,解读IP等级与MIL-STD标准,结合物流、电力、巡检等实际应用场景,告诉你三
    的头像 发表于 09-28 10:58 274次阅读
    三<b class='flag-5'>防</b>手持机是什么?工业<b class='flag-5'>级</b>三<b class='flag-5'>防</b>手持机抗摔能力怎么样?

    探头的延时介绍

    探头的延时是指信号从被测点传输到示波器输入端的时间间隔,即信号经过探头的探针、传输电缆、内部电路等路径后,到达示波器采样系统的总时间延迟,(以下讨论低速信号情景,忽略示波器通道间ps延时误差)。不同型号的探头
    的头像 发表于 09-17 17:32 648次阅读
    探头的<b class='flag-5'>延时</b>介绍

    毫秒响应!配网行波故障预警与定位装置焕新效率

    在电力配网运行中,故障预警与定位始终是保障供电可靠性的关键环节。一旦发生线路短路、接地等故障,故障区域的持续停电会给工业生产、居民生活带来巨大影响。而如今,配网行波故障定位装置的出现,以其“毫秒
    发表于 09-03 13:45

    认识探头的延时

    探头的延时是指信号从被测点传输到示波器输入端的时间间隔,即信号经过探头的探针、传输电缆、内部电路等路径后,到达示波器采样系统的总时间延迟,(以下讨论低速信号情景,忽略示波器通道间ps延时误差
    的头像 发表于 08-26 17:04 642次阅读
    认识探头的<b class='flag-5'>延时</b>

    中科曙光让气象数据解码迈入毫秒时代

    依托曙光超智融合与液冷技术,某气象大数据云平台的数据并发处理能力跃升显著,数据解码速度进入毫秒时代,为我国气象数值预测现代化建设注入澎湃动力。
    的头像 发表于 07-31 17:17 964次阅读

    智能安边缘计算的技术解析

    维度,剖析核心板如何推动安从"被动记录"到"主动决策"的升级,并给出选型建议。   --- 一、核心板的硬件架构创新**   1. 异构计算架构:算力与能效的平衡  以SSD2351为例,其采用**"CPU+NPU+IVE"三
    的头像 发表于 06-26 11:56 381次阅读

    智能电网第6期 毫秒时延如何实现?电力设备状态实时监控优化

    随着新型电力系统建设加速推进,电力设备状态监控对通信时延的要求已提升至毫秒。在变电站自动化、输电线路监测等场景中,传统通信方案面临严峻挑战:   时延瓶颈:保护控制类业务要求端到端时延 可靠性挑战
    的头像 发表于 04-25 09:40 424次阅读
    智能电网第6期 <b class='flag-5'>毫秒</b><b class='flag-5'>级</b>时延如何实现?电力设备状态实时监控优化

    深控技术工业网关如何让MES数据“精准到毫秒”,驱动智能决策?

    深控技术解决方案:高精度采集+智能校验 技术原理:从“原始数据”到“可信信息” 毫秒实时采集: 支持1ms高速采样(如冲压机压力曲线、激光焊机光强波动),覆盖99%工业场景。 数据流实时推送至MES(延迟
    的头像 发表于 03-17 15:59 556次阅读
    深控技术工业网关如何让MES数据“精准到<b class='flag-5'>毫秒</b>”,驱动智能决策?

    条码比对呆扫描系统提升生产效率,避免重码错码漏码等问题

    高速扫描器(如LV3000U、FM430EX),结合光学识别与图像处理技术,毫秒响应生产线条码信息。通过预设规则与数据库实时校验,发现重复、错误或缺失条码时立即触
    的头像 发表于 03-03 16:29 1286次阅读
    条码比对<b class='flag-5'>防</b>错<b class='flag-5'>防</b>呆扫描系统提升生产效率,避免重码错码漏码等问题

    电子产品三处理技术全面剖析

    在电子产品设计与应用中,三处理(防潮、盐雾、防霉)是确保设备长期稳定运行、提升可靠性和耐用性的关键环节。 随着电子设备应用环境的多样化,尤其是向极端环境拓展,三处理的必要性愈发显著。 本文通过
    的头像 发表于 02-20 09:28 1349次阅读
    电子产品三<b class='flag-5'>防</b>处理技术全面<b class='flag-5'>剖析</b>