总线设备驱动模型的极简框架

分离:把硬件相关的东西抽出来;把相对稳定的软件部分抽出来。
分层:input.c 向上提供统一给 APP 操作的统一接口。每一层专注于自已的事件。
在这里插入图片描述

一边的“device”结构体和另一边的“较稳定的 drivice 代码”的联系:
“device_add()”除了将“devcie”结构放到 bus 的“dev 链表”之外,还会从另一边的“drv”
链表中取表元即某个“driver”结构,用总线里的一个(.match)函数来作比较,看另一边的
“driver”是否支持一边的“device”。若是能够支持,则接着调用软件驱动部分的“.probe”
函数。
“driver_register()“会将“bus_drv_dev”模型中的较稳定代码“driver”结构体放到虚拟总线的
某个链表(drv 链表)中。从另一边的“dev”链表中取出每一个“device”结构用 bus 中的
“.match”函数来作比较,若支持则调用“.probe”函数。
“只不过”左右两个注册建立起来的一种机制。在“.probe”函数中做的事件由自已决定,
打印一句话,或注册一个字符设备,再或注册一个“input_dev”结构体等等都是由自已决定。
强制的把一个驱动程序分为左右两边这种机制而已,可以把这套东西放在任何地方,这里的
“driver”只是个结构体不要被这个名字迷惑,“device”也只是个结构体,里面放什么内容
都是由自已决定的。
第一部分:简单框架搭建
首先,写“平台设备”:
Led_dev.c 设备部分:
1,定义平台设备:
1.1,分配、设置、注册一个 platform_device 结构体。
led_resource主要包含哪个寄存器;
LED的寄存器起始地址:
gpfcon = (volatile unsigned long *)ioremap(0x56000050,16);
LED寄存器结束地址:gpfdat = gpfcon + 1;
以及内存资源。
在这里插入图片描述
1.2,入口函数:注册一个平台设备
在这里插入图片描述
1.2.1,看注册平台设备的过程:
platform_device_register (&led_dev);
–>platform_device_add(pdev);
–>device_add(&pdev->dev); 将device放到平台总线的“dev”链表中去。
1.3,出口函数:卸载平台设备
在这里插入图片描述
1.4,修饰出入口函数:
在这里插入图片描述
以上便写好了平台设备部分代码。
接着写“平台驱动”:
2.1, 定义平台驱动:
2.1.1,分配、设置、注册一个 platform_driver 结构体。定义一个平台驱动.因为平台总线的.match 函数比较的是"平台设备"和"平台驱动"的名字.所以两边名字要相同这样才会认为这个 drv 能支持这个 dev。才会调用平台驱动里面的”.probe"函数。
在这里插入图片描述
2.2,构造平台驱动结构中的“.probe”函数:
2.2.1,平台驱动结构中的”.probe"函数.这个函数是自已按照自已的要求写的。首先、根据 platform_device 的资源进行 ioremap,其次、注册字符设备驱动程序
在这里插入图片描述
2.3,构造平台驱动结构中的“.remove”函数:做与“.probe”相反的事件。首先、根据 platform_device 的资源进行 iounmap。其次、卸载字符设备驱动程序
在这里插入图片描述
2.4,入口函数:注册一个台平台驱动。
在这里插入图片描述
2.5,出口函数:卸载平台驱动。
在这里插入图片描述
2.6,修饰出入口函数:
在这里插入图片描述
进行编译加载
在这里插入图片描述
单板挂接 NFS 文件系统:
注册"led_platform_drv.ko":
在这里插入图片描述
这时候 insmod led_platform_dev.ko 后没有任何输入,是因为只是把平台驱动结构放到了 bus
平台总线的“drv”链表中。而此时另一边的“设备链表”中还没有同名的“device”。接着
再注册“led_platform_dev.ko”
在这里插入图片描述
卸载时,就会打印“platform_driver led_drv”结构的“.remove = led_remove”函数:
platform_driver led_drv->(.remove = led_remove)
–>int led_remove(struct platform_device *pdev)
–>printk(“led_remove, remove led\n”);
卸载是“void led_drv_exit(void)”
–>platform_driver_unregister (&led_drv);
–>driver_unregister(&drv->driver);
–>bus_remove_driver(drv);
卸载是从平台总线的“derive”链表上取下注册上的平台设备结构,根据设备的“同名名字”
找到“平台驱动”层之前相对应的“平台驱动结构”,调用里面的“.remove”函数。
卸载时出错:提示为没有“release()”函数。
在这里插入图片描述
平台设备 结构体定义中有一个“device”结构,这个“device”结构在“device.h”中定义:
其中有定义“void (*release)(struct device * dev);”。我们要提供这个 relase 函数,这里
什么都不用做。以后可以放一些硬件相关的到里面。这个例子里暂时不做任何事情。
修改代码如下:
在这里插入图片描述
重新注册“dev.ko”后,是将一个平台设备结构注册到平台总线下的“平台设备”链表,这
时另一方“平台驱动”通过“设备名”匹配到一个“平台驱动”结构后,调用此结构下的“.probe”
函数,为这个“平台设备”作相关的处理;当“insmod xx_dev.ko”后,是从“平台设备”
结构链表中删除了 这个“xx_dev.ko”,这时另一端相关同名的“平台驱动”就调用自已结构
中的“.remove”函数作相关清理工作。
在这里插入图片描述
第二部分:实用代码填充
2.1在“.probe”函数中做有意义的事情:注册字符设备。定义主设备号并构造一个 file_operations 结构体
在这里插入图片描述
2.2创建‘类,让系统自动创建‘设备节点
在这里插入图片描述
2.3根据 platform_device 的资源进行 ioremap。获得资源: led_dev中有IORESOURC_MEM 内存资源, IERSOURCE_IRQ中断资源。
在这里插入图片描述
2.4file_operations led_fops 结构中的 open 函数的处理。open 后要把这些引脚配置成“输出”引脚。
在这里插入图片描述
2.5file_operations led_fops 结构中的 write 函数的处理。open 后要把这些引脚配置成“输出”引脚。在这里插入图片描述
2.6出口函数的完善。首先,卸载平台驱动。其次,在cls类下面创建设备,则要卸载掉类设备。接着,去掉类、卸载字符设备、"iounmap()"卸载
在这里插入图片描述
最后进行测试:
在这里插入图片描述
这两个头文件要包含。
在这里插入图片描述
接着再编译再装载:
在这里插入图片描述
要是想测试其他 LED 的情况,则修改“led_dev.c”中的引脚资源而“led_drv.c”就可以保持不动。
在这里插入图片描述
总结:分层是每一层专注做自已的事情。分离经常使用的就是“bus_drv_dev 模型”中,这个模型只是提供一种机制,在这个机制中做什么事件是由自已定义的,在“.probe”函数中的操作完全 是由自已决定的(.probe 中的操作是核心内容)。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值