内核中,互斥锁的使用
驱动初始化流程
- 申请自定义beep结构体空间
*- 构建新的CDEV设备
- 注册新申请的设备编号
- 设置新的cdev操作方法
- 将cdev加入链表中
*- 初始化锁资源
*- 映射物理地址空间
- 操作寄存器
- 创建sys文件系统中的设备类文件
- 创建新的设备文件
*- 构建调试节点
我们可以简化2、4部分流程,使用系统的混杂设备
思想
1.设备和驱动分离
驱动:保留相同操作;不同硬件设备信息单独分离出来
1.设备树
|------|--------------|
| dts | 设备树源文件 |
| dtsi | 设备树头文件 |
| dtb | 编译好的二进制设备树文件 |
| DTC | 编译工具 |
节点名 {
属性1 = ;
属性2 = ;
}
2.驱动分层
1.pinctrl方案定义
pinctrl_puteled : puteled {
fsl,pins = <宏名 电气属性寄存器的值>;
};
2.pinctrl方案使用
设备树节点{
pinctrl-name = " 名称(一般为default)"
pinctrl-0 = <&pinctrl方案定义名>;
};
3.gpio子系统
设备树节点 {
gpio-名称 = <&gpio1 5 0>;(最后一位:外设使能的逻辑电平)
};
阻塞
中断
中断中执行速度快,不允许睡眠、延时
中断中不能加互斥锁(阻塞等待),互斥锁加锁和解锁之间,可以切换调度任务
中断中可以加自旋锁(忙等待),自旋锁 中间不会切换调度任务
中断子系统
GPIO按键驱动改造为标准的input设备
对比了传统混杂设备(misc)与input子系统的差异,并详细演示了如何将一个GPIO按键驱动改造为标准的input设备。
1. 输入设备框架概述
- 输入设备(如按键、鼠标、触摸屏)应使用Linux input子系统,而非misc混杂设备,以获得更规范的事件上报机制和统一的用户空间接口。
- input设备支持多种连接方式(GPIO、USB、I2C等),并通过事件类型(type)、编码(code)和值(value)三元组上报事件。
2. input设备驱动实现步骤
- 申请设备 :使用
input_allocate_device()分配input_device结构体。- 配置能力 :通过
set_bit()设置支持的事件类型(如EV_KEY)和按键编码(如KEY_0)。- 注册设备 :调用
input_register_device()将设备注册到系统。- 中断处理 :在中断服务程序中调用
input_event()上报按键按下/抬起事件,并以input_sync()结束事件包。3. 应用层交互与设备节点
- input设备自动在
/dev/input/eventX下创建节点,无需手动mknod。- 应用层通过读取
/dev/input/eventX获取input_event结构体数据,解析type、code、value即可识别按键事件。4. 补充说明
- 按键抖动需在驱动或应用层通过定时器消抖处理。
总线
功能
将设备与驱动进行匹配
匹配规则
- 设备树节点device中的overdrive与驱动名一致
- 设备树节点中compatible选项与驱动of_match_table一致
- x86架构中设备树与驱动匹配(x)
- device设备树中的设备名与驱动中id_tables一致
- 设备名称与驱动名称一致
注册设备
- misc_register
- input_register
- fd_register
- v412_register
- iio_register
虚拟平台总线
像蜂鸣器之类的设备没有总线连接,可以使用虚拟平台总线
Probe函数在驱动加载时被调用,主要完成以下几项关键工作:
- 设备匹配校验 :通过
of_match_device再次确认设备树节点与驱动的匹配关系,若不匹配则直接退出,确保安全性09:13。- 获取设备数据 :从匹配到的设备树节点中提取配置信息(如
match_data),并转换为驱动内部使用的结构体09:41。- 内存资源映射 :从设备树中获取寄存器基地址和大小,调用
devm_ioremap进行物理地址到虚拟地址的映射11:34。- 申请并初始化私有数据:为引脚控制所需的结构体分配内存空间,并初始化寄存器默认值(如将配置寄存器设为 -1)10:10。
- 注册操作接口 :设置
pinctrl_ops操作结构体,注册到内核的 pinctrl 子系统中,完成设备注册
I2C子系统

通信协议

主机接收数据:start信号-> 从机地址+w -> ACK -> 寄存器地址








