You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PC平台UIO用户空间中断处理实现问题咨询

在Ubuntu PC上用UIO处理ISA中断的解决方案

因为PC架构没有设备树,没法用嵌入式系统里常见的设备树绑定UIO的方式。不过你可以通过编写一个极简的内核模块来手动注册UIO设备,生成/dev下的uio节点,具体步骤如下:

1. 确认目标ISA IRQ状态

首先要确定你连接的ISA IRQ号,以及它是否空闲:

cat /proc/interrupts

找到对应的IRQ行,确保没有其他设备在使用它(如果是共享IRQ,需要后续模块中设置共享标志)。另外,记得检查BIOS是否启用了该ISA IRQ,有些PC默认会禁用部分ISA中断线路。

2. 编写极简UIO内核模块

创建一个名为uio_isa_irq.c的文件,内容如下(替换IRQ_NUMBER为你的实际IRQ号,比如5):

#include <linux/module.h>
#include <linux/uio_driver.h>
#include <linux/interrupt.h>

// 替换成你的ISA IRQ编号
#define IRQ_NUMBER 5

static struct uio_info uio_isa_irq_info = {
    .name = "uio_isa_irq",
    .version = "0.1",
    .irq = IRQ_NUMBER,
    // 如果IRQ需要共享,保留IRQF_SHARED;独占则去掉
    .irq_flags = IRQF_SHARED,
    // 使用UIO提供的默认中断处理函数,会自动通知用户空间
    .handler = uio_interrupt,
};

static int __init uio_isa_irq_init(void) {
    return uio_register_device(NULL, &uio_isa_irq_info);
}

static void __exit uio_isa_irq_exit(void) {
    uio_unregister_device(&uio_isa_irq_info);
}

module_init(uio_isa_irq_init);
module_exit(uio_isa_irq_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("UIO Driver for ISA External Interrupt");

3. 编译模块

创建Makefile文件:

obj-m += uio_isa_irq.o
all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

先安装内核头文件依赖:

sudo apt update && sudo apt install linux-headers-$(uname -r)

然后编译模块:

make

4. 加载模块并验证

加载模块:

sudo insmod uio_isa_irq.ko

查看/dev目录下是否生成了uio设备节点:

ls /dev/uio*

通常会生成/dev/uio0(如果已有其他uio设备,编号会递增)。

5. 用户空间测试程序

创建一个简单的用户空间程序uio_test.c来验证中断:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#define UIO_DEV_PATH "/dev/uio0"

int main() {
    int fd = open(UIO_DEV_PATH, O_RDWR);
    if (fd < 0) {
        perror("Failed to open UIO device");
        return 1;
    }

    unsigned long irq_count;
    printf("Waiting for ISA interrupts...\n");
    while (1) {
        // 读取中断计数,此调用会阻塞直到中断触发
        if (read(fd, &irq_count, sizeof(irq_count)) == sizeof(irq_count)) {
            printf("Interrupt received! Total count: %lu\n", irq_count);
        }
    }

    close(fd);
    return 0;
}

编译并运行:

gcc uio_test.c -o uio_test
sudo ./uio_test

此时触发外部微控制器的中断,就能看到程序打印中断信息了。

额外注意事项

  • 权限问题:默认/dev/uioX只有root可访问,你可以临时修改权限:
    sudo chmod 666 /dev/uio0
    
    或者添加udev规则永久设置权限:创建/etc/udev/rules.d/99-uio.rules,内容为:
    SUBSYSTEM=="uio", MODE="0666"
    
    然后重载udev规则:
    sudo udevadm control --reload-rules && sudo udevadm trigger
    
  • 卸载模块:如果需要卸载模块,执行:
    sudo rmmod uio_isa_irq
    

内容的提问来源于stack exchange,提问作者jshh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:27:54