微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 总线设备驱动模型总结

总线设备驱动模型总结

时间:12-01 来源:互联网 点击:
我的环境:

主机开发环境:Fedora14

开发板: TQ2440

编译器: arm-linux-gcc-4.3.2

总线设备驱动模型其实现主要是基于Kobject和sysfs等机制,对于驱动模型程序开发主要是理解三个元素:总线、设备、驱动的关系。三者之间因为一定的联系性实现对设备的控制。

首先是总线,总线是三者联系起来的基础,通过一种总线类型,将设备和驱动联系起来。总线类型中的match函数用来匹配设备和驱动。当匹配操作晚餐之后就会控制驱动程序中的probe函数。

总线设备驱动模型的设计主要包括三个元素的注册,将三个元素加载到内核中,然后通过内核的内部机制将三者联系起来。

首先,总线类型的注册,包括属性文件的添加,总线也是一种设备,也需要将总线设备注册。

其次,完成设备的注册和添加以及对设备添加设备属性文件,同时填充最基本的函数操作。

最后,完成驱动的注册和天极以及对设备驱动添加属性文件,同时填充最基本的函数操作。

1、总线

总线类型是通过结构体bus_type表示的。其源码如下所示:

struct bus_type {

/*总线名*/

const char *name;

/*总线、设备、驱动属性*/

struct bus_attribute *bus_attrs;

struct device_attribute *dev_attrs;

struct driver_attribute *drv_attrs;

/*总线支持的函数操作*/

/*匹配函数,主要用来识别相应的设备和驱动,是两者直接形成关联

用来判断指定的驱动程序能否处理指定的设备

*/

int (*match)(struct device *dev, struct device_driver *drv);

/*在进行热插拔事件之前,为设备配置环境变量操作函数*/

int (*uevent)(struct device *dev, struct kobj_uevent_env *env);

int (*probe)(struct device *dev);

int (*remove)(struct device *dev);

void (*shutdown)(struct device *dev);

int (*suspend)(struct device *dev, pm_message_t state);

int (*suspend_late)(struct device *dev, pm_message_t state);

int (*resume_early)(struct device *dev);

int (*resume)(struct device *dev);

struct dev_pm_ops *pm;

struct bus_type_private *p;

};

其中的int (*match)(struct device * dev, struct device_driver * drv)是必须实现的函数,因为这个函数主要是实现设备和驱动之间的匹配管理。其中匹配的具体逻辑关系需要驱动设计着设定。

int (*uevent)(struct device *dev, char **envp, int num_envp,char *buffer, int buffer_size)则在热插拔事件之前,允许总线为设备添加环境变量。

通常创建一种总线类型的过程中只要完成总线类型结构体的填充,然后完成相应的注册、属性文件创建即可实现总线类型的添加。并不需要对bus_type类型中的所有变量进行赋值,只要将其中的name,bus_attribute,match实现即可。

最后不要忘了总线也是设备,需要将总线设备添加到内核中(注册函数)。

关于总线类型的属性设置,实质上就是完成一个结构体的操作。

如下源码所示:

struct bus_attribute {

/*属性结构体*/

struct attribute attr;

/*属性读操作函数,即显示函数*/

ssize_t (*show)(struct bus_type *bus, char *buf);

/*属性写操作函数,也就是存储到结构体中*/

ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);

};

/*可以通过宏命令定义一个总线结构体,但是需要自己实现属性读写操作函数,如果没有,可设置为NULL*/

/*总线属性定义宏*/

#define BUS_ATTR(_name, _mode, _show, _store)

struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)

/*__ATTR的宏实现如下所示:*/

#define __ATTR(_name,_mode,_show,_store) {

.attr = {.name = __stringify(_name), .mode = _mode },

.show = _show,

.store = _store,

}

由于通常情况下需要查找总线的版本信息,可以将版本信息添加到属性的读属性操作函数中,这样就能显示具体的版本信息。

在宏定义中##是指链接符的作用,相当于将两个部分链接起来,比如bus_attr_##name = bus_attr_name。这是在宏定义中比较常用的定义方式之一。

总线类型的注册和总线类型属性文件创建,以及总线设备的注册主要是依据下面几个函数来实现:

/*总线类型注册函数,由于可能会出错,因此必须对返回值进行检查*/

int __must_check bus_register(struct bus_type *bus);

/*总线类型释放函数*/

void bus_unregister(struct bus_type *bus);

/*总线文件属性创建函数,

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top