Linux内核驱动程序:IRQ触发或超时



在linux内核驱动程序中,我想无限期地重复以下序列:

  • 在时间T,硬件IRQ被启用
  • 在时间T和T+"大约"15ms之间,如果触发IRQ,则可以到达IRQ回调。我之所以这么说,是因为我没有使用RT内核,如果是14或16ms,那也没关系。在IRQ回调中,我需要写下get-cpu_clock(0)并调用wake_up_interruptible。超时需要终止。整个过程需要在5ms内重新启动
  • 如果T+"大约"15毫秒,IRQ还没有被触发,我需要执行一些其他代码。然后应禁用IRQ。整个过程需要在5ms内重新启动

因此,在T+"大约"20ms时,在最坏的情况下,整个过程需要重新启动。

请注意,如果IRQ在18ms时被物理触发,那就太糟糕了,"我错过了火车"。我将在下一个序列中捕获另一个硬件触发器。

在测试时,我沿着以下伪代码做了一些事情:

INIT_DELAYED_WORK(&priv->work, driver_work);
INIT_DELAYED_WORK(&priv->timeout, driver_timeout);
request_irq(priv->irq, driver_interrupt, IRQF_TRIGGER_RISING, "my_irq", priv);

然后:

queue_delayed_work(priv->workq, &priv->work, 0ms);
static void driver_work(struct work_struct *work) {
    queue_delayed_work(priv->workq, &priv->timeout, 15ms);
    priv->interruptCalled = 0;
    enable_irq(priv->irq);
}

然后:

static irqreturn_t driver_interrupt(int irq, void *_priv) {
    disable_irq_nosync(priv->irq);
    priv->interruptCalled = 1;
    cancel_delayed_work(&priv->timeout);
    priv->stamp = cpu_clock(0);
    wake_up_interruptible(&driver_wait);
    queue_delayed_work(priv->workq, &priv->work, 5ms);
    return IRQ_HANDLED;

}

和:

static void driver_timeout(struct work_struct *work) {
    if (priv->interruptCalled == 0) {
        disable_irq_nosync(priv->irq);
        //Do other small cleanup
        queue_delayed_work(priv->workq, &priv->work, 5ms);
    }
}

我正在尝试编写一个健壮但简单的驱动程序。这是一个恰当的实施吗?如何改进此实施?

回答我自己的问题:问题是queue_delayerd_work是基于jiffies的。或者5ms是不可能的,因为HZ=100(1 jiffy=10ms)。HR计时器带来了一个很好的解决方案。

相关内容

  • 没有找到相关文章

最新更新