Linux的总线设备驱动模型
裸机编写驱动比较自由,按照手册实现其功能即可,每个人写出来都有很大不同;
而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的总线设备驱动模型的更多相关文章
- Linux中总线设备驱动模型及平台设备驱动实例
本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...
- Linux I2C总线设备驱动模型分析(ov7740)
1. 框架1.1 硬件协议简介1.2 驱动框架1.3 bus-drv-dev模型及写程序a. 设备的4种构建方法a.1 定义一个i2c_board_info, 里面有:名字, 设备地址 然后i2c_r ...
- Linux学习 : 总线-设备-驱动模型
platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver.Linux 2.6的设备驱动模型中,把I2C.RTC.LCD等都归纳为pl ...
- usb驱动开发4之总线设备驱动模型
在上文说usb_init函数,却给我们留下了很多岔路口.这次就来好好聊聊关于总线设备驱动模型.这节只讲理论,不讲其中的函数方法,关于函数方法使用参考其他资料. 总线.设备.驱动对应内核结构体分别为bu ...
- 总线设备驱动模型---platform篇
总线设备驱动模型----驱动篇 http://blog.chinaunix.net/uid-27664726-id-3334923.html http://blog.chinaunix.net/uid ...
- 芯灵思SinlinxA33开发板 Linux平台总线设备驱动
1.什么是platform(平台)总线? 相对于USB.PCI.I2C.SPI等物理总线来说,platform总线是一种虚拟.抽象出来的总线,实际中并不存在这样的总线. 那为什么需要platform总 ...
- Linux总线设备驱动模型
1. Linux2.6内核引入总线.设备.驱动模型来描述各种总线(PCI.USB.I2C.SPI)与外围设备及其驱动之间的关系. 2. 在Linux内核中,总线用bus_type结构来描述,定义于文件 ...
- Linux平台总线设备驱动
1. 平台总线(Platform bus)是linux2.6内核加入的一种虚拟总线,其优势在于采用了总线的模型对设备(没有挂到真实总线的设备)与驱动进行了管理,这样提高了程序的可移植性. 2. 平台总 ...
- Linux下 USB设备驱动分析(原创)
之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...
随机推荐
- 用Java模拟实现对系统文件以目录的拷贝功能
要用Java对单个文件拷贝的话,其实思路很简单,循环读取被拷贝文件,放入byte数组,然后写入目标文件.当然我们也可以借助现有的类去完成,如InputStream中的transferTo()方法就可以 ...
- Scala中实现break与continue
Scala是函数式编程语言,因此没有直接的break与continue关键字,要实现break与continue效果,需要绕一下. 需要导入包: import util.control.Breaks. ...
- 通过shell脚本统计elasticsearch indices每天的数量以及大小
前情提要: 最近elasticsearch集群总出问题,之前虽然修复了,现在又出现新的问题,于是PM要求拉取elasticsearch每天建立的索引有多少,索引有多大,需要对机器进行评估 客户现场无法 ...
- 面向对象—继承(Day19)
初识继承 继承是一种创建新类的方式,在python中新类可以继承一个或多个父类,父类又可称为基类或超类,新建的类为派生类或子类.(类与类之间的关系是什么是什么的关系.) 继承语法: class Par ...
- 关于TP90 TP99 等常用于评估软件系统的处理性能的指标概念
工作中还是蛮少直接接触到评估系统性能的,但是不妨碍有兴趣了解.认为这是常识,只是个人才疏学浅不了解其定义. TP=Top Percentile,Top百分数,是一个统计学里的术语,与平均数.中位数都是 ...
- libc++abi.dylib: terminating with uncaught exception of type NSException
这是微信sdk注册时候报的错误 解决方法 选择Build Setting,在"Other Linker Flags"中加入"-Objc -all_load"
- VS Code 在线运行:code-server部署(系列一)
偶然间发现VS Code可以在线运行,闲来无事部署了一套试试效果,先上图,是不是很熟悉的感觉,初步体验基本跟本地运行效果一样. 进入正题 首先要准备一套linux环境,环境配置最低是1G内存.2核CP ...
- Rust所有权及引用
Rust 所有权和借用 Rust之所以可以成为万众瞩目的语言, 就是因为其内存安全性. 在以往内存安全几乎全都是通过GC的方式实现, 但是GC会引来性能.CPU以及Stop The World等问题, ...
- ssh远程端口转发&&windows系统提权之信息收集&&网安工具分享(部分)
一.ssh远程端口转发 背景:当我们在渗透过程中,获取到内网的一台仅有内网IP的服务器后,我们可以通过ssh隧道,将内网某个主机的端口进行远程转发 1.网络拓扑图 假设获取的服务器为web服务器,we ...
- Web应用程序攻击和检查框架w3af
实验目的 利用w3af爬虫插件探测出目标网站的目录结构. 实验原理 1) W3AF是一个web应用安全的攻击.审计平台,通过增加插件来对功能进行扩展.这是一款用python写的工具,可以查看所有源代码 ...