根据 Linus 在此线程中的说法:
如果是 1% 左右的折扣,那就没问题了。如果有人选择了一个对延迟中的小错误非常敏感的延迟值,以至于他们注意到了——或者甚至注意到了 5% 之类的东西——那么他们选择的延迟太短了。
udelay() 从来没有真正打算成为某种精密仪器。尤其是在 CPU 以不同频率运行的情况下,我们历来都会有一些相当剧烈的波动。传统的繁忙循环最终不仅受到中断的影响,而且还受到缓存对齐(我们曾经内联它)之类的影响,然后基于 TSC 的循环显然依赖于 TSC 的稳定(它们不是为了尽管)。
所以从历史上看,我们已经看到 udelay()真的关闭(即 50% 关闭等),我不会担心 1% 范围内的事情。
莱纳斯
所以它不会是完美的。它会关闭。多少取决于很多因素。不要使用for
循环,mdelay
而是考虑使用。可能会更准确一些。来自O'Reilly Linux 设备驱动程序书:
udelay调用应该只在很短的时间内调用,因为 的精度只有loops_per_second
8 位,并且在计算长延迟时会累积明显的错误。即使最大允许延迟接近一秒(因为计算会因更长的延迟而溢出),但建议的udelay最大值为 1000 微秒(一毫秒)。在延迟必须长于一毫秒的情况下,函数mdelay 会有所帮助。
同样重要的是要记住udelay是一个忙等待函数(因此mdelay也是如此);在时间流逝期间无法运行其他任务。因此,您必须非常小心,尤其是使用mdelay时,除非没有其他方法可以实现您的目标,否则请避免使用它。
目前,支持长于几微秒和短于计时器滴答的延迟是非常低效的。这通常不是问题,因为延迟需要足够长才能被人类或硬件注意到。对于与人类相关的时间间隔,百分之一秒是合适的精度,而对于硬件活动来说,一毫秒是足够长的延迟。
特别是“ udelay的建议最大值是 1000 微秒(一毫秒) ”这一行在我看来很突出,因为您声明 2000 是最大值。从此文档中插入延迟:
mdelay 是 udelay 的宏包装器,用于在将大参数传递给 udelay 时解决可能的溢出问题
因此,您可能会遇到溢出错误。虽然我通常不会认为 2000 年是一个“大争论”。
但是,如果您需要真正准确的计时,您需要像您一样处理偏移量,滚动您自己的或使用不同的内核。有关如何使用汇编程序或使用硬实时内核来滚动您自己的延迟函数的信息,请参阅这篇关于高分辨率时序的文章。
另请参阅:Linux 内核:udelay() 返回太早?