1. Linux内核虚拟中断控制器驱动开发实战
在嵌入式Linux系统开发中,中断控制器是连接硬件设备和CPU的重要桥梁。传统的中断控制器通常只支持简单的单参数中断配置,但在实际项目中,我们经常需要传递更多元的信息来精确控制中断行为。本文将详细介绍如何开发一个支持多参数传递的虚拟中断控制器驱动。
1.1 中断控制器基础概念
在ARM架构中,中断主要分为三种类型:
-
SPI (Shared Peripheral Interrupt): 共享外设中断,最常见的类型,用于UART、I2C等外部设备产生的中断,可以路由到任何CPU核心。宏定义为GIC_SPI。
-
PPI (Private Peripheral Interrupt): 私有外设中断,针对单个CPU核心,通常用于核心定时器等私有硬件。宏定义为GIC_PPI。
-
SGI (Software-Generated Interrupt): 软件产生的中断,用于CPU核心间的通信。
在设备树中,中断通常这样表示:
c复制interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
1.2 多参数中断控制器的需求
传统的中断控制器通常只支持单一的中断号参数,但在复杂场景下,我们可能需要传递更多信息:
- 中断分组信息(用于区分不同类型的中断)
- 硬件中断号(标识具体的中断源)
- 触发类型(电平触发、边沿触发等)
- 优先级信息
- 目标CPU核心信息
我们的目标是开发一个支持至少3个参数(组号、硬件中断号、触发类型)的虚拟中断控制器。
2. 设备树配置与解析
2.1 设备树节点定义
首先需要在设备树中定义我们的虚拟中断控制器:
c复制vic: virtual_irq_controller {
compatible = "mycorp,virtual-irq-controller";
interrupt-controller;
#interrupt-cells = <3>; // 使用3个cell来描述中断
mycorp,hwirq-base = <0>; // 硬件中断号基址
};
然后定义使用该控制器的客户端设备:
c复制virtual_irq_client {
compatible = "mycorp,virtual-irq-client";
interrupt-parent = <&vic>;
interrupts = <32 60 1>; // 组号32, 硬件中断号60, 触发类型1(上升沿)
};
2.2 设备树解析关键点
-
#interrupt-cells:这个属性决定了描述一个中断需要多少个参数(cell)。我们设置为3,表示需要组号、硬件中断号和触发类型三个参数。
-
interrupt-parent:指定该设备的中断父控制器。
-
interrupts:具体的中断描述,按照#interrupt-cells定义的格式提供参数。
注意:设备树中的硬件中断号是相对于hwirq-base的偏移量。例如,如果hwirq-base=100,那么硬件中断号60实际对应的是160。
3. 驱动实现核心逻辑
3.1 驱动数据结构
c复制#define VIC_MAX_IRQS 100
struct vic_chip_data {
struct irq_domain *domain; // IRQ域
u32 hwirq_base; // 硬件中断号基址
};
3.2 中断芯片操作
我们需要实现irq_chip结构体的基本操作:
