总线、设备、驱动

83 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 31 天,点击查看活动详情

一、总线、设备、驱动

硬编码式的驱动开发带来的问题:

  1. 垃圾代码太多
  2. 结构不清晰
  3. 一些统一设备功能难以支持
  4. 开发效率低下

1. 初期解决思路:设备和驱动分离

image.png

struct device来表示一个具体设备,主要提供具体设备相关的资源(如寄存器地址、GPIO、中断等等)。

struct device_driver来表示一个设备驱动,一个驱动可以支持多个操作逻辑相同的设备。

带来的问题-------怎样将二者进行关联(匹配)?

硬件上同一总线上的设备遵循一致的时序通信,在其基础上增加管理设备和驱动的软件功能;于是引入总线(bus),各种总线的核心框架由内核来实现,通信时序一般由SOC供应商支持。

内核中用struct bus_type来表示一种总线,总线可以是实际存在的总线,也可以是虚拟总线:

  1. 实际总线:提供时序通信方式 + 管理设备和驱动

  2. 虚拟总线:仅用来管理设备和驱动(最核心的作用之一就是完成设备和驱动的匹配)

理解方式:

设备:提供硬件资源——男方

驱动:提供驱动代码——女方

总线:匹配设备和驱动——婚介所:提供沟通机制,完成拉郎配

整体的一个思路就是:先开发硬件模块,再开发驱动模块,最后建立一种关系将两者结合起来。

2. 升级思路:根据设备树,在系统启动时自动产生每个节点对应的设备

初期方案,各种device需要编码方式注册进内核中的设备管理结构中,为了进一步减少这样的编码,引进设备树。

二、基本数据类型

1. struct device

struct device 
{ 
     struct bus_type *bus; //总线类型 
     dev_t devt; //设备号 
     struct device_driver *driver; //设备驱动 
     struct device_node *of_node;//设备树中的节点,重要 
     void (*release)(struct device *dev);//删除设备,重要 
     //....... 
};

2. struct device_driver

struct device_driver 
{ 
     const char *name; //驱动名称,匹配device用,重要
     struct bus_type *bus; //总线类型 
     struct module *owner; //模块THIS_MODULE 
     const struct of_device_id *of_match_table;//用于设备树匹配 
     struct of_device_id对象地址) 重要 
     //......
}    
struct of_device_id 
{ 
    char name[32];//设备名 
    char type[32];//设备类型 
    char compatible[128]; //用于device和driver的match,重点 
}; 
//用到结构体数组,一般不指定大小,初始化时最后加{}表示 数组结束