等待二十个tick很简单,直到读数突然变小
嵌入式设备采集数据、启动AI推理,并等待结果在规定时间内返回。固件读取递增计数器:保存截止值,再与当前值比较,是否就足够?接近计数器上限时,这种比较可能在等待刚开始时就宣告超时。问题不是模型速度,而是如何用有限位数表示时间。
研究对象是16位无符号计数器,取值0到65535。从65530开始,等待20次递增,表示出来的截止值是14,比起点还小。我们将推导:在明确条件下,模差值为何能正确恢复经过时间,以及为什么它无法恢复未被观察到的完整一圈。所有数值都来自已执行的Python程序,没有编译固件、测量开发板或在设备上运行内核。
先理解tick,再换算秒
tick是计数器的一次离散递增。假设每秒1000 tick,可以把计数换算为秒,但这并不意味着程序进行了时间测量。16位计数器经过65536次递增回到初始值,在假设频率下相当于65.536秒。32位的相同计算约为49.71天。增加位数只是推迟问题,并不能修正无法跨越归零点的顺序比较。
M是可用状态的数量,不是可存储的最大值;最大值为M−1。mod表示除以M得到的余数,取0到M−1之间的值。当当前读数还是65530时,“当前值大于等于14”就已经成立,但没有经过任何tick。因此,这个比较本身无法表达等待,即使远离上限的例子看起来正常。
比较时间间隔,而不是表盘上的两个标签
计数器类似一个转到最后刻度后又回到第一刻度的表盘。这个类比说明,小读数不一定代表更早,但不能告诉我们转了几圈。要恢复从起点前进的距离,应先相减,再把结果映射回同一状态集合。这是模差值,不是无限精度整数的普通减法。
经过11 tick后,计数器读数为5。普通减法5−65530为负数,模65536后则为11。经过20 tick,读数为14,模差值为20,达到所要求的持续时间。这个判据也能正确处理截止前后的相邻读数。但在称它为通用方案之前,还必须证明delta实际保留了哪些信息。
证明同时给出适用边界
令E为从起点实际经过的递增次数。它是参考模型中的变量,并不是计数器自动提供的信息。若计数器没有跳变或复位,now就是start+E的余数。代入模差值,start被消去,结果为E模M。当E处于0到M−1之间时,余数就是E本身。
因此得到明确的充分条件:从起点实际经过的时间必须少于完整一圈;duration阈值必须可表示,且使用同一计数单位。在这些条件下,比较delta和duration,就等价于比较实际经过的tick数和阈值。当前读数无需在数值上大于初始读数;关键限制在于两次读数所代表的实际时间间隔。
| 实际E(tick) | now | delta | 正确超时判断 | 简单比较 |
|---|---|---|---|---|
| 0 | 65530 | 0 | 0 | 1 |
| 5 | 65535 | 5 | 0 | 1 |
| 11 | 5 | 11 | 0 | 0 |
| 19 | 13 | 19 | 0 | 0 |
| 20 | 14 | 20 | 1 | 1 |
| 26 | 20 | 26 | 1 | 1 |
表中1表示真,0表示假;简单比较是now大于等于截止值14。前两行体现关键失败:程序可能还没给推理过程留出所需等待时间,就将其终止。后面的行解释了为什么只在归零后测试,会误以为判据正确。检验计时算法需要覆盖转换发生前的情况,而不是只看最终读数。

两次读数无法恢复隐藏的完整一圈
现在在没有其他信息的情况下,让时间恰好经过65536 tick。计数器回到初值65530,delta为0。真实的20 tick等待早已结束,但模比较无法识别。这并不是证明出错,而是违反了E小于M的假设。两次观察与零等待时完全相同;任何只接收这些观察的算法,都无法确定区分两种情况。
解决办法需要额外信息或约束,例如记录圈数的计数器、保证观察间隔的上限、更宽的定时器,或由操作系统时间服务保存所需状态。“定期读取”不能只是模糊承诺,必须把读取频率与最大可能延迟联系起来,包括休眠和阻塞。如果设备重启或计数器因其他原因被清零,也就不再符合简单模递增模型。
为什么还会听到半圈限制
另一个问题是:事先不知道两时间戳之间时间方向时,如何判断任意两个时间戳谁先谁后?在8状态的表盘上,0与4相对,两个方向的模距离都是4。要定义局部顺序,必须把观察范围限制在半圈以内。不能把它与前面的证明混淆:恢复已知非负的经过间隔,允许E小于一整圈;为任意时间戳排序则是另一个问题。
因此本文不把转换为有符号整数当作万能捷径。除半区间假设外,这种技术还依赖语言与表示规则。代码明确使用Python整数求模M余数,使算术模型清晰可见。这不等于证明它与任何处理器上编译的、看似相同的C表达式都等价。
变量类型不一定是减法运算的类型
在C中,较小类型的操作数可能在相减之前发生整数提升。例如,若int能表示某16位无符号类型的全部值,操作数可能提升为int。此时5−65530先得到可表示的负整数,而不是直接按模65536计算。之后再赋给预期位宽的无符号类型,才引入模转换。这是两个不同步骤。
公开草案N1570于2011年4月12日发布,其6.2.5、6.3.1.1和6.3.1.3节记录了这些区别。本文将它作为C11草案引用,而不是所有当前编译器行为的认证说明。若在转换前比较,使用的值可能不同于模型预期。我们没有编译C程序;实现时必须检查具体工具链中的类型、提升、常量与转换,不能仅凭变量名称推断正确性。
内核实际做了什么:不仅是一次减法
我们阅读了FreeRTOS-Kernel V11.2.0的tasks.c中xTaskCheckForTimeOut方法,版本明确,并非笼统指向当前分支。该方法在临界区读取计数,考虑溢出状态,在继续等待时更新剩余时间,并处理阻塞被中止、无限等待等选项。这里概述的是已阅读的方法,并不等于执行或验证整个内核。
所以,隐藏一整圈的例子不能证明FreeRTOS有缺陷:我们的模型只有两次读数,内核方法却保存额外状态。比较接口时,必须考虑它们拥有的信息是否相同。从还依赖圈数、临界区和状态更新的算法中只抄出一行减法,可能恰好删掉了原算法正确所需的条件。
原子读取与算术是不同问题。若一个较宽的计数器分多次读取,可能把不同时刻的高低部分拼在一起;复位也可能改变时间起点的含义。这里假设读数一致且没有复位。Python代码不能证明微控制器读取的原子性,也不能证明某架构上临界区的效果;这些需要具体平台、编译器、配置和专门测试。
程序检查的是性质,不是性能
为避免只依赖少量数值,我们把计数器缩小为8位,测试全部256个起点与0至255之间全部256个间隔,共65536种情况。每种情况下,模差值都等于实际间隔。这不是可靠性百分比,也不是统计抽样,而是对缩小模型中特定性质的穷举检查。前面的证明则说明,在所列假设下,相同恒等式对任意M都成立。
测试所有组合需要M²种情况,b位时即4的b次方。因此穷举例子只用8位,并不声称已经探索16位或32位系统的所有运行历史。若计数器能放入一个机器字,单次差值只需固定数量的算术操作。但这不是微秒级测量,真实成本取决于实现、编译器和平台。Python的无限精度整数也不是MCU能耗模型。
附件代码把模拟器已知的真实经过时间E,与算法能够得到的读数now分开保存。这种区分是发现时间混叠的关键。若预期结果也用同一模差值生成,测试就只是在重复实现,无法检查完整一圈的限制。保存的数据特意包含E等于M的情况:此时方法缺少必要信息。
从计数到真实推理截止时间
二十个tick并不自动保证任务在20毫秒内完成。即使假设每秒1000 tick,初始读取也可能落在两次递增之间,任务还可能因调度延迟而稍后才执行。模型只计算递增次数,没有恢复初始相位。真实截止时间必须定义预算从何时开始、由哪个时间源测量,以及超时动作何时真正生效。
在传感器、预处理、推理、执行器组成的流水线中,只计算神经网络等待时间会遗漏其他环节。若推理结束后才检查截止时间,可能只能发现迟到,却无法阻止迟到。正确计时算术回答的是一个必要但更窄的问题:在模型条件下经过了多少次递增?它不能证明整条流水线的最大延迟、分位数、能耗或实时性。
从模型走向测量,需要明确平台、tick配置、内核与编译器版本、采集协议及运行条件。本文没有把这些内容写成已测事实,因为这里没有硬件试验。EL-AI对嵌入式应用的兴趣,是待探索的编辑与应用方向,不代表企业已经拥有具备这些性能的开发板或实际部署。
结论:读数归零不代表经过的时间归零
超时必须按时间间隔理解。在本例中,若已知实际间隔小于65536 tick,从65530到14就意味着经过了20 tick。模差值能够跨越零点保留这一信息。如果可能已经过了未观察到的完整一圈,两次读数就不够,需要额外状态或有保证的时间界限。认识到这一边界,才能避免把实用公式误当成普遍可靠性的承诺。
来源、版本与代码
M=65536
start=65530
duration=20
for elapsed in [0,5,11,19,20,26,65536]:
now=(start+elapsed)%M
delta=(now-start)%M
print(elapsed,now,delta,delta>=duration)
for start8 in range(256):
for elapsed8 in range(256):
now8=(start8+elapsed8)%256
assert (now8-start8)%256==elapsed8
代码、数据与说明 · JSON. 教学计算使用 Python 3.14.0,图使用 Matplotlib 3.11.2。分析由 AI 辅助,不声称经过同行评审或人工审核。原创 ImageGen 封面仅作示意,不记录 EL-AI 人员、场所或实际安装。来源查阅于 2026 年 10 月 21 日。

