目录
- 1. Linux驱动的分离与分层
- 1.1 为什么要进行Linux驱动的分离与分层
- 1.2 Linux驱动的分层
- 2. 驱动-总线-设备
- 2.1 总线
- 2.2 驱动
- 2.3 设备
- 3. platform平台设备总线
- 3.1 platform总线注册
- 3.2 platform驱动
- 3.3 platform设备
1. Linux驱动的分离与分层
1.1 为什么要进行Linux驱动的分离与分层
便于驱动的移植,例如IIC通信协议是不变的,那么如果换一个平台换一个芯片就写一套IIC驱动这显然是不合算的,因为如果工程量大起来的话一改就是整个项目的重构这样驱动的利用率和可重塑性就太差了.示意图如下;
1.2 Linux驱动的分层
网络有七层,每个层面处理不同的信息,对于Linux系统而言,其也需要分层的,简要说明一下Linux分层归类,input子系统负责管理所有和输入有关的驱动,包括键盘、鼠标、触摸等,最底层的就是设备的原始驱动,负责获取输入设备的原始值,获取到的输入事件上报给input核心层。input核心层会处理各种IO模型,并且提供file_operations操作集合。我们在编写输入设备驱动的时候只需要处理好输入事件的上报即可,至于如何处理上报的输入事件是上层去考虑的事情,我们不用管。因此可以看出来借助分层模型可以极大的简化对驱动的编写,对于驱动的编写非常的友好.
2. 驱动-总线-设备
根据驱动的分离与分层衍生出了总线-驱动-设备的驱动框架。总线的代码是由内核给出的我们不需要编写,需要我们编写的部分是驱动和设备。当向总线注册的时候,总线会从现有的设备中查找看看哪个设备和此驱动匹配,同理,当向总线注册设备的时候总线也会在现有的驱动中查看与之匹配的驱动.
2.1 总线
总线的数据类型为:bus-type。向内核注册总线使用
bus_register
2.2 驱动
驱动的数据类型为:device-driver。向内核注册驱动使用:
deiver_register
向总线中注册驱动的时候,会检查当前总线下的所有设备,有没有与此驱动匹配的设备,如果有的话,驱动和设备匹配后驱动里面的probe函数就会执行.
2.3 设备
当向总线中注册设备的时候,设备数据类型为:struct device
注册函数为:
device_register()
3. platform平台设备总线
根据设备-驱动-总线模型,IIC,SPI,USB这样的实实在在的总线是完全匹配的,但是一些例如定时器、RTC、LCD等无法归结为一类具体的总线,因此Linux内核创造了一个虚拟的总线:platform总线
- 方便开发,Linux提出了驱动的分离与分层
- 进一步引出了驱动-总线-设备驱动模型,或者框架
- 对于SOC内部的RTC,timer等不好归类的具体总线,有一个虚拟的platform总线。
3.1 platform总线注册
plotform_bus_init->bus_register()
注册的内容就是:
struct bus_type_bus_type={
.name="paltform",
dec_groups=paltform_dev_groups,
.match=paltform_match,
.uevent=paltform_uevent,
.pm=&platform_dev_pm_ops,
}
3.2 platform驱动
struct platform_driver
:
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
bool prevent_deferred_probe;
};
其中比较重要的函数是:int (*probe)(struct platform_device *);
3.3 platform设备
当不使用设备树时要向总线注册paltform设备,当有设备树时就不用再注册设备了,因为启动内核时会自动解析设备树添加对应的设备,因此只需要注册驱动即可,同时当驱动和设备进行成功匹配时就会执行对应的prob函数.