加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

Linux内核:udelay()返回太早了?

发布时间:2020-12-14 02:02:18 所属栏目:Linux 来源:网络整理
导读:我有一个需要微秒延迟的驱动程序.为了创建这个延迟,我的驱动程序正在使用内核的udelay函数.具体来说,有一个调用udelay(90): iowrite32(data,addr + DATA_OFFSET);iowrite32(trig,addr + CONTROL_OFFSET);udelay(30);trig |= 1;iowrite32(trig,addr + CONTRO
我有一个需要微秒延迟的驱动程序.为了创建这个延迟,我的驱动程序正在使用内核的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;
            }
        }
    }
}

……现在司机完美无瑕.

最后一点,我发现a discussion表明频率缩放可能导致* delay()函数系列行为不当,但这是在ARM邮件列表上 – 我假设在基于Linux x86的PC上不存在这样的问题.

解决方法

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

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读