驱动开发 platfrom总线驱动的三种方式

news2024/11/24 20:49:18

驱动的分隔与分离:

        对于 Linux 这样一个成熟、庞大、复杂的操作系统,代码的重用性非常重要,在驱动程序,因为驱动程序占用了 Linux 内核代码量的大头,如果不对驱动程序加以管理,任由重复的代码肆意增加,那么用不了多久 Linux 内核的文件数量就庞大到无法接受的地步。

        例如:现在有三个SOC A、B 和 C上都有 MPU6050 这个 I2C 接口的六轴传感器,按照我们写裸机 I2C 驱动的时候的思路,每个平台都有一个MPU6050的驱动,那么设备端的驱动将会重复的编写好几次。显然在 Linux 驱动程序中这种写法是不推荐的,最好的做法就是每个SOC的 I2C 控制器都提供一个统一的接口 (也叫做主机驱动),每个设备的话也只提供一个驱动程序(设备驱动),每个设备通过统一的 I2C 接口驱动来访问,这样就可以大大简化驱动文件。

        

        当我们向系统注册一个驱动的时候,总线就会在右侧的设备中查找,看看有没有与之匹配
的设备,如果有的话就将两者联系起来。同样的,当向系统中注册一个设备的时候,总线就会
在左侧的驱动中查找看有没有与之匹配的设备,有的话也联系起来。
        在linux内核中的驱动程序都采用总线、驱动和设备这样的模式。
        platform 驱动就是这一思想下的产物。

总线驱动模型:

        platform总线遵从总线模型,platform是linux内阁抽象出来的软件代码,没有真实的总线和它对应(不存在)

        platfor总线去驱动的思想:是将设备信息和驱动进行分离。platform_device和platform_driver通过总线进行匹配,匹配成功后会执行驱动中的probe函数,在probe函数中可以获取到device中的硬件设备信息。

以下是platfrom的三种匹配方式:

一:设备名

pdrv:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/platform_device.h>
#include<linux/mod_devicetable.h>
struct resource *res;
int irqno;
int pdrv_probe(struct platform_device *pdev)
{
    res=platform_get_resource(pdev,IORESOURCE_MEM,0);
    if(res==NULL)
    {
        return ENODATA;
    }
    irqno=platform_get_irq(pdev,0);
    if(irqno<0)
    {
        return ENODATA;
    }
    printk("addr:%#llx,irqno:%d\n",res->start,irqno);
    return 0;
}
int pdrv_remove(struct platform_device *pdev)
{
    printk("%s:%d\n",__func__,__LINE__);
    return 0;
}
 
 
struct platform_driver pdrv={
    .probe=pdrv_probe,
    .remove=pdrv_remove,
    .driver={
        .name="aaaaa",
    },
};
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

pdev:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/platform_device.h>

struct resource res[]={
    [0]={
        .start=0x12345678,
        .end=0x12345678+49,
        .flags=IORESOURCE_MEM,
    },
    [1]={
        .start=71,
        .end=71,
        .flags=IORESOURCE_IRQ,
    },
};
void pdev_release(struct device *dev)
{
    printk("%s:%d\n",__func__,__LINE__);
}
struct platform_device pdev=
{
    .name="aaaaa",
    .id=PLATFORM_DEVID_AUTO,
    .dev={
        .release=pdev_release,
    },
    .resource=res,
    .num_resources=ARRAY_SIZE(res),
};
 
 
static int __init demo_init(void)
{
    platform_device_register(&pdev);
    return 0;
}
 
static void __exit demo_exit(void)
{
    platform_device_unregister(&pdev);
}
 
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");

 

二:设备名列表

pdev:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/platform_device.h>
 
 
struct resource res[]={
    [0]={
        .start=0x12345678,
        .end=0x12345678+49,
        .flags=IORESOURCE_MEM,
    },
    [1]={
        .start=71,
        .end=71,
        .flags=IORESOURCE_IRQ,
    },
};
void pdev_release(struct device *dev)
{
    printk("%s:%d\n",__func__,__LINE__);
}
struct platform_device pdev=
{
    .name="hello1",
    .id=PLATFORM_DEVID_AUTO,
    .dev={
        .release=pdev_release,
    },
    .resource=res,
    .num_resources=ARRAY_SIZE(res),
};
 
 
static int __init demo_init(void)
{
    platform_device_register(&pdev);
    return 0;
}
 
static void __exit demo_exit(void)
{
    platform_device_unregister(&pdev);
}
 
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");

pdrv2:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/platform_device.h>
#include<linux/mod_devicetable.h>
struct resource *res;
int irqno;
int pdrv_probe(struct platform_device *pdev)
{
    res=platform_get_resource(pdev,IORESOURCE_MEM,0);
    if(res==NULL)
    {
        return ENODATA;
    }
    irqno=platform_get_irq(pdev,0);
    if(irqno<0)
    {
        return ENODATA;
    }
    printk("addr:%#llx,irqno:%d\n",res->start,irqno);
    return 0;
}
int pdrv_remove(struct platform_device *pdev)
{
    printk("%s:%d\n",__func__,__LINE__);
    return 0;
}
 
struct  platform_device_id idtable[]={
    {"hello1",0},
    {"hello2",1},
    {"hello3",2},
    {}
};
 
struct platform_driver pdrv={
    .probe=pdrv_probe,
    .remove=pdrv_remove,
    .driver={
        .name="aaaaa",
    },
    .id_table=idtable,
};
MODULE_DEVICE_TABLE(platform,idtable);
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

 

三:设备树

添加设备树节点:

pdrv3:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/platform_device.h>
#include<linux/mod_devicetable.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
struct resource *res;
int irqno;
struct gpio_desc *gpiono;
int pdrv_probe(struct platform_device *pdev)
{
    res=platform_get_resource(pdev,IORESOURCE_MEM,0);
    if(res==NULL)
    {
        return ENODATA;
    }
    irqno=platform_get_irq(pdev,0);
    if(irqno<0)
    {
        return ENODATA;
    }
    printk("addr:%#x,irqno:%d\n",res->start,irqno);
    gpiono=gpiod_get_from_of_node(pdev->dev.of_node,"myled1",0,GPIOD_OUT_HIGH,0);
    if(IS_ERR(gpiono))
    {
        printk("获取gpio编号失败\n");
        return PTR_ERR(gpiono);
    }
    gpiod_set_value(gpiono,1);
    return 0;
}
int pdrv_remove(struct platform_device *pdev)
{
    gpiod_set_value(gpiono,0);
    gpiod_put(gpiono);
    printk("%s:%d\n",__func__,__LINE__);
    return 0;
}
struct of_device_id oftable[]={
    {.compatible="hqyj,platform",},
    {}
};
struct platform_driver pdrv={
    .probe=pdrv_probe,
    .remove=pdrv_remove,
    .driver={
        .name="aaaaa",
        .of_match_table=oftable,
    },
    
};
module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47250.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于深度学习的合成孔径雷达自聚焦

文章目录引言什么是合成孔径雷达什么是自聚焦经典自聚焦方法基于机器学习的方法基于极速学习机的方法基于深度学习的SAR自聚焦代码附录引言 本文全面介绍合成孔径雷达自聚焦概念和方法。想获取更为详尽的描述&#xff0c;请参考以下几篇论文, 如果数据或代码对你的研究有用&am…

【ASM】字节码操作 工具类与常用类 ClassRemapper 介绍 类映射 代码混淆

文章目录 1.概述2. ClassRemapper#2.1 class info2.2 fields2.3 构造方法2.4 method3. 案例3.1 案例1-修改类名3.2 案例2-修改字段名和方法3.3 案例3-修改2个类4.总结1.概述 在上一篇文章:【ASM】字节码操作 工具类与常用类 InstructionAdapter 介绍 我们知道了,对于Instruc…

[思维模式-5]:《如何系统思考》-1- 认识篇 - 总体结构与知识框架

目录 前言&#xff1a; 第一篇&#xff1a;认知篇 第1章 无所不在的系统 // 2 第2章 思维的转变 // 30 第二篇&#xff1a;方法与工具 第3章 深入思考 // 50 第4章 动态思考 // 78 第5章 全面思考 // 109 第6章 系统思考的“新语言”&#xff1a;因果回路图 // …

Zookeeper(一)- Zookeeper介绍与集群部署

文章目录一、Zookeeper 介绍1. Zookeeper概述2. Zookeeper工作机制3. Zookeeper特点4. Zookeeper数据结构5. Zookeeper应用场景&#xff08;1&#xff09;统一命名服务&#xff08;2&#xff09;统一配置管理&#xff08;3&#xff09;统一集群管理&#xff08;4&#xff09;服…

翻译QT使用手册:将库添加到项目

将库添加到项目 除了 Qt 库之外&#xff0c;您还可以将其他库添加到您的项目中。该过程取决于图书馆的类型和位置。您可以添加系统库、您自己的库或第三方库。该库可以位于当前项目的构建树中&#xff0c;也可以位于另一个构建树中。 将库添加到项目 除了 Qt 库之外&#xff0c…

远距离双目视觉测量系统纵深方向测量精度较低原因分析

两台相机基线距离约1200mm&#xff0c;对20m外的一个LED发光点进行持续观测&#xff0c;效果如下视频所示&#xff1a; 可见ZZZ方向的重复性精度比较差&#xff0c;波动量甚至多于2mm了&#xff0c;而以10mm导轨基准距离为基准&#xff0c;精度测试结果也比较差&#xff0c;如…

[附源码]计算机毕业设计springboot个性化产品服务管理系统论文

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

xss-labs/level11

首先输入 <script>alert(xss)</script> 丝毫不差 没有出现回弹现象 根本就不出人意料好吧 接着来看一下源代码好吧 能够看得出来第一个输出点由于htmlspecialchars转义操作 所以上述代码根本行不通 这一关比上一关又多了一个隐藏表单 一共是有四个隐藏表单 从…

C++入门笔记

C 入门笔记Functions in CC header Files下面主要是我学习C的一个笔记&#xff0c;记录学习中遇到的一些重点事项。下面是视频的连接https://www.bilibili.com/video/BV1Ay4y1i7Z6/?p10&spm_id_from333.1007.top_right_bar_window_history.content.click&vd_sourcee6e…

单连通图的判断

单连通图的判断算法&#xff1a; &#xff08;1&#xff09;对每个点进行dfs得到一棵dfs树&#xff1b; &#xff08;2&#xff09;判断是否存在前向边和横向边&#xff0c;若有则必定存在两个点之间有至少2条简单路径&#xff0c;因此该图不属于单连通图&#xff1b; &#xf…

一个开源且完全自主开发的国产网络协议栈

已剪辑自: https://mp.weixin.qq.com/s/_1LE7mGc9mRuajRgNsyirQ onps是一个开源且完全自主开发的国产网络协议栈&#xff0c;适用于资源受限的单片机系统&#xff0c;提供完整地ethernet/ppp/tcp/ip协议族实现&#xff0c;同时提供sntp、dns、ping等网络工具&#xff0c;支持以…

mac pro M1(ARM)安装:.Net、C#开发环境

0.引言 因为.Net是开发、运行环境&#xff0c;而C#是一个编程语言&#xff0c;专用于.Net平台&#xff0c;C#是运行在.Net之上的&#xff0c;所以两者的安装是密不可分的 1. 安装 1、因为arm架构安装Visual Studio 2022 for mac可以自动附带安装.Net&#xff0c;所以我们只需…

刷题之完全二叉树的权值和小字辈及根据后序和中序遍历输出先序遍历

1、完全二叉树的权值 1&#xff09;题目 给定一棵包含 N 个节点的完全二叉树&#xff0c;树上每个节点都有一个权值&#xff0c;按从 上到下、从左到右的顺序依次是 A1, A2, AN&#xff0c;如下图所示&#xff1a; 现在小明要把相同深度的节点的权值加在一起&#xff0c;他想…

开关电源32个检测项目、检测方法与检测设备(下)

开关电源是电器必备&#xff0c;本文详细介绍了开关电源的32个常见检测项目、检测方法与仪器&#xff0c;内容较多&#xff0c;前些日子介绍了上部分16个项目&#xff08;点击阅读&#xff09;&#xff0c;今天介绍剩下的16个项目。抱歉久等了&#xff01; 过压保护测试 一、目…

MySQL数据库事务控制

目录 一、事务控制概念 二、事务控制特性 三、事务控制相关命令 1、测试begin和commit&#xff08;开始事务和提交事务&#xff09; 2、测试事务回滚rollback 四、总结 1、事务的ACID特性 2、事务之间的相互影响 3、事务的隔离级别 一、事务控制概念 在MySQL中用于处理…

上海大治河二线船闸总体设计与结构计算

目录 第一章 设计基本资料 1 1.1工程概况 1 1.2 货运量预测 1 1.3 建筑物设计等级 1 1.4 通航情况及计算参数的选取 1 1.5 设计船型 2 1.6 特征水位表 2 1.7 水文气象资料 3 1.8 工程地质 3 第二章 总体设计 4 2.1 船闸地理位置确定 4 2.2 船闸线、级数确定 5 2.3 船闸的基本尺…

【能效管理】变电所运维云平台在上海某医院的设计分析

摘要&#xff1a;本文概述了变电所电力运维技术&#xff0c;分析了医院变电所中存在的技术设备老化和技术荷载不足的技术性问题&#xff0c;并从主变低压进出线路监测故障、环境监测故障、设备档案记录、运维排班记录、分析报告五个方面探讨了变电所电力运维技术的具体应用。变…

1. 语音类实现 (实现读取wav/pcm,STFT)

[C 基于Eigen库实现CRN前向推理] 第一部分&#xff1a;WavFile.class (实现读取wav/pcm,实现STFT) 前言&#xff1a;(Eigen库使用记录)第一部分&#xff1a;WavFile.class (实现读取wav/pcm,实现STFT)第二部分&#xff1a;Conv2d实现第三部分&#xff1a;TransposedConv2d实现…

荧光标记肽(Arg)9, FAM-labeled

(Arg)9, FAM-labeled 是一种带有 FAM 标记的 ARG&#xff0c;属于细胞穿透肽 (CPP)。CPPs 已成为一种强大的工具&#xff0c;用于将生物活性物质输送到完整细胞胞质中。(Arg)9, FAM-labeled, a cell-penetrating peptide (CPP), is a nona-arginine (ARG) with FAM label. CPPs…

mac上的python2安装

iiPython Release Python 2.7.18rc1 | Python.orgThe official home of the Python Programming Languagehttps://www.python.org/downloads/release/python-2718rc1/不小心把mac上的python2给删除了&#xff0c;发现老的nodejs项目需要pytho2&#xff0c;这下晕了&#xff0c;…