当前位置:首页 > 嵌入式 > 嵌入式软件
[导读]Linux设备驱动的难点在于复杂的,庞大的结构。理清楚结构和一个结构与另外结构的关系,以及linux设备驱动的层次性和层次封装抽象性。对于linux设备驱动的结构有点像C++中的类,而层次与抽象有点像继承的关系。

Linux设备驱动的难点在于复杂的,庞大的结构。理清楚结构和一个结构与另外结构的关系,以及linux设备驱动的层次性和层次封装抽象性。对于linux设备驱动的结构有点像C++中的类,而层次与抽象有点像继承的关系。

一、总线、设备、驱动的主要三个结构关系

structbus_type  

---------------------------------

struct bus_type中为devices和drivers准备了两个链表:

struct klist klist_devices

struct klist klist_drivers

struct device

---------------------------------

struct device有两个成员

struct bus_type *bus 记录的是这个设备连在哪条总线上

struct device_driver *driver 记录的是这个设备用的是哪个驱动

struct device_driver

---------------------------------

struct device_driver同样有两个成员

struct bus_type *bus 代表的是这个驱动属于哪条总线

struct klist klist_devices 记录的是这个驱动支持的那些设备,没错,是devices(复数),因为一个驱动程序可以支持一个或多个设备,反过来一个设备则只会绑定给一个驱动程序.

二、总线,设备,驱动的关联

总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每 注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。一个现实的Linux设备和驱动通常都需要挂接在一种总线上。设备与驱动的关联通过总线的match()方法进行匹配,驱动挂载总线时与所有设备进行匹配,设备挂载总线时与所有的驱动进行匹配,所以驱动和设备的挂载无先后之分。匹配成功后会通过调用驱动的probo()方法来初始化设备。

三、总线,设备,驱动的注册

设备与驱动需要挂载在总线上,需要指明驱动与设备是属于哪条总线的,所以设备与驱动需要注册。而总线在linux系统中也是属于设备,所以总线也要注册,同时要先有总线而后才能注册设备和驱动,所以总线要先注册。

总线在linux系统中有俩种,一是实际存在的总线 pci usb 等等,还有一类是虚拟存在的总线 platform ,platform总线主要是用于集成在SoC系统的设备,使得每一个设备都属于一条总线,相应的设备称为platform_device,而驱动成为 platform_driver。linux驱动中platform总线用的非常多,以platform总线说明总线,设备,驱动的注册顺序,注意这里是以先调加设备为例。

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);

}

}

device_attach() 的返回值:

1 设备和驱动匹配成功

0 设备已经注册,但是总线上没有与之相匹配的驱动( 系统启动阶段,由于总线上还没有驱动,所以设备在此匹配不到与之对应的驱动,只是将其添加到总线的设备链表)

-ENODEV 设备没有注册(registered) -- 设备在哪里注册?

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

四、附录linux内核中的platform的几个结构源代码

[cpp] view plain copy

1. // 所在目录:kernel/include/linux/platform_device.h

2. struct platform_device

3. {

4. const char * name;/* 设备名 */

5. u32 id;

6. struct device dev;

7. u32 num_resources;/* 设备所使用各类资源数量 */

8. struct resource * resource;/* 资源 */

9. };

10. // 所在目录:include/linux/ioport.h

11. struct resource

12. {

13. resource_size_t start; /* 资源的开始值 */

14. resource_size_t end; /* 资源的结束值 */

15. const char *name; /* 资源的名字 */

16. unsigned long flags; /* 资源的类型值,如可以是:mem,io,irq,dma等等 */

17. struct resource *parent, *sibling, *child;

18. };

19. // 所在目录:kernel/include/linux/ioport.h

20. struct platform_driver

21. {

22. int (*probe)(struct platform_device *);

23. int (*remove)(struct platform_device *);

24. void (*shutdown)(struct platform_device *);

25. int (*suspend)(struct platform_device *, pm_message_t state);

26. int (*suspend_late)(struct platform_device *, pm_message_t state);

27. int (*resume_early)(struct platform_device *);

28. int (*resume)(struct platform_device *);

29. struct pm_ext_ops *pm;

30. struct device_driver driver;

31. };

32. // 所在目录:include/linux/device.h

33. struct device_driver

34. {

35. char * name;

36. struct bus_type * bus;

37. rwlock_t lock;

38. atomic_t refcount;

39. list_t bus_list;

40. list_t devices;

41. struct driver_dir_entry dir;

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

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

44. int (*suspend) (struct device * dev, u32 state, u32 level);

45. int (*resume) (struct device * dev, u32 level);

46. void (*release) (struct device_driver * drv);

47. };

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭