我有一个需要微秒延迟的驱动程序。为了产生这种延迟,我的驱动程序正在使用内核的udelay函数。具体来说,有一个对udelay(90)的调用:

iowrite32(data, addr + DATA_OFFSET);
iowrite32(trig, addr + CONTROL_OFFSET);

udelay(30);

trig |= 1;
iowrite32(trig, addr + CONTROL_OFFSET);

udelay(90); // This is the problematic call

我们的设备存在可靠性问题。经过大量调试,我们将问题追溯到驱动程序在90us过去之前恢复。 (请参阅下面的“证明”。)

我在Intel Pentium Dual Core(E5700)上运行内核版本2.6.38-11-generic SMP(Kubuntu 11.04,x86_64)。

据我所知,文档指出udelay将延迟执行至少指定的延迟,并且是不间断的。 此版本的内核是否存在错误,还是我对udelay的使用有误解?

为了使自己确信问题是由于udelay返回时间过早而引起的,我们将100kHz时钟馈送到一个I/O端口,并实现了自己的延迟,如下所示:
// Wait until n number of falling edges
// are observed
void clk100_delay(void *addr, u32 n) {
    int i;

    for (i = 0; i < n; i++) {
        u32 prev_clk = ioread32(addr);
        while (1) {
            u32 clk = ioread32(addr);
            if (prev_clk && !clk) {
                break;
            } else {
                prev_clk = clk;
            }
        }
    }
}

...驾驶员现在可以正常工作。

作为最后的注释,我发现a discussion指示频率缩放可能导致* delay()系列功能出现异常,但这在ARM邮件列表中-我假设在基于Linux x86的PC上将不存在此类问题。 。

最佳答案

我不知道该内核版本中的任何错误(但这并不意味着没有错误)。
udelay()不是“不间断的”-它不会禁用抢占,因此RT任务可以在延迟期间抢占您的任务。但是,您的备用延迟实现也是如此,因此这不太可能成为问题。

您的实际问题可能是DMA一致性/内存排序问题吗?您的备用延迟实现访问总线,因此这可能将实际问题隐藏为副作用。

关于Linux内核: udelay() returns too early?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8352812/

10-12 04:34