linux 设备与驱动模型 您所在的位置:网站首页 linux驱动调用 linux 设备与驱动模型

linux 设备与驱动模型

2023-03-28 16:15| 来源: 网络整理| 查看: 265

抽象出device model的必要性

Linux kernel运行在不同架构的硬件平台上,需要最大限度的在不同平台上复用代码。比如我们将同一个USB 设备驱动用于一个x86 平台或者是一个arm 平台,即使在这两个平台上的USB 控制器是不同的。这需要一个干净的具有统筹性的代码组织,使设备驱动与控制器驱动分离、硬件描述(dts)与驱动本身(设备驱动源码)分离。

Kernel与设备驱动在linux中,设备驱动与Framework与bus结构有关

Framework:允许驱动体现硬件的通用特性

Bus infrastructure:隶属于驱动模型,检测硬件或是与硬件通讯

设备模型围绕三种数据结构来组织总线驱动

设备模型构成之一是总线驱动,每一类总线对应一类总线驱动,如PCIe/PCI,USB,SPI,UART,I2C,MMC等等。

总线驱动的作用

注册总线类型允许适配器驱动注册(USB controllers,I2C adapters等等),检测已连接的设备,提供与设备的通讯机制允许设备驱动(USB 设备,I2C设备,PCI设备)注册、管理设备匹配设备驱动与适配器驱动检测到的设备对适配器驱动与设备驱动提供API定义驱动数据结构与设备描述数据结构

USB总线

USB总线架构示例USB总线目录层级

USB设备驱动

USB 网卡示例

drivers/net/usb/rtl8150.c

设备描述

定义设备驱动可以管理的设备集,目的使USB core知道设备要用的对应设备驱动

MODULE_DEVICE_TABLE()宏允许depmod去提取设备描述与驱动之间的关系,所以驱动可以被udev设备自动加载。

usb driver实例化

struct usb_driver是由USB core定义的结构,每个USB设备驱动都必须实例化它,并注册它自身到USB core。

struct usb_driver继承自struct device_driver(由设备模型定义)

驱动注册于取消注册

当驱动被加载或是卸载时,相应的驱动注册到USB core或是从USB core取消注册,借助USB core提供的函数usb_register()与usb_deregister实现:

上述功能现已被如下接口取代

初始化阶段

与下图USB controller通讯的USB 适配器驱动注册其自身到USB core。

rtl8150 USB设备驱动注册其自身到USB core

之后USB core了解到rtl8150供应商ID、产品ID与struct usb_driver的联系。

当一个设备被检测到Probe函数

probe()函数接收一个描述设备的结构作为参数,这个机构通常由Bus framework(结构pci_dev, Struct usb_interface,等等)实例化。

probe()函数负责初始化设备、映射 I/O memory、注册中断handlers。bus infrastructure提供获取地址的方法、中断号和其他设备指定的信息;注册设备到合适的kernel framework,比如网络 infrastructure。

递归模型平台驱动非可发现式bus

在嵌入式系统,设备通常不是通过一个允许枚举、热插拔、和提供唯一标识的总线连接的。比如I2C总线或是SPI总线或是直接作为soc 范畴的设备

然而,我们仍然想将这些设备纳入device model的范畴。这些设备不能被动态检测,但是可被静态地描述在

kernel source code/dts/BIOS ACPI tables中。

平台设备

对于非可发现式设备,绝大部分是直接隶属SOC的设备:UART控制器、以太网控制器、SPI控制器、I2C控制器、音视频设备等。

在kernel中,一个被称作平台总线的专门的总线(被虚拟的创作出来)用来处理上述设备

这类总线支持平台驱动处理平台设备

这类总线类似于其他总线如USB、PCI。区别在于这类设备是被静态枚举的。

平台驱动实现

平台驱动实现一个struct platform_driver结构,比如drivers/tty/serial/imx.c

注册到、取消注册到platform driver infrastructure

或是直接应用module_platform_driver(serial_imx_driver);

平台设备实例化

平台设备不能被动态检测,它们是被静态定义的

在一些旧的 ARM平台上通过直接实例化struct platform_device结构。在板级或是SOC相关代码中实现定义。

针对ARM平台,看一个实例(较旧的风格):

arch/arm/mach-imx/mx1ads.c

资源机制

每个设备都需要使用一些相关的硬件资源比如I/O寄存器地址、DMA通道、IRQ lines等

用struct resource结构描述这些信息,struct resource 数组与struct platform_device 关联

允许为多个功能相似的设备实例化一个驱动程序,但是不同的地址、irq等

首先了解下device tree

针对许多嵌入式架构,手动实例化平台设备太繁琐,不容易维护

很多架构已经转向到使用device tree

它是一个节点树,对系统中设备包括从处理器内部的设备连接到板上的设备的层次结构进行建模

每个节点拥有一定数量的参数来描述设备的各种属性:address,interrupts,clocks等等。

在boot 阶段,给定编译版本的kernel、Device tree Blob 它被解析以实例化DT中描述的所有设备

device tree示例

节点名:serial@02020000

label:uart1,可以被引用&uart1

其他是属性

device tree的继承关系

每个特定的硬件平台都有自己的设备树

然而,多个硬件平台使用相同的处理器,而且通常是不同的同一家族中的处理器有许多相似之处。为了顺应这种情况,一个设备树文件可以包含另一个设备树。

可以使用设备树语言提供的/include/语句;或者使用#include语句,这需要在解析设备树之前调用C预处理器

示例说明

兼容字符串

有了设备树,使用兼容字符一个设备可以被绑定到相关的驱动上

struct device_driver的of_match_table域列出驱动支持的匹配字符串

驱动程序将使用与我们之前看到的相同的机制来检索basic 信息:中断号码,物理地址等

可用资源列表将在启动时由内核从设备树构建,因此在加载驱动程序时不需要对DT进行任何不必要的查找

任何附加信息都将特定于驱动程序或它所属的类,从而定义绑定

sysfs

总线、设备、驱动程序等结构是内核内部的

sysfs虚拟文件系统提供了一种将这些信息导出到用户空间的机制

The end!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有