总线+设备+驱动 (国嵌笔记)

来源:互联网 发布:一元淘宝网 编辑:程序博客网 时间:2024/06/14 07:43
设备模型
1.设备模型元素
总线、驱动、设备
总线是处理器和设备之间的通道,在设备模型中,所有的设备都通过总线相连,设置是内部的虚拟“platform”总线。
在LINUX设备模型中,总线由bus_type结构表示,定义在<linux/device.h>中


总线也是一个设备,也要对应一个struct device

注册
注销
总线属性


创建属性
删除属性


init函数
{ 注册总线bus_register(初始化bus_type结构);创建属性文件bus_create_file()}

bus_type里面有match函数,进行匹配,根据匹配规则进行匹配


通过BUS_ATTR宏进行属性设置


会出现/sys/bus/相应的总线名称/     目录创建总线成功,总线中有使用bus_create_file创建的文件,读取此文件就是总线设置的属性

创建总线完成之后添加设备!!!


向总线中添加设备


1.LINUX中每一个设备用struct device来描述
关键字段
bus_id[BUS_ID_SIZE];//在总线上唯一表示该设备的字符串
struct bus_type *bus;//设备所在总线
struct device_drvier *driver;//管理该设备的驱动
void *driver_data;//该设备驱动使用的私有数据成员


注册
注销
设备属性
device_attribute

创建属性
删除属性

init()
{
初始化设备
struct device//总线体现出关系,具体见下方
注册设备
device_register()
创建属性文件
device_create_file()//通过宏DEVICE_ATTR
}


创建设备的模块
extern struct device my_bus
extern struct bus_type my_bus_type


struct device my_dev={
.bus=&my_bus_type,
···
···
.parent=···
.release=my_dev_release,//一定要定义此函数,相应函数为空也可以
}
创建总线的模块
struct device my_bus={
······
}
struct bus_type my_bus_type={
 ······
}

EXPORT_SYMBOL(my_bus); 
EXPORT_SYMBOL(my_bus_type);


会在相应的/sys/bus/相应总线/devices/下有相应设备



在总线上注册一个驱动


驱动用struct device_driver来描述
关键数据
const char *name;//驱动程序名字(体现在sysfs中)
struct bus_type *bus;//驱动程序所在总线
······
  int (*probe)(struct device* dev);//当匹配成功,调用此函数。也是相应驱动程序的入口


注册
driver_register()
注销


属性
driver_attribute()

init()
{
注册驱动
driver_register()
创建属性文件
driver_create_file()
}

1.总么体现在相应的总线上
2.找到相应处理的设备时,要做什么事情
3.驱动和设备怎么匹配的,通过什么机制匹配的。//在总线上进行设置的。match函数

struct device_driver my_driver={
.bus=&my_bus_type,  //相应的总线
.probe=my_probe,//当匹配成功时要做的事情
.remove=my_remove,
}

加载模块后,总线会调用匹配函数。
只要往总线上添加设备驱动程序或添加设备,总线就会把驱动和设备进行一个一一匹配,找到后进行执行驱动的probe

驱动不可重名
设备可以重名



转载自:http://blog.csdn.net/zhenwenxian/article/details/6437341

Linux关于总线、设备、驱动的注册顺序

        设备挂接到总线上时,与总线上的所有驱动进行匹配(用bus_type.match进行匹配),
         如果匹配成功,则调用bus_type.probe或者driver.probe初始化该设备,挂接到总线上
         如果匹配失败,则只是将该设备挂接到总线上。
+----> devices
|
|
|
-----------------------------------------------------------------------------
struct bus_type    match() probe()
-----------------------------------------------------------------------------
|
|
|
+----> drivers     probe()
         驱动挂接到总线上时,与总线上的所有设备进行匹配(用bus_type.match进行匹配),
         如果匹配成功,则调用bus_type.probe或者driver.probe初始化该设备;挂接到总线上
         如果匹配失败,则只是将该驱动挂接到总线上。

需要重点关注的是总线的匹配函数match(),驱动的初始化函数probe()

 

1. platform_bus_type--总线先被kenrel注册。

2. 系统初始化过程中调用platform_add_devices或者platform_device_register,将平台设备(platform devices)注册到平台总线中(platform_bus_type)
3. 平台驱动(platform driver)与平台设备(platform device)的关联是在platform_driver_register或者driver_register中实现,一般这个函数在驱动的初始化过程调用。

通过这三步,就将平台总线,设备,驱动关联起来。

1. platform bus先被kenrel注册。
------------------------------------------------------
do_basic_setup() -->-driver_init() -->-platform_bus_init()-->bus_register()


2. 系统初始化过程中调用platform_add_devices或者platform_device_register,将平台设备(platform devices)注册到平台总线中(platform_bus_type)
------------------------------------------------------
系统启动阶段,总线的驱动链表还是空的,所以启动阶段的platform_add_devices()只负责将设备添加到总线的设备链表上。

linux-2.6.26/drivers/base/platform.c
int platform_add_devices(struct platform_device **devs, int num)
{
----...
----ret = platform_device_register(devs[i]);
----...
}

int platform_device_register(struct platform_device *pdev)
{
----device_initialize(&pdev->dev);
----return platform_device_add(pdev);
}

int platform_device_add(struct platform_device *pdev)
{
----...
----pdev->dev.bus = &platform_bus_type;
----...
----ret = device_add(&pdev->dev);
----...
}

device_add() -->-bus_attach_device()

void bus_attach_device(struct device *dev)
{
----struct bus_type *bus = dev->bus;
----int ret = 0;

----if (bus) {
--------if (bus->p->drivers_autoprobe)
------------ret = device_attach(dev);
--------WARN_ON(ret < 0);
--------if (ret >= 0)
------------klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
----}
}

 

如果设备和驱动匹配成功;或者设备已经注册,但是总线上没有与之相匹配的驱动,bus_attach_device()将调用klist_add_tail()将设备添加到总线的设备链表尾部。

0 0
原创粉丝点击