6

我有一个需要微秒延迟的驱动程序。为了产生这种延迟,我的驱动程序使用了内核的 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 过早返回引起的,我们向其中一个 I/O 端口提供了一个 100kHz 时钟,并实现了我们自己的延迟,如下所示:

// 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;
            }
        }
    }
}

...并且驱动程序现在可以完美运行。


作为最后一点,我发现一个讨论表明频率缩放可能导致 *delay() 系列函数行为异常,但这是在 ARM 邮件列表中 - 我假设此类问题在基于 Linux x86 的系统上不存在个人电脑。

4

2 回答 2

3

我不知道该版本的内核中有任何错误(但这并不意味着没有错误)。

udelay()不是“不间断的”——它不会禁用抢占,因此您的任务可以在延迟期间被 RT 任务抢占。但是,您的备用延迟实现也是如此,因此这不太可能成为问题。

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

于 2011-12-05T04:20:30.277 回答
2

E5700 有X86_FEATURE_CONSTANT_TSC但没有X86_FEATURE_NONSTOP_TSC。TSC 可能是udelay. 除非使用关联掩码绑定到其中一个内核,否则您的任务可能已在udelay. 或者 TSC 在低功耗 CPU 模式下可能不稳定。

您可以尝试在 期间禁用中断或禁用抢占udelay吗?另外,尝试在之前和之后阅读 TSC。

于 2011-12-03T03:10:13.773 回答