驱动——platform驱动总线三种匹配方式

这篇具有很好参考价值的文章主要介绍了驱动——platform驱动总线三种匹配方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

三种platform驱动匹配方式代码案例以及现象

方式一:通过设置名字进行匹配

相关API简介:

1、platform_device的API

①分配对象

struct platform_device {

        const  char *name;//用于进行匹配的名字

        int  id;//总线号 PLATFORM_DEVID_AUTO(自动分配总线号)

        struct  devicedev;//父类

        u32     num_resources;//表示设备信息的个数

        struct resource*resource;//描述硬件设备信息的结构体

};

struct device {

        void    (*release)(struct device *dev); //释放device的资源

}

struct resource {

        resource_size_t start;//资源的起始数值 

        resource_size_t end;//资源的结束值

        unsigned long flags;//资源的类型 // IORESOURCE_IO|IORESOURCE_MEM|IORESOURCE_IRQ };

②对象初始化

1>定义一个relese函数

void pdev_release(struct device *dev) { }

2>对设备信息进行填充

struct resource res[]={

                [0]={

                        .start=0x12345678,

                        .end=0x12345678+49,

                        .flags= IORESOURCE_MEM,

                },

                [1]={

                        .start=71,

                        .end=71,

                        .flags= IORESOURCE_IRQ,

                },

};

3>给对象赋值

struct platform_device pdev={

                        .name="aaaaa",

                        .id=PLATFORM_DEVID_AUTO,

                        .dev={

                                .release=pdev_release,

                        },

                        .resource=res,

                        .num_resources=ARRAY_SIZE(res),

};

③将对象注册进内核

int platform_device_register(struct platform_device *pdev)

参数:platform_device对象指针

④注销对象

 int platform_device_unregister(struct platform_device *pdev)

 2、platform_driver的API

①对象结构体

struct platform_driver {
                //匹配成功后执行probe函数
                int (*probe)(struct platform_device *);
                 //设备和驱动分离的时候执行remove函数
                int (*remove)(struct platform_device *);
                 //父类,进行匹配选项的设置
                struct device_driver driver;
                 //通过id_table的方式匹配设备文件
                const struct platform_device_id *id_table;
};

struct device_driver {
                const char  *name;//设置名字匹配
                struct of_device_id*of_match_table;//通过设备树进行匹配
        };

②对象的初始化

//定义一个probe函数
    int pdrv_probe(struct platform_device *pdev)
    {      
    }
    int pdrv_remove(struct platform_device *pdev)
    {      
    }
    //对象初始化
    struct platform_driver pdrv={
        .probe=pdrv_probe,
        .remove=pdrv_remove,  
        .driver={
            .name="aaaaa",        
        },  
    };

③对象的注册

 #define platform_driver_register(drv)   __platform_driver_register(drv, THIS_MODULE)

④对象的注销

void platform_driver_unregister(struct platform_driver *drv)

3、代码实现

——device

#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,      
      },
  };
  
//定义一个relese函数
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 mycdev_init(void)
{
    //注册device
    return platform_device_register(&pdev);
}
static void __exit mycdev_exit(void)
{
    //注销device
    platform_device_unregister(&pdev);

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

——driver

#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)
{
    printk("%s:%d\n",__func__,__LINE__); 
    res=platform_get_resource(pdev,IORESOURCE_MEM,0);
        if(res==NULL)
        {
            printk("获取MEM资源失败\n");
            return ENODATA;
        }
    //获取中断类型的资源
    irqno=platform_get_irq(pdev,0);
        if(irqno<0)
        {
            printk("获取中断资源失败\n");
            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");

4、测试现象

platform匹配过程,驱动开发,驱动开发,c语言,开发语言

 方式二:通过id_table方式匹配

        在驱动编写的时候,有时候需要一个驱动适配多款硬件,任何一个硬件的设备信息和这个驱动匹配成功后都可以执行这个驱动里的probe函数,所以为了解决这个情景,linux内核设计了id_table存取设备的名字列表,驱动端选择id_table方式通过platform_device_id来实现:

#include<linux/mod_devicetable.h>
struct platform_device_id {
    char name[PLATFORM_NAME_SIZE];//匹配的名字
    kernel_ulong_t driver_data;//设备驱动的私有数据
};

 代码实现—

——device

#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,      
      },
  };
  
//定义一个relese函数
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 mycdev_init(void)
{
    //注册device
    return platform_device_register(&pdev);
}
static void __exit mycdev_exit(void)
{
    //注销device
    platform_device_unregister(&pdev);

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

——driver

#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)
{
    printk("%s:%d\n",__func__,__LINE__); 
    res=platform_get_resource(pdev,IORESOURCE_MEM,0);
        if(res==NULL)
        {
            printk("获取MEM资源失败\n");
            return ENODATA;
        }
    //获取中断类型的资源
    irqno=platform_get_irq(pdev,0);
        if(irqno<0)
        {
            printk("获取中断资源失败\n");
            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},
    {},
};
//热插拔宏
MODULE_DEVICE_TABLE(platform,idtable);
struct platform_driver pdrv={
    .probe=pdrv_probe,
    .remove=pdrv_remove,
    .driver={
        .name="aaaaa",
    },
};

module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

测试现象 

 platform匹配过程,驱动开发,驱动开发,c语言,开发语言

方式三:通过设备树进行匹配

        在linux内核版本3.10之后,要求所有的设备信息都放在设备树中,所以在platform驱动被使用的时候不再写platform_device了。而是将platform_device中的设备信息直接放在设备树中即可

 1、添加设备节点信息

   myplatform{
       compatible="hqyj,platform";
       reg=<0x12345678 0x14>;
       interrupt-parent = <&gpiof>;
       interrupts = <9 0>;
       myled1 = <&gpioe 10 0>;
   };                              

2、将匹配方式设置为设备树匹配 

 //构建compatible表
    struct of_device_id oftable[]=
    {
        {.compatible="hqyj,platform",},
        {}
    };
    //热插拔宏
    MODULE_DEVICE_TABLE(of,oftable);  
    //对象初始化
    struct platform_driver pdrv={       
        .probe=pdrv_probe,
        .remove=pdrv_remove,  
        .driver={
            .name="aaaaa", //设置名字匹配
            .of_match_table=oftable,//设备树匹配
        }, 

3、解析设备树节点信息获取GPIO编号

4、代码实现

#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>
/*   myplatform{
       compatible="hqyj,platform";
       reg=<0x12345678 0x14>;
       interrupt-parent = <&gpiof>;
       interrupts = <9 0>;
       myled1 = <&gpioe 10 0>;
   };                              
*/
struct resource *res;
int irqno;
struct gpio_desc *gpiono;
//对象的初始化
int pdrv_probe(struct platform_device *pdev)
{
    printk("%s:%d\n",__func__,__LINE__);
    res = platform_get_resource(pdev,IORESOURCE_MEM,0);
    if(res==NULL)
    {
        printk("paltform get resource error\n");
        return ENODATA;
    }
    irqno = platform_get_irq(pdev,0);
    if(irqno<0)
    {
        printk("paltform get irq error\n");
        return ENODATA;
    }
    printk("addr:%#x,irqno:%d\n",res->start,irqno);
    //解析设备树节点信息获取GPIO编号
    gpiono=gpiod_get_from_of_node(pdev->dev.of_node,"myled1",0,GPIOD_OUT_HIGH,NULL);
    if(IS_ERR(gpiono))
    {
        printk("gpiod get from of node error\n");
        return PTR_ERR(gpiono);
    }
    printk("gpiod get from of node success\n");
    //点灯
    gpiod_set_value(gpiono,1);
    return 0;
}

int pdrv_remove(struct platform_device *pdev)
{
    printk("%s:%d\n",__func__,__LINE__);
    gpiod_set_value(gpiono, 0);
    gpiod_put(gpiono);
    return 0;
} 
//构建compatible表
struct of_device_id oftable[]=
{
    {.compatible="hqyj,platform",},
    {}
};
//热插拔宏
MODULE_DEVICE_TABLE(of,oftable);
struct platform_driver pdrv={
    .probe=pdrv_probe,
    .remove=pdrv_remove,
    .driver={
        .name="aaaaa",
        .of_match_table=oftable,//设备树匹配
    },
    
};

module_platform_driver(pdrv);
MODULE_LICENSE("GPL");

5、 测试现象

platform匹配过程,驱动开发,驱动开发,c语言,开发语言

platform匹配过程,驱动开发,驱动开发,c语言,开发语言文章来源地址https://www.toymoban.com/news/detail-586233.html

到了这里,关于驱动——platform驱动总线三种匹配方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 驱动开发,IO多路复用实现过程,epoll方式

    被称为当前时代最好用的io多路复用方式; 核心操作:一棵树(红黑树)、一张表(内核链表)以及三个接口;  思想:(fd代表文件描述符)         epoll要把检测的事件fd挂载到内核空间红黑树上,遍历红黑树,调用每个fd对应的操作方法,找到发生事件的fd,如果没有发

    2024年02月07日
    浏览(53)
  • 为什么MCS-51 单片机总线和端口要有匹配的驱动电路?

            MCS-51系列单片机是一种广泛使用的8位微控制器,它通常用在嵌入式系统中。单片机的总线和端口可能需要额外的驱动电路,这取决于外部设备的电气特性和所需的电流能力。下面将从以下几个方面分析为什么驱动电路这么重要:          电流驱动能力: MCS-51单片机

    2024年02月20日
    浏览(54)
  • I2C总线驱动:裸机版、应用层的使用、二级外设驱动三种方法

    SOC芯片平台的外设分为: 一级外设:外设控制器集成在SOC芯片内部 二级外设:外设控制器由另一块芯片负责,通过一些通讯总线与SOC芯片相连 Inter-Integrated Circuit: 字面意思是用于“集成电路之间”的通信总线,简写:IIC(或者I2C) i2c传输的要点就是: 传输一个字节 后面必然

    2024年02月09日
    浏览(38)
  • <Linux开发>驱动开发 -之-platform 驱动

    <Linux开发>驱动开发 -之-platform 驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: <Linux开发> -之-系统移植 uboot移植过程详细记录(第一部分) <Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分) <Linux开发>

    2024年02月12日
    浏览(57)
  • 驱动开发-platform

    实现设备与驱动分离的思想        先解析设备信息,成功后执行probe函数控制相关硬件信息 实例:

    2024年02月11日
    浏览(47)
  • 【驱动开发】Windows过滤平台(WFP,Windows Filtering Platform)

    正题开始之前,先总结一下Windows的发展历程。 Windows1.0、2.0、3.0、3.1、3.2:16位。 Windows9x:包括 Windows 95 、 Windows 98 、 Windows Me 。 WindowsNT系列:包括 Windows NT 3.1 、 Windows NT 3.1 、 Windows NT 4.0 、 Windows 2000 、 Windows XP 、 Windows Server 2003 、 Windows Vista 、 Windows Server 2008 、 Windows

    2024年02月08日
    浏览(39)
  • 详解AT24CXX驱动开发(linux platform tree - i2c应用)

    目录 概述 1 认识AT24Cxx 1.1 AT24CXX的特性 1.2 AT24CXX描述 1.2.1 引脚 1.2.2 容量描述 1.2.3 设备地址 1.3 操作时序 1.3.1 写单个字节时序 1.3.2 写page字节时序 1.3.3 读取当前数据时序 1.3.4 随机读取数据 1.3.5 连续读取多个数据 2 驱动开发 2.1 硬件接口 2.2 代码实现 2.2.1 查看设备信息 2.2.2 编写

    2024年02月22日
    浏览(44)
  • 韦东山嵌入式Liunx入门驱动开发一(Hello 驱动编程、GPIO基础知识、LED驱动、总线设备驱动模型)

    本人学习完韦老师的视频,因此来复习巩固,写以笔记记之。 韦老师的课比较难,第一遍不知道在说什么,但是坚持看完一遍,再来复习,基本上就水到渠成了。 看完视频复习的同学观看最佳! 基于 IMX6ULL-PRO 参考视频 Linux快速入门到精通视频 参考资料 :01_嵌入式Linux应用

    2024年04月25日
    浏览(78)
  • 【genius_platform软件平台开发】第九十七讲:linux设备驱动中信号(signal函数)的异步通知机制

    意思是: 一旦设备就绪,则主动通知应用程序 ,这样应用程序根本就不需要查询设备状态,这一点非常 类似于硬件上“中断”的概念 ,比较准确的称谓是“ 信号驱动的异步I/O ”。信号是在软件层次上对 中断机制的一种模拟 ,在原理上,一个进程收到一个信号与处理器收到一

    2024年02月08日
    浏览(61)
  • 【IMX6ULL驱动开发学习】07.驱动程序分离的思想之平台总线设备驱动模型和设备树

    目录 一、驱动程序分离的思想 二、设备树 2.1 使用设备树 三、平台总线设备驱动模板 【IMX6ULL驱动开发学习】05.字符设备驱动开发模板(包括读写函数、poll机制、异步通知、定时器、中断、自动创建设备节点和环形缓冲区)_阿龙还在写代码的博客-CSDN博客 之前编写驱动程序

    2024年02月07日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包