设备驱动程序中的中断处理

问题描述 投票:0回答:3

我编写了一个简单的字符驱动程序,并在 GPIO 引脚上请求 IRQ,并为其编写了一个处理程序。

err = request_irq(irq, irq_handler,IRQF_SHARED | IRQF_TRIGGER_RISING,  INTERRUPT_DEVICE_NAME,  raspi_gpio_devp);

static irqreturn_t irq_handler(int irq, void *arg);

现在从理论上我知道,在中断中断控制器时,告诉处理器调用

do_IRQ()
,它将检查IDT并调用该行的中断处理程序。

内核如何知道中断处理程序是针对这个特定设备文件的

我还知道中断处理程序不在任何进程上下文中运行。但是假设我正在访问在处理程序范围之外声明的任何变量,静态全局标志 = 0,在处理程序中我使标志 = 1 指示发生了中断。该变量位于流程上下文中。所以我很困惑这个不在任何进程上下文中的处理程序如何修改进程上下文中的变量。

谢谢

linux-kernel kernel linux-device-driver interrupt
3个回答
8
投票

内核不知道这个特定的中断是针对特定设备的。

它唯一知道的是它必须以

irq_handler
作为参数来调用
raspi_gpio_devp
。 (像这样:
irq_handler(irq, raspi_gpio_devp)
)。

如果您的IRQ线是共享的,您应该检查您的设备是否生成了IRQ。代码:

int irq_handler(int irq, void* dev_id) {
    struct raspi_gpio_dev *raspi_gpio_devp = (struct raspi_gpio_dev *) dev_id;
    if (!my_gpio_irq_occured(raspi_gpio_devp))
        return IRQ_NONE;
    /* do stuff here */
    return IRQ_HANDLED;
}

中断处理程序在中断上下文中运行。 但是您可以访问在中断范围之外声明的静态变量

通常,中断处理程序的作用是:

  • 检查中断状态
  • 从硬件检索信息并将其存储在某个地方(例如缓冲区/fifo)
  • wake_up()
    等待该信息的内核进程

如果您想对中断处理的该做和不该做真正有信心,最好阅读有关内核的进程是什么的内容。

Robert Love 所著的 Linux Kernel Developpement 是一本处理此问题的优秀书籍。


7
投票

内核不知道中断属于哪个设备。单个中断可以在多个设备之间共享。以前这种情况很常见。由于中断控制器中中断支持的改进以及消息信号中断的引入,这种情况正在变得不那么严重。您的驱动程序必须确定中断是否来自您的设备(即您的设备是否需要“服务”)。

您可以通过提供的“void *arg”为中断处理程序提供上下文。这永远不应该是特定于进程的上下文,因为进程可能会退出而使指针悬空(即引用已被释放和/或可能为其他目的重新分配的内存)。

全局变量不是“在进程上下文中”。它存在于所有上下文中——或者如果您愿意的话,也可以不存在任何上下文。当您听到“不在进程上下文中”时,这意味着以下几点:(1)您不能阻塞/睡眠(因为您要让哪个进程进入睡眠状态?),(2)您不能对用户空间虚拟进行任何引用地址(因为这些引用会指向什么?),(3)你不能引用“当前任务”(因为没有一个或它是未知的)。

通常,驱动程序的中断处理程序将数据推送或拉入“驱动程序全局”数据区域,驱动程序的进程上下文端可以从中传输数据。


1
投票

这是为了回答你的问题:-

内核如何知道中断处理程序是针对这个特定的>设备文件的?

  1. 每个片上系统文档都会提到连接到不同中断线的不同设备的中断号。

  2. 必须在设备树条目中提及相同的中断号才能实例化设备驱动程序。

  3. 设备驱动程序常用的探测函数解析设备树数据结构并读取IRQ号并使用register_irq函数注册处理程序。

  4. 如果单个 IRQ 编号/线路有多个设备,则可以在 IRQ 处理程序内部使用 IRQ 状态寄存器(如果映射在同一 VM 空间下,则针对不同的设备)进行区分。

请在我的博客

阅读更多内容
© www.soinside.com 2019 - 2024. All rights reserved.