代码由gitee托管
https://gitee.com/maziot-samsung/jz2440v3.drivers/tree/master/platform_dev_dri
问题:在第一个驱动程序LED中,如果我们修改了硬件。将LED连接到其他的某个引脚,或者改变LED的点亮电平。那么我们都要对整个驱动程序修改源代码重新编译和insmod。由于LED相对简单,修改起来还不是太麻烦。如果是其他的驱动修改起来可能会很麻烦,还容易出错,因此想出了一种新的写法,分离分层。
解决方法:将驱动程序分成两部分写。即设备和驱动。在上面那个问题中,如果我们修改了硬件。只需要修改设备部分即可,因为驱动还是一样的,本质上还是一个LED驱动,驱动部分是可以不修改的。
先看下devices部分的代码 在入口函数中调用platform_device_register 注册一个平台设备 led_dev 中包含名字(名字很重要)资源,资源中包含的就是具体LED连接的某个pin的寄存器地址,同时注意led_release函数可以为空但必须有。devices非常简单,当遇到前面的问题时只要更改资源中的寄存器地址就可以了。
再来看下driver部分的代码 在入口函数中调用platform_driver_register 注册一个平台驱动led_drv中包含名字、probe和remove。在Linux机制中,当注册一个平台设备时,就会将此平台设备挂载到一条设备链表中,平台驱动也一样。同时注册完毕之后会去另一条链表中搜索,根据名字相匹配。(所以说名字非常重要,要是写错了就匹配不到了)当匹配成功时就会调用驱动函数的probe函数,同理当卸载的时候会调用remove函数。probe函数首先调用platform_get_resource以获取平台设备中的资源。拿到资源后映射IO口然后注册一个字符设备,注意:字符设备的核心依然是file_operations结构体。只不过原来注册字符设备是在入口函数,而现在放到了probe函数中而已。平台设备总线模型只是一种比较特殊的写法,意在分离分层,解耦,个人感觉和MVC有异曲同工之妙。
当然这种写法可以说非常好,但是还是有一定的确定,比如还是要重新编译设备那部分,对于那种直接编进内核种的代码来讲还要重新烧录内核。所以后面又开发了一种新的方法设备树,设备树可以不用重新编译内核。只需要重新编译设备树文件生成新的dtb重新开机加载就可以了。设备树的具体笔记后面在做分析