驱动编写的三种方式:传统/总线/设备树
字符设备驱动程序框架:
如何编写驱动代码
① 确定主设备号,也可以让内核分配
② 定义自己的 file_operations 结构体
③ 实现对应的 drv_open/drv_read/drv_write 等函数,填入 file_operations 结构体
④ 把 file_operations 结构体告诉内核:register_chrdev
⑤ 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数
⑥ 有入口函数就应该有出口函数:卸载驱动程序时,出口函数调用 unregister_chrdev
⑦ 其他完善:提供设备信息,自动创建设备节点:class_create, device_create
我们需要知道什么资料或整体操作步骤是什么?
如何告诉驱动程序引用的是什么那个引脚(传统/总线/设备树):
三者的区别在于如何指定硬件资源。
传统方法:
即在代码中写死,即直接将寄存器地址配置给设备。
LED: 0X......
总线模式:
包含两个文件:
led_drv.c :注册file_operations,初始化结构体。
led_dev.c: 指定引脚
设备树模式:
led_drv.c :注册file_operations,初始化结构体。
jz3440.dts: 指定引脚
三者的区别:
以点亮两个LED的案例来解释:
传统:
首先,写led_drv.c:
分配:allc file_operations.
设置:配置相应的LED操作函数:read/write/open等
注册:
入口函数/出口函数:
但如果是配置两个LED驱动,方法是将前面注册调用的操作复制一遍,将其pin1->pin2。所以,相对编程简单,但是不容易维护,因为新的板子过来需要重新修改led.c的代码
总线模式:
总线将引脚抽出来,单独去配置。
led_drv.c / led_dev.c 将文件挂载在platform总线,led.drv与前面操作相同,不同在于led_dev.c用来指定资源
led_dev.c 会分配/注册一个platform_devices,通过“.resource”来指定引脚。对于不同的board,公用同一led_drc.c。
led-drv.c 分配/设置/注册 platform_driver struct。内包含“probe”, "driver_struct"
probe:分配注册file_operations
设置/注册.....与前面相同
而引脚在platform中被指定,我们在操作GPIO即platform的硬件资源,当borad被修改后,直接修改led_dev.c 的platform中的硬件资源即可。
但是这种方式对于不同的驱动程序,需要注册不同的“resource”,造成代码的冗余,且因为dev为.c文件需要重新编译
设备树:
组成:led_drv.c(与总线相同),设备树文件(*.dts)执行硬件资源
kernel根据*.dts构造platform_dev,在运行时去解析dts文件,来分配/注册一个platform_dev,所以在配置时不需要重新编译,只需要拷贝dts文件即可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)