嵌入式Linux驱动开发学习--韦东山老师嵌入式Linux学习
- 最无益,只怕一日曝十日寒,贵在有恒。
2025-01-18
1、基础内容
- 应用、驱动、硬件:
- 应用程序通过标准的接口访问文件,访问到驱动程序,最终到达硬件:
- 应用程序和驱动程序涉及到用户数据和驱动数据的拷贝;
- 驱动程序和硬件涉及到硬件寄存器实际地址和虚拟地址变量的映射;
- 物理地址和虚拟地址映射:
ioremap
; - CPU看到的是MMU映射的虚拟地址,使得启动两次的相同应用程序虽然在内存实际不同地址上但其中变量可以打印相同的虚拟地址,其他硬件也类似;
- 物理地址和虚拟地址映射:
- 驱动程序编写步骤:
- 1)提供主设备号;
- 2)定义file_operations 结构体,应用的标准接口能够调用起来 =》 驱动程序里也提供对应的接口;
- 3)注册设备驱动;
- 4)提供入口函数,放到
module_init()
宏; - 5)提供出口函数,放到'module_exit()`宏;
- 6)提供 class_create 和 device_create 创建设备节点;
2、通用GPIO操作
- 1)使能GPIO:用到的时候开启时钟、配置使能等;
- 2)通过MUX_MODE将引脚配置为GPIO功能(可能有多功能复用);
- 3)配置输入输出模式:用于输入还是用于输出,Dir;
- 4)设置输出数据或者读取输入数据;
3、硬件操作
- 根据硬件地址操作对应硬件位置的值或者读取——定义指针指向该地址即可;
volatile
(易变的)使用:- 程序中对于同一变量连续两次赋值编译器可能会优化只执行后面的语句,因为最终结果相同;
- 但是对于硬件来说,连续的操作可能是为了作不同的事情,不能这样优化,必须一步一步来——加上
volatile
声明,要求编译器不做优化;
4、驱动涉及的思想_面向对象_分层_分离
- Linux驱动 = 驱动框架 + 硬件操作;
1)面向对象
- 把事件抽象为结构体,如字符设备驱动程序抽象出一个 file_operations 结构体;
2)分层
- 上下分层:将硬件无关操作和硬件相关操作分开为上下两层;
3)分离
- 左右分离:将资源类型文件和硬件通用代码分离为左右两侧;
5、驱动进化之路_总线设备驱动模型
- 驱动编写的3种方法:
- 1)传统写法:
- 2)总线设备驱动模型:
- 左右分离思想的更好扩展实现 ,分别用 platform_device 结构体和 platform_driver 结构体来对应分离的硬件具体引脚等和通用硬件操作代码;
- 然后用总线来管理他们,总线左边一系列 device,总线右边一系列 driver,通过总线将他们两两匹配;
- 对于各种不同设备 device 的定义,可以直接用一个 .c 文件来管理 platform_device,但是会因为各种不同硬件设备出现一堆的 .c 文件;
- 通过 .c 文件定义 dev 与 driver 的匹配:
- 在配对成功的时候,通过 driver 的 probe 函数实现资源的注册和初始化;当设备去掉以后,调用 driver 的 remove 函数;
- 3)使用dts文件来实现 device 的配置,dts 文件可编译为 dtb 文件,传递给内核成为 platform_device 结构体;
- 解决用 .c 文件定义 dev 设备造成的大量重复、没有过多技术含量的代码文件,并且每次有修改就要重新编译内核 =》 用配置文件来解决,内核动态加载;
01-19
6、驱动进化之路_设备树的语法
- 设备树语法:
- 1)节点:
- 节点的名字后面也可以加上地址,也可以加上label方便在设备树种引用;
- 2)节点的属性:
- 常用属性:
- compatible,兼容;
- status:状态,使能/禁用;
- reg:表示寄存器地址;
- name:节点名字,可以用来与 platform_driver 匹配;
- device_type:节点类型;
- 1)节点:
- dtsi :i 表示 include,语法与 dts 一致,用来给不同的单板 dts 包含——此处,可以引用label + 配合 status 属性设置为 dsabled,将公板中定义的节点而本单板用不到的节点给禁用掉;
7、驱动进化之路_内核对设备树的处理与使用
7.1 内核对设备树的处理与使用
- 设备树是给内核、驱动程序使用的,内核与驱动程序如何使用设备树?
- 1)dtb 中每个节点都被转换为 device_node 结构体:
- 2)某些device_node 转换为 platform_device(并不是所有都能转换):
- 3)driver 与设备树定义的 device 匹配:
- 4)匹配成功后,调用 platform_driver 里面的 probe 函数获得设备树节点中的资源:
- 使用 platform_get_resource 接口获得标准资源,如reg、interrupts获得memory资源、中断资源等;
- 对于非特殊节点,也可以使用内核函数来获得属性;同样对于没有转化为 platform_device 的节点也可以调用内核函数获得对应属性值;
- 5)如何修改设备树文件:
7.2 LED模板驱动程序的改造:设备树
-
1)设备树生成的platform_device和驱动platform_driver匹配:
- dts文件中节点指定comatible属性,platform_driver设定of_match_table并有一项指定.compatible成员,设备和驱动要能匹配上:
- tips:GPIO通过宏指定地址映射方式:
-
2)设备树节点指定资源后platorm_driver获得资源的方法:
- 通过在设备树节点中添加属性,在驱动程序中通过
of_property_read_u32
获取属性值(即得到相关硬件资源配置值):
- 通过在设备树节点中添加属性,在驱动程序中通过
-
3)调试技巧:通过设备树节点目录查找定义的设备树节点:
- 通过platform_device找到对应platform_driver:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY