我做了这样的功能
trace_printk("111111");
udelay(4000);
trace_printk("222222");
并且日志显示它是4.01毫秒,它是'OK
但是当我这样打电话时
trace_printk("111111");
ndelay(10000);
ndelay(10000);
ndelay(10000);
ndelay(10000);
....
....//totally 400 ndelay calls
trace_printk("222222");
日志将显示4.7毫秒。这是不可接受的。 为什么ndelay的错误是如此巨大?
深入了解内核代码,我发现了这两个函数的实现
void __udelay(unsigned long usecs)
{
__const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
}
void __ndelay(unsigned long nsecs)
{
__const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
}
我认为udelay将是ndelay的1000倍,但它不是,为什么?
答案 0 :(得分:2)
正如您已经注意到的那样,纳秒延迟实现与毫秒延迟相比是一个非常粗略的近似,因为使用了0x5
常数因子。 0x10c7 / 0x5
约为859.使用0x4
将接近1000(约1073)。
但是,使用0x4会导致ndelay
小于请求的纳秒数。通常,只要用户请求,延迟函数的目的就是提供至少的延迟(参见此处:http://practicepeople.blogspot.jp/2013/08/kernel-programming-busy-waiting-delay.html)。
答案 1 :(得分:1)
每次调用它时,都会添加舍入错误。请注意评论2**32 / 1000000000
。这个值真的是~4.29,但它被四舍五入到5.这是一个非常大的错误。
相比之下,udelay错误很小:(~4294.97对4295 [0x10c7])。
答案 2 :(得分:0)
您可以使用ktime_get_ns()获得自启动以来的高精度时间。因此,您不仅可以将其用作高精度延迟,还可以将其用作高精度计时器。有一个例子:
u64 t;
t = ktime_get_ns(); // Get current nanoseconds since boot
for (i = 0; i < 24; i++) // Send 24 1200ns-1300ns pulses via GPIO
{
gpio_set_value(pin, 1); // Drive GPIO or do something else
t += 1200; // Now we have absolute time of the next step
while (ktime_get_ns() < t); // Wait for it
gpio_set_value(pin, 0); // Do something, again
t += 1300; // Now we have time of the next step, again
while (ktime_get_ns() < t); // Wait for it, again
}