我们有一个使用3.2内核的ARM9 - 一切似乎都运行良好。最近我被要求添加一些代码,以便在启动时在某些GPIO线上添加50ms脉冲。脉冲代码很好;正如预期的那样,我可以看到线条向下和向上。什么不能按我预期的方式工作udelay()
函数。阅读文档使我认为单位是微秒,但在逻辑分析仪中测量它太短了。所以我最终添加了这段代码以获得50ms。
// wait 50ms to be sure PCIE reset takes
for (i=0;i<6100;i++) // measured on logic analyzer - seems wrong to me!!
{
__udelay(2000); // 2000 is max
}
我不喜欢它,但它运作正常。 udelay
代码中有一些奇怪的常量和指令。有人可以告诉我这应该如何工作?所有时钟初始化后调用此代码,所以其他一切似乎都没问题。
答案 0 :(得分:4)
根据Linus在this thread中的说法:
如果它大约1%的折扣,一切都很好。如果有人选择了延迟值 这对他们注意到的延迟中的小错误非常敏感 那 - 或者甚至注意到5%的东西 - 然后他们也选择了 没有延迟。
udelay()从来没有真正意义上的某种精确性 仪器。特别是CPU运行频率不同, 我们历史上有一些相当大的波动。传统的 繁忙的循环最终不仅会受到中断的影响,还会受到影响 像缓存对齐(我们用来内联它),然后是后来的 基于TSC的显然取决于TSC的稳定性(他们 没有一段时间)。
所以在历史上,我们已经看到udelay()真的关闭(即50%的折扣) 等),我不担心1%范围内的事情。
莱纳斯
所以它不会是完美的。它会关闭。多少取决于很多因素。请考虑使用for
,而不是使用mdelay
循环。它可能会更准确一些。来自O'Reilly Linux Device Drivers书:
udelay 调用只能在短时间内调用,因为
loops_per_second
的精度只有8位,值得注意 计算长延迟时会累积错误。即便如此 最大允许延迟接近一秒(自计算以来) 溢出更长的延迟), udelay 的建议最大值是 1000微秒(一毫秒)。函数 mdelay 有助于 延迟必须超过一毫秒的情况。记住 udelay 是一个忙碌的等待功能也很重要 (因此 mdelay 也是如此);其他任务在此期间无法运行 失效。因此,您必须非常小心,特别是使用 mdelay ,以及 除非没有其他方法可以达到目标,否则请避免使用它。
目前,支持延迟时间超过几微秒 短于计时器滴答是非常低效的。这通常不是 问题,因为延迟需要足够长的时间才能被注意到 人类或硬件。百分之一秒是合适的 与人类相关的时间间隔的精度,而一毫秒是一个 硬件活动的延迟时间足够长。
特别是 udelay 的建议最大值 1000微秒(1毫秒)“,因为你声明2000是最大值。从this document开始插入延迟:
mdelay是udelay周围的宏包装器,可以解释 将大型参数传递给udelay
时溢出
所以你可能会遇到溢出错误。虽然我通常不认为2000是一个“大论点”。
但是如果你的时间需要真正的准确性,你需要像你一样处理偏移,自己动手或者使用不同的内核。有关如何使用汇编程序或使用硬实时内核滚动自己的延迟函数的信息,请参阅High-resolution timing上的这篇文章。