【问题标题】:Handling interrupt in character device处理字符设备中的中断
【发布时间】:2017-01-20 06:34:12
【问题描述】:

我正在尝试在内核中为用户界面正确注册中断。

令人惊讶的是,我在内核中没有找到很多示例。

中断处理程序

static irqreturn_t irq_handler(int irq, void *dev_id)
{
   struct el_irq_dev *el_irq = &el_irq_devices[0];
    printk("irq in\n");

    spin_lock(&el->my_lock,flags);

    clear_interrupt() 

    some_buffer[buf_wr] = ch;
    el_irq->buf_wr++;
    if (el_irqbuf_wr >= 16)
        el_irqbuf_wr = 0;


     spin_unlock(&el->my_lock,flags);
     wake_up_interruptible(&el->pollw);



return IRQ_HANDLED;

}

ioctl 等待中断

static long el_device_ioctl( struct file *filp, 
         unsigned int ioctl_num, 
         unsigned long ioctl_param)
{
    struct el_irq_dev *el_irq = &el_irq_devices[0];
switch (ioctl_num) {
case IOCTL_WAIT_IRQ:      <<<---- using ioctl (no poll) to wait on interrupt
    wait_event_interruptible(el_irq->pollw, &el_irq->buf_wr != &el_irq->buf_rd) ;
    spin_lock(&el_irq->my_lock);
    if (el_irq->buf_wr != &el_irq->buf_rd)
    {
        my_value=some_buffer[el_irq->buf_rd];
        el_irq->buf_rd++;
        if (el_irq->buf_rd >= 16)
            el_irq->buf_rd = 0;
    }

    spin_unlock(&el_irq->my_lock);
    copy_to_user(ioctl_param,&my_value,sizeof(my_value));

default:
        break;
    }
    return 0;
}

我的问题是:

  1. 我们是否应该将 fpga 中的中断清除 (clear_interrupt() ) 放在中断中 在 wake_up 之前还是之后?我们可以将清除中断放在用户空间处理程序(IOCTL_WAIT_IRQ)中,而不是在 中断处理程序?
  2. 正如您在代码中看到的,我使用循环缓冲区来处理用户空间处理程序丢失中断的情况。这真的是必需的还是我们可以假设没有遗漏? 换句话说,假设永远不会错过中断是否合理?这样 ioctl 调用永远不会看到超过 1 个等待中断?如果是 - 也许我不需要中断处理程序和 ioctl 处理程序之间的缓冲机制。

谢谢你, 然

【问题讨论】:

  • 为什么你首先需要所有这些?
  • 我们有 fpga 内存空间,而是在用户空间中执行大部分驱动程序,并且只是从内核向用户空间发出中断信号
  • 什么样的内存?一般用途?为什么不在内核驱动中使用 DMA 呢?

标签: linux-kernel interrupt-handling ioctl


【解决方案1】:

简短回答。

  1. 在我看来,清除用户空间处理程序中的中断似乎是合理的。尽可能晚做是有意义的,在所有工作完成之后,只要你在清理之后再次检查是否真的没有工作要做(一些更多的工作可能在清理之前到达)。李>
  2. 用户空间处理程序可能确实会错过中断,例如如果在对 IOCTL_WAIT_IRQ 的调用之间有几个到达。尽管如果在清除中断之前有几件工作到达,中断也可能在某种意义上被“错过”。堆栈(硬件和软件)的设计应使这不是问题。中断应该只是发出有工作要做的信号,并且用户空间处理程序应该能够在返回之前完成所有未完成的工作。
  3. 您可能应该在您的 IOCtl 代码中使用 spin_lock_irqsave() [1]。

[1]http://www.makelinux.net/ldd3/chp-5-sect-5

【讨论】:

  • 感谢您的详细解答。假设永远不会错过中断是否合理?即 ioctl 应该永远不会看到超过 1 个等待中断?如果是 - 也许我不需要中断处理程序和 ioctl 之间的缓冲机制
  • 不太清楚你所说的“错过的中断”是什么意思。最简单的事情是让 IOCtl 处理程序(不用担心我的大写,有几个变体)在自上次 clear_interrupts() 以来至少有一个中断时返回。但是用户空间处理程序应该假设自 IOCtl 上次返回以来可能已经发生了几次中断,并且用户空间处理程序应该有一种方法可以找出这些中断报告的所有工作。跨度>
  • 所以我假设我在这个例子中使用的缓冲机制(some_buffer)是非常必要的。
  • 如果这是为用户空间提供所有工作的唯一方法,那么可以。在您的代码中,您将“ch”分配给当前的缓冲区插槽,但我看不到您从哪里获得“ch”或它到底是什么(我假设您只是将它从草图代码中删除)。许多硬件会在内部实现像 some_buffer 这样的缓冲区,最终处理程序(在这种情况下是用户空间处理程序)可以直接读取。在这种情况下,将不需要 some_buffer。如果这个硬件不这样做,那么你真的应该确保尽可能快地清除中断以避免丢失工作。这有帮助吗?
  • 是的,它帮了很多忙!我也将此标记为解决方案。我现在也开始认为我真的不需要这个缓冲区,因为硬件很关心。只要我不清除 fpga 中的中断,我希望 fpga 缓冲区的填充量不会超出预期。所以应该不会有任何真正的问题——如果——用户空间处理程序(在 ioctl 上等待)足够快来复制缓冲区并清除中断,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
  • 1970-01-01
  • 2018-05-19
相关资源
最近更新 更多