第4章 驱动开发基础与设备树
设备树(Device Tree)是嵌入式Linux硬件描述的语言,platform驱动是内核与设备树交互的桥梁,字符设备驱动则是BSP工程师最常编写的驱动类型。面试中,这三个核心点往往被组合考察——从设备树节点定义,到驱动匹配,再到字符设备注册与调试,形成一条完整的技术链路。
📌 面试问答卡片
问题:请描述设备树中一个I2C设备节点的完整结构。
🎯 面试官考察点
- 是否理解设备树节点语法(@地址、compatible、reg)
- 是否知道I2C设备地址如何表示
- 是否熟悉status属性用途
📐 回答框架
- 节点命名:
device@address - compatible = "厂商,芯片型号";
- reg = <地址>; (I2C为7位地址)
- 可选status = "okay" / "disabled"
💬 简短示例回答
“例如:&i2c1 { touch@1a { compatible = "goodix,gt911"; reg = <0x1a>; status = "okay"; }; }; 其中reg是设备I2C地址,compatible用于驱动匹配,status控制节点是否生效。”
❓ 可能追问
如何添加两个同型号设备?如何表达中断引脚?
⚠️ 避坑提醒
reg中的地址必须为整数,不可用字符串;不要忽略status="disabled"导致驱动不加载。
问题:platform驱动如何与设备树中的节点匹配?
🎯 面试官考察点
- 是否理解of_match_table机制
- 是否知道MODULE_DEVICE_TABLE的作用
- 是否了解驱动与设备树的绑定关系
📐 回答框架
- 驱动定义struct of_device_id数组,填compatible
- 内核扫描设备树中已注册节点的compatible
- 匹配成功则调用probe
- 导出MODULE_DEVICE_TABLE以便模块加载
💬 简短示例回答
“驱动中声明 static const struct of_device_id my_of_match[] = { { .compatible = "vendor,device" }, {} }; 并使用 MODULE_DEVICE_TABLE(of, my_of_match);。设备树节点中compatible属性与之一致,内核即可自动匹配并调用probe。”
❓ 可能追问
多个驱动匹配同一compatible会怎样?of_match_table支持模糊匹配吗?
⚠️ 避坑提醒
忘记导出MODULE_DEVICE_TABLE,模块加载时将无法自动匹配;内核会按编译顺序选择第一个匹配的驱动。
问题:字符设备驱动的probe函数中需要完成哪些初始化工作?
🎯 面试官考察点
- 是否熟悉字符设备注册流程(设备号、cdev、class)
- 是否知道file_operations结构体的实现要求
- 是否理解设备节点自动创建机制
📐 回答框架
- 动态分配设备号:alloc_chrdev_region
- 初始化cdev结构:cdev_init
- 添加cdev到内核:cdev_add
- 创建设备类/节点:class_create + device_create
💬 简短示例回答
“先调用alloc_chrdev_region(&devno,0,1,"mydev")获取设备号,然后cdev_init(&cdev,&fops)和cdev_add(&cdev,devno,1),最后通过class_create(THIS_MODULE,"myclass")和device_create(class,NULL,devno,NULL,"mydev")自动创建设备节点。”
❓ 可能追问
如何避免设备号冲突?如果系统没有udev/mdev,节点怎么创建?
⚠️ 避坑提醒
使用静态注册(MKDEV)容易冲突,推荐动态分配;cdev_add失败后需手动释放设备号。
📁 项目案例模板:基于设备树的I2C触摸屏驱动调试
| 项目名称 | 基于设备树的I2C触摸屏驱动调试(Goodix GT911) |
| 业务背景 | 某款工业平板使用Goodix GT911电容触摸屏,需在Linux 5.4内核上适配驱动并支持多点触控,中断响应要求<10ms。 |
| 规模指标 | 单板调试,触摸点数5个,中断频率约80Hz |
| 技术栈 | Linux 5.4、设备树、I2C subsystem、input子系统、中断处理 |
| 核心难点 | ①设备树中断配置错误导致中断无法触发;②I2C时序不匹配导致通信失败;③多点触控协议上报时序。 |
🔥 面试高频追问
- 如何验证设备树中的中断配置是否正确?
- I2C通信失败时,你的排查步骤是什么?
- 如何确认驱动确实收到了中断并上报了input事件?
💡 可迁移回答话术
“调试中断时先cat /proc/interrupts确认中断号计数是否变化,再检查设备树中interrupts属性值是否与GPIO控制器的中断号匹配。I2C通信验证用i2cget -f -y 读取寄存器,对比预期值。如果读回全0xFF则多半是地址或硬件连接问题。”