1. 为什么需要设备与驱动分离架构
在传统嵌入式开发中,硬件驱动往往与具体设备高度耦合。我曾接手过一个老项目,代码里充斥着这样的写法:
c复制#define LED_GPIO_PORT GPIOA
#define LED_GPIO_PIN GPIO_PIN_5
void led_init(void) {
GPIO_InitTypeDef gpio;
gpio.Pin = LED_GPIO_PIN;
gpio.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(LED_GPIO_PORT, &gpio);
}
这种写法的问题在于:当硬件变更时(比如LED从PA5改为PB3),需要重新修改驱动代码并编译整个内核。在工业级产品中,这种耦合会导致维护成本呈指数级上升。
设备驱动分离架构通过以下方式解决这个问题:
- 设备资源描述:将硬件参数(如GPIO编号、中断号)提取到设备树(dts)或平台数据中
- 驱动通用化:驱动代码只处理业务逻辑,不包含具体硬件参数
- 动态绑定:通过匹配机制(如compatible属性)在运行时关联设备与驱动
以按键中断为例,分离后驱动只需要关注:
- 如何注册中断处理函数
- 消抖算法实现
- 事件上报机制
而具体的GPIO引脚、触发方式等都由设备树描述。
2. Linux中断子系统关键机制解析
2.1 中断注册流程剖析
在Linux内核中,request_irq()的实际工作流程远比表面复杂。以ARM平台为例,其调用链如下:
code复制request_irq()
→ __setup_irq()
→ irq_alloc_desc() // 分配中断描述符
→ irq_set_chip() // 设置硬件控制器操作集
→ irq_set_handler() // 设置中断处理函数
关键数据结构关系:
mermaid复制graph TD
irq_desc --> irq_chip
irq_desc --> irqaction
irqaction --> handler
实际开发中最容易忽
