platform模型

原始字符设备注册过程

1、分配cdev结构体内存cdev_alloc()
2、分配设备号register_chrdev_region() 动态自动申请alloc_chrdev_region()
3、初始化字符设备cdev_init()
4、将字符设备设备添加进内核cdev_add()
5、实现字符设备操作函数集(内部都是函数指针) read、write、open、close、ioctl
6、设备注销 cdev_del删除cdev设备管理结构体,使用unregister_chrdev_region()释放字符设备号
7、指定字符设备的入口和出口module_init()、module_exit()与insmod命令和rmmod命令相联系

platform模型
  • 使用的液晶屏,可能液晶屏控制器五花八门,但是其接口无非就是LVDS、MIPI、8080、SPI、I2C、RGB等。很多时候我们不需要自己去为每个设备写一个驱动,显然驱动是可以共用一套的,
  • *platform驱动模型将设备抽象为总线上的节点
  • *该模型将将整个驱动主要分为三个部分,总线platform_bus(内核自带很多)、驱动platform_driver、设备platform_device
  • *platform驱动模型最大的好处就是可以让一个驱动可以与多个设备绑定,即时多个设备可以用一个驱动
  • *在此驱动模型之下,产生了各种子系统pinctrl子系统、spi子系统、i2c子系统、scsi子系统、alsa子系统、input子系统、tty子系统等等。这些子系统使得这驱动模型变得规范化和流程化
未引入dts时

设备和驱动是两个独立的驱动,因此这两套代码都有 module_init 和 module_exit宏。不管是驱动还是设备的注册,他们都会去尝试匹配相应的驱动或者设备,即我们不需要担心谁先后注册的问题。

驱动注册步骤:
1、申请一个platform_driver结构体,该结构体是我们的驱动注册和注销时候使用的.内部含有led_probe和led_remove函数和匹配设备的选项

2、对申请的platform_driver结构体,其中包含的内容选项需要去初始化和定义比如probe匹配函数(申请设备结构体、申请设备号、初始化owner、注册内核、创建类、设备,硬件相关资源)与remove注销函数(删除设备结构体、注销设备号、删除设备节点、类、取消映射)

3、定义module_init里面是注册驱动platform_driver_register(platform_driver结构体),定义module_exit里面是注销驱动platform_driver_unregister(platform_driver结构体)。

4、指定模块入口和出口module_init(led__driv_init)、module_exit(led_driv_exit);
*Linux将驱动和设备分离的主要目的就是希望硬件和软件能够独立,这样修改硬件的时候就不用修改软件,就是当硬件设备发生变化时,我们需要修改设备代码,而无需修改驱动代码

设备注册步骤:
1、申请设备结构体platform_device结构体(name与驱动名匹配、id、num_resources设备资源数、resource资源结构体(包含主要寄存器的地址)、dev指定设备相关的描述)

2、对定义的结构体里面的内容进行初始化和定义

3、定义module_init里面是注册驱动platform_device_register(platform_device结构体),定义module_exit里面是注销驱动platform_device_register(platform_device结构体)

4、指定模块入口和出口module_init(led_dev_init)、module_exit(led_dev_exit);

引入dts时:

从上面可以看到设备代码完全可以被设备树替代。而且设备树完成的更好(这是内核这个大功臣解析设备树,解析成功后将其生成device_node并加入到设备节点树上,之后内核又会将device_node转换为platform_device,同时内核会将这个platform_device注册到platform_bus总线上) 解放双手,无需自己写platform_device代码

对于内核不是所有的设备树节点转为platform_device,满足以下要求:
1、该节点必须包含compatible属性
2、该节点必须包含interrupt类型属性
该节点为根节点的子节点(不过有一种情况需要非常注意,当根节点的子节点其 compatible 属性为"simple-bus"、“simple-mfd”、“isa”、"arm,amba-bus"时,该节点的一级子节点将会被注册为 platform_device 设备。)

*一堆分析之后我们已经知道我们已经**不需要再去申请platform_device去定义初始化以及之后的注册。**我们现只需要关心如何去注册platform_driver==>因此导致platform_的注册也发生了变化。

在这里插入图片描述
在这里插入图片描述
引入设备树之后,probe和remove函数这不用多说,但是driver多了一个led_match_table(用来匹配设备树中节点的compatible属性的),以及多了一个**.id_table(用来告诉驱动可以匹配多个设备)但是一般就.name来匹配,一旦匹配成功就直接触发probe函数进行注册驱动**

驱动注册步骤:
1、在设备树里面添加设备的节点(寄存器以及引脚信息)

2、定义一个驱动结构体platform_driver

3、老样子我们需要继续进行结构体里面的函数probe和remove函数以及driver结构体哥id_table初始化
*这里对probe函数的编写(申请设备结构体、申请设备号、初始化结构体中的THIS_MODULE与初始化桥梁、将设备添加到内核中、创建一个类和创建一个设备、硬件初始化【取设备树的寄存器的信息】ioremap映射)
*这里对remove函数编写(取消映射、删除设备结构体、注销设备号、删除设备节点与设备类)
*file_operations结构体实现led_ops = { .owner = THIS_MODULE, .open = led_open, .read = led_read,.write = led_write,release = led_close}在对里面函数实现(核心)
*id_table结构体定义static struct of_device_id led_match_table[ ]={{.compatible = “lite200,led”,}, };

4、指定模块的入口和出口。
led_driver_init(){内部是platform_driver_register(设备结构体)}
Led_driver_exit(){内部是platform_driver_unregister(设备结构体)}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栋哥爱做饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值