转载地址:https://blog.csdn.net/liuhangtiant/article/details/77387583
DM即driver module,也就是驱动模型。
uboot为什么引入驱动模型呢?驱动模型又是一个怎样的一个模型呢?第一个问题很简单,既然uboot要引入驱动模型,那肯定是因为驱动模型要比老旧的驱动方案要好,至于好在哪里,那就必须要先搞清楚第二个问题了。
首先我们先区分两个概念,设备和驱动,也就是device和driver。device持有物理设备的资源信息,而driver实现对设备的管理。
以RTC芯片为例,硬件拓扑如下:
I2C控制器出I2C总线,RTC连在I2C总线上。
RTC对应的device持有RTC的资源信息,包括I2C地址,位宽,这些信息要么是接口相关的,要么是跟硬件设计相关的;而RTC对应的driver则负责对RTC的管理,如将从RTC中读出来的时间值解析为用户可以识别的时间值,以及将时间编码后写入RTC芯片,driver和device结合起来才能实现RTC芯片的访问和管理。
其实RTC的资源信息不止I2C地址和寄存器位宽,还有寄存器定义,那么寄存器定义是否也需要放入device中呢?其实不必,当然放进去也可以。其实硬件设备的资源信息是否要放入device中有一个关键的原则,如果该资源信息影响driver的通用性,就把它放到device中。拿RTC来说,RTC I2C地址是跟硬件设计相关的,不同的硬件设计下I2C地址会不一样,这个信息就需要放在device中,那么针对不同的硬件设备平台,就只需要修改device中的信息即可,而不需要修改driver。寄存器位宽和寄存器定义都是跟硬件设计无关的,完全是RTC自身的参数,所以可以不放在device中,直接在driver中编码即可。其实对于哪些硬件资源信息需要放入device,并没有统一的规则,主要还是看需求而定。
把device和driver区分开以后,就可以正式开撸DM模型了,DM模型有几个关键的概念,把这几个关键概念搞明白就基本了解了DM模型,这几个概念分别是:uclass,device定义
,device和driver绑定,设备层级关系。
uclass
uclass是DM模型的精华所在,uclass代表着一个类,同一类设备属于同一个uclass,拥有相同的uclass ID。还是拿RTC来说事,市面上RTC芯片很多,由不同的厂家生产,其内存寄存器定义甚至访问接口都不一样,所以RTC的driver肯定是不一样的,但是从功能的角度来说,他们都是用来记录时间的,所他们都属于rtc-class。
uclass从层级结构来讲,起到非常好的承上启下的作用,它既能屏蔽具体设备个体间的差异性,向用户提供统一的接口,又能为同一类的设备定义统一的处理函数,具体的设备驱动只需要实现这些处理函数即可,从而简化的设备驱动的开发。
从设备的角度来看,同一类的设备拥有相同的uclass ID,并全部挂在该uclass下。从驱动的角度来看,uclass driver实现通用的处理逻辑。
device定义
device持有设备资源,device的定义方式有三种,通过硬编码的方式或者设备树的方式或者传参的方式。硬编码的方式就是在代码中调用U_BOOT_DEVICE宏来定义设备资源,实际上是一个设备实例;设备树的方式就是将设备描述信息写在对应的DTS文件中,DTS文件被编译成DTB文件,然后跟uboot 二进制合并在一起,uboot启动的时候,会解析DTB文件,将所有的设备描述信息解析出来,以设备树的方式定义设备资源信息是目前比较流行的方案;参数的方式就是通过命令行或者接口将设备资源信息传递进来,非常灵活。
device和driver绑定
通过U_BOOT_DEVICE或者设备树定义的设备资源,实际上代表着一个设备实例,该设备实例必须找到对应的driver才能实现设备管理,为设备实例查找driver的过程其实就是device和driver的绑定过程。那么device和driver如何才能绑定在一起呢?如果是通过U_BOOT_DEVICE定义的设备实例,通过name来进行匹配具有相同名字的driver,如果是通过设备树定义的设备实例,则需要通过compatible来匹配compatible相同的driver。一个device和driver匹配后,就会创建对应的struct udevice结构体,它会同时指向设备资源和driver,这样设备资源和driver就绑定在一起了。
如果是通过命令行或接口将设备资源信息传递进来的话,一般会指定对应的driver跟该设备实例绑定。如sf probe 0:1 100000命令,将总线号,片选,时钟通过命令行传递进去,内部处理逻辑会指定spi_flash_std驱动与该设备实例匹配。