草庐IT

Linux内核平台设备驱动模型platform_device和platform_driver框架

D584640810 2023-04-08 原文

        关于Linux平台设备驱动模型,并不是创建新的设备分类,是在原有的字符设备基础上使用,将设备和驱动分开,生成两个.ko文件。
        Linux内核维护一个全局设备链表,对应的总线会将驱动和设备链表里的设备名进行匹配,如果匹配成功就会将设备的信息传递给驱动的probe函数,probe函数得到设备的核心结构体platform_device的信息就可以进行对应的操作。
        我们只需实现平台驱动和平台设备即可,平台总线是内核实现的,常见的总线如IIC、SPI、CAN等,LED、KEY这类型的普通字符设备,linux内核就使用虚拟的平台总线struct bus_type  platform_bus_type来匹配这类设备。

首先来看platform_device平台设备层结构体。

我们只需要关注name、id、num_resources、resource、dev这几个成员。

struct platform_device{

           const char *name; //自定义的设备名,用于和驱动匹。

           int id;     //当设备和驱动一对一匹配时,所设值为-1

           struct device dev;     //下面列举其成员介绍。该结构体下的release函数是必须实现的

           u32 num_resources;  //设备的个数,即设备资源数组的元素个数

           struct resource   *resource; //设备所用资源数组的首地址

};

接下来看platform_device下的resources结构体。

我们需关注前四个成员,最后一个成员是由内核实现。

struct resource{

        resource_size_t start;   //所用资源的起始物理地址

        resource_size_t end;   //所用资源的结束物理地址

        const char *name;    //自定义的资源名称,此名称不与驱动相匹配,可以随便写,但要有意义

        unsigned long flags;   //所用资源的类型,例如中断IORESOURCE_IRQ,外设或者用于和设备通讯的支持直接寻址的地址空间IORESOURCE_MEM

};

接下来看platform_device结构体下的struct device,由于结构体过大,只展示重要的部分。

 struct  device{

      void  *platform_data;  //这个指针指向设属性信息,platform_driver可以获取该数据

      void *driver_data ;  //用来告诉驱动需要服务的设备的类型

      void (*release)(struct device *dev); //释放平台设备时会调用此函数,必须要实现

}

因此,编写平台设备的步骤大概如下:

1、分析硬件原理图,写出所使用的设备的占用资源情况,例如GPIO0寄存器的起始物理地址,GPIO0寄存器所占用的空间大小

2、定义并初始化一个资源结构数组struct resource,存放所有使用到的设备的信息。

3、编写一个release函数,在释放平台设备device时会调用此函数。

4、定义并初始化一个平台设备核心结构struct platform_device,其下的name是用来与driver下的name匹配的。

5、在模块初始化函数中调用注册平台设备函数,将平台设备核心结构体注册到内核中。

6、在模块卸载函数中调用注销平台设备函数,将平台设备核心结构体从内核中注销。

接下来实现平台驱动platform_driver核心结构体。

 

我们只需关注要用到的成员。

struct platform_driver {

        int (*probe)(struct platform_device *); //指向设备探测函数,当与设备相匹配时调用此函数,参数是将平台设备指针传入,通过操作平台设备指针可以初始化硬件。是很重要的函数

        int (*remove)(struct platform_device *);//指向移除设备函数,当总线上的设备和驱动匹配关系解除时会调用此函数。如果probe函数中申请了资源,就需要在此函数中按顺序释放

        struct device_driver driver; //此结构体下的name成员和设备相匹配,还有一个成员是用于和设备树相匹配,下面会列出

        const struct platform_device_id *id_table; /如果需要匹配多个设备,也可以使用此成员

};

接下来看platform_driver下的device_driver结构体。

 

我们只需关注重要的成员。

struct device_driver{

        const char *name; //此名字会和平台设备的名字相匹配

        const struct of_device_id *of_match_table; //此成员下的compatible是和设备的名字相匹配,下面会列出。是用于设备树的方式实现一个驱动匹配多个设备

}

接下来关注platform_driver下的platform_device_id。

struct platform_device_id {

        char name[PLATFORM_NAME_SIZE]; //此成员用于和设备名相匹配

        kernel_ulong_t driver_data; //此成员用于来保存设备的配置

};

因此,平台驱动有三种方式和平台设备相匹配。

第一种:也就是优先级最低的一种。platform_driver下的name成员和平台设备platform_device下的name成员匹配。

第二种:优先级第二高。平台设备platform_device下的name成员和platform_driver下的platform_device_id所指向的数组的每个元素的name匹配。

第三种:优先级最高,使用的是设备树方式。platform_driver下的device_driver下的of_device_id所指向的每个元素的compatible值与设备树中设备节点的compatibl值相匹配。

这里的优先级是指,当设备树方式实现时,会先用设备树方式匹配,当设备树无法匹配时会使用platform_device_id匹配,最后再使用platform_driver下的name成员匹配。

因此,平台驱动层的编写大概如下:

1、定义一个probe探测函数和remove删除函数。

2、如果需要用到platform_device_id,则需要定义一个platform_device_id的数组来存储相应的设备信息。如果不需要用到则跳过。

3、如果需要用到设备树匹配,则定义一个of_device_id数组来存储设备的信息和数据。如果不需要用到则跳过。

4、定义一个平台设备驱动核心结构体platform_driver并初始化里面需要用到的成员。

5、在模块初始化函数中调用注册平台驱动函数。

6、在模块卸载函数中调用注销平台驱动函数。

一般probe探测函数框架如下:

1、获取平台设备的属性信息、数据,利用传进来的指针可以得到。

2、探测资源。

3、申请资源

4、使用资源,映射寄存器、申请中断资源等。

5、初始化硬件设备。

6、注册input子系统设备、字符设备、块设备、网络设备等。

remove函数就将probe函数中所申请占用的资源按顺序进行释放。

 

 

 

 

有关Linux内核平台设备驱动模型platform_device和platform_driver框架的更多相关文章

  1. ruby-on-rails - Capybara-webkit 引发 Capybara::Driver::Webkit::WebkitInvalidResponseError - 2

    我在rspec中收到来自webkit驱动程序的以下消息:Capybara::Driver::Webkit::WebkitInvalidResponseError:UnabletoloadURL:http://127.0.0.1:44923/posts几天前它成功了。问题出在save_page方法上。有什么问题吗? 最佳答案 当我的页面出现错误时,我收到过类似的错误消息。您应该通过在测试模式下启动服务器(railss-etest)并自行访问页面来手动检查情况是否如此。 关于ruby-on-

  2. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  3. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  4. ruby - 为什么 Object 在 Ruby 中既包含内核又继承它? - 2

    在Ruby(1.8.X)中为什么Object既继承了内核又包含了内核?仅仅继承还不够吗?irb(main):006:0>Object.ancestors=>[Object,Kernel]irb(main):005:0>Object.included_modules=>[Kernel]irb(main):011:0>Object.superclass=>nil请注意,在Ruby1.9中情况类似(但更简洁):irb(main):001:0>Object.ancestors=>[Object,Kernel,BasicObject]irb(main):002:0>Object.included

  5. 【Linux操作系统】——网络配置与SSH远程 - 2

    Linux操作系统——网络配置与SSH远程安装完VMware与系统后,需要进行网络配置。第一个目标为进行SSH连接,可以从本机到VMware进行文件传送,首先需要进行网络配置。1.下载远程软件首先需要先下载安装一款远程软件:FinalShell或者xhell7FinalShellxhell7FinalShell下载:Windows下载http://www.hostbuf.com/downloads/finalshell_install.exemacOS下载http://www.hostbuf.com/downloads/finalshell_install.pkg2.配置CentOS网络安装好

  6. Linux磁盘分区中物理卷(PV)、卷组(VG)、逻辑卷(LV)创建和(LVM)管理 - 2

    文章目录一基础定义二创建逻辑卷2-1准备物理设备2-2创建物理卷2-3创建卷组2-4创建逻辑卷2-5创建文件系统并挂载文件三扩展卷组和缩减卷组3-1准备物理设备3-2创建物理卷3-3扩展卷组3-4查看卷组的详细信息以验证3-5缩减卷组四扩展逻辑卷4-1检查卷组是否有可用的空间4-2扩展逻辑卷4-3扩展文件系统五删除逻辑卷5-1备份数据5-2卸载文件系统5-3删除逻辑卷5-4删除卷组5-5删除物理卷六LVM逻辑卷缩容6-1缩容注意事项6-2标准缩容步骤一基础定义LVM,LogicalVolumeManger,逻辑卷管理,Linux磁盘分区管理的一种机制,建立在硬盘和分区上的一个逻辑层,提高磁盘分

  7. 【RuntimeError: CUDA error: device-side assert triggered】问题与解决 - 2

    RuntimeError:CUDAerror:device-sideasserttriggered问题描述解决思路发现问题:总结问题描述当我在调试模型的时候,出现了如下的问题/opt/conda/conda-bld/pytorch_1656352465323/work/aten/src/ATen/native/cuda/IndexKernel.cu:91:operator():block:[5,0,0],thread:[63,0,0]Assertion`index>=-sizes[i]&&index通过提示信息可以知道是个数组越界的问题。但是如图一中第二行话所说这个问题可能并不出在提示的代码段

  8. ruby - 如何在 Ruby 中获取 linux 系统信息 - 2

    如何在Ruby中获取linux系统(这必须适用于Fedora、Ubuntu等)的软件/硬件信息? 最佳答案 Chef背后的优秀人才,拥有一颗名为Ohai的优秀gemhttps://github.com/opscode/ohai以散列形式返回系统信息,例如操作系统、内核、规范、fqdn、磁盘、空间、内存、用户、接口(interface)、sshkey等。它非常完整,非常好。它还会安装命令行二进制文件(也称为ohai)。 关于ruby-如何在Ruby中获取linux系统信息,我们在Stack

  9. ruby - rbenv:在 Linux Mint 上找不到 gem 命令 - 2

    我在LinuxMint17.2上。我最近使用apt-getpurgeruby​​删除了ruby​​。然后我安装了rbenv然后rbenvinstall2.3.0所以现在,~/.rbenv/versions/2.3.0/bin/ruby存在。但是现在,我无法执行geminstallrubocop。我明白了:$geminstallrubocoprbenv:gem:commandnotfoundThe`gem'commandexistsintheseRubyversions:2.3.0但是我可以~/.rbenv/versions/2.3.0/bin/geminstallrubocop。但是,

  10. ruby - 在 Linux 上编译 Ruby 1.9.2 所需的先决条件? - 2

    我是Ruby和RoR的新手。我有一个带有Ubuntu镜像的干净Linode实例,我想从源代码编译Ruby而不是使用apt-get。我已经在谷歌上搜索了执行此操作的说明,但经过一些尝试后,当我尝试运行一些教程示例时,我不断收到有关缺少zlib和其他一些包的错误。任何人都可以给我详细的说明(或链接),教我如何在从源代码编译Ruby之前安装必要的必备包吗?我的目的是编译Ruby的最新稳定版本,然后安装Rubygems和Rails。提前感谢您的帮助!!! 最佳答案 Thisblogpost涵盖从源代码编译ruby​​所需的包和安装过程;它引

随机推荐