裸机编写驱动比较自由,按照手册实现其功能即可,每个人写出来都有很大不同;

而Linux中还需要按照Linux的驱动模型来编写,也就是需要按照“模板”来写,写出来的驱动就比较统一。

一、 Linux采用总线设备驱动模型。主要包含总线、设备、驱动三个部分。

总线:最先注册,有几个重要的回调函数,例如match函数用于匹配device和driver。

设备:设备的物理信息,例如设备名、物理地址、中断号等;

驱动:设备的驱动程序和设备名等信息,例如初始化函数、波特率设置函数、启动停止函数、中断函数等。

现实中,很多设备都是接在总线上的,例如SPI Flash接在SPI总线上,EEPROM接在I2C总线上。

但也有很多芯片内部设备没有挂在总线上,例如UART、SPI控制器。为了统一使用Linux总线设备驱动模型,内核中定义了一个虚拟总线 platform_bus_type,将这些设备(叫做平台设备)注册到该虚拟总线上统一管理。

二、Linux驱动注册顺序(总线、设备、驱动三者关系)

1、注册总线 xxx_bus_type:

在系统初始化阶段,会首先向内核注册各种常用的总线类型,比如pci, usb, spi, i2c, platform等等。

有两个重要的链表挂在bus上,一个是设备device链表,一个是驱动driver链表。

它包含的最关键的函数:match()用于匹配device和driver。

//例子:
static int __init spi_init(void)
{
int status; printk("@@ spi_init :spi_bus_type\n");
buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
if (!buf) {
status = -ENOMEM;
goto err0;
} status = bus_register(&spi_bus_type);
if (status < 0)
goto err1; status = class_register(&spi_master_class);
if (status < 0)
goto err2;
return 0; err2:
bus_unregister(&spi_bus_type);
err1:
kfree(buf);
buf = NULL;
err0:
return status;
}

2、注册设备:将系统设备注册进内核的对应总线上,大多是调用xxx_device_regisger注册。

(xxx_device_regisger:将自己加到xxx总线的device链表,然后使用总线bus匹配对应的driver )

3、注册驱动:将系统设备的driver注册进内核的对应总线上:大多是调用xxx_drvier_register()注册。

(xxx_drvier_register:将自己加到xxx总线的driver链表,然后使用总线bus匹配对应的device )

2和3很多是在同一个函数中注册的,所以一起举例:

例子1:
platform_driver_register(&uart_driver); //将uart的driver注册到platform_bus上;
platform_device_register(&uart_device); //将uart的device注册到platform_bus上; 例子2:
SPI Master控制器:drivers/spi/my_spi_master.c
platform_device_register(&dw_spi0_device); //注册device
platform_driver_probe(&dw_spi0_driver, dw_spi0_probe); //1、注册driver
//2、spi_new_device子函数会注册SPI Flash的device到spi总线上;
//3、这里实现Master和Flash的绑定,即flash要使用哪个控制器控制; 例子3:
SPI Flash:drivers/mtd/gd25q_spi.c
spi_register_driver(&spi_flash_drv); //注册SPI Flash的driver到spi总线 上面几个例子的device和driver都成功注册后,对应总线的match回调函数会成功匹配driver和device,
并调用driver的probe函数完成设备初始化。 可以看到,不同设备的device和driver注册位置可能不同、注册顺序可能不同、注册函数名可能不同!!

4、设备和驱动的匹配:

老版内核的匹配大部分是看device和driver的name属性是否相同;新版使用设备树的内核中,是根据程序中driver的compatible 与设备树节点的compatible 是否相同来匹配!

match的工作是由总线(bus)来完成。

在xxx_device_register()或xxx_drvier_register(),即设备或驱动注册的时候,都会引发总线调用自己的match函数来寻找是否挂载有与该设备(或驱动)名字匹配的驱动(或设备);

如果只注册了设备或者只注册了驱动,总线会判定匹配失败,则暂时不会调用driver中的probe函数进行初始化等操作; 要等到设备、驱动都注册成功并匹配绑定后才会调用。

Linux的总线设备驱动模型的更多相关文章

  1. Linux中总线设备驱动模型及平台设备驱动实例

    本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...

  2. Linux I2C总线设备驱动模型分析(ov7740)

    1. 框架1.1 硬件协议简介1.2 驱动框架1.3 bus-drv-dev模型及写程序a. 设备的4种构建方法a.1 定义一个i2c_board_info, 里面有:名字, 设备地址 然后i2c_r ...

  3. Linux学习 : 总线-设备-驱动模型

    platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver.Linux 2.6的设备驱动模型中,把I2C.RTC.LCD等都归纳为pl ...

  4. usb驱动开发4之总线设备驱动模型

    在上文说usb_init函数,却给我们留下了很多岔路口.这次就来好好聊聊关于总线设备驱动模型.这节只讲理论,不讲其中的函数方法,关于函数方法使用参考其他资料. 总线.设备.驱动对应内核结构体分别为bu ...

  5. 总线设备驱动模型---platform篇

    总线设备驱动模型----驱动篇 http://blog.chinaunix.net/uid-27664726-id-3334923.html http://blog.chinaunix.net/uid ...

  6. 芯灵思SinlinxA33开发板 Linux平台总线设备驱动

    1.什么是platform(平台)总线? 相对于USB.PCI.I2C.SPI等物理总线来说,platform总线是一种虚拟.抽象出来的总线,实际中并不存在这样的总线. 那为什么需要platform总 ...

  7. Linux总线设备驱动模型

    1. Linux2.6内核引入总线.设备.驱动模型来描述各种总线(PCI.USB.I2C.SPI)与外围设备及其驱动之间的关系. 2. 在Linux内核中,总线用bus_type结构来描述,定义于文件 ...

  8. Linux平台总线设备驱动

    1. 平台总线(Platform bus)是linux2.6内核加入的一种虚拟总线,其优势在于采用了总线的模型对设备(没有挂到真实总线的设备)与驱动进行了管理,这样提高了程序的可移植性. 2. 平台总 ...

  9. Linux下 USB设备驱动分析(原创)

    之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...

随机推荐

  1. MySQL时间格式TIMESTAMP和DATETIME的区别

    时区,timestamp会跟随设置的时区变化而变化,而datetime保存的是绝对值不会变化 自动更新,insert.update数据时,可以设置timestamp列自动以当前时间(CURRENT_T ...

  2. HGAME-week2-web-wp

    hgame第二周总结 1.webpack-engine 我不懂,但是真的刚打开就出来了,一脸懵逼(wp说是sourcemap没关 hgame{D0nt_f0r9et_2_ClOs3_S0urce_m@ ...

  3. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  4. CVE-2021-33739 EOP漏洞分析

    背景   CVE-2021-33739是一个UAF漏洞,成因是由于在对象CInteractionTrackerBindingManagerMarshaler与对象CInteractionTracker ...

  5. 练习推导一个最简单的BP神经网络训练过程【个人作业/数学推导】

    写在前面   各式资料中关于BP神经网络的讲解已经足够全面详尽,故不在此过多赘述.本文重点在于由一个"最简单"的神经网络练习推导其训练过程,和大家一起在练习中一起更好理解神经网络训 ...

  6. 手把手教你把 Git 子模块更新到主项目

    本文以 skywalking-rocketbot-ui子模块合并到 skywalking 为例,手把手教你如何把 Git 子模块更新到主项目中去. 首先,把fork的skywalking项目克隆到本地 ...

  7. NSSCTF-gift_pwn

    最近才开始接触"pwn"这个东西,这是近两天做的一个题目,然后就想着记一下. 好的,步入正题, 直接nc连接返回空白,然后直接退出,用kali的checksec工具或者是die检测 ...

  8. scrapy爬取youtube游戏模块

    本次使用mac进行爬虫 mac爬虫安装过程中出现诸多问题 避免日后踩坑这里先进行记录 首先要下载xcode ,所以要更新macOS到10.14.xx版本 更新完之后因为等下要进行环境路径配置 但是ma ...

  9. 在 Linux 下确认 NTP 是否同步的方法

    NTP 意即网络时间协议Network Time Protocol,它通过网络同步计算机系统之间的时钟.NTP 服务器可以使组织中的所有服务器保持同步,以准确时间执行基于时间的作业.NTP 客户端会将 ...

  10. Map<String, String> map按key值排序

    private static String buildMd5Params(Map<String, String> map) { StringBuilder result = new Str ...