❤️⭐万字长文玩转总线设备驱动platform_device与platform_driver⭐❤️

2023-10-14 00:10

本文主要是介绍❤️⭐万字长文玩转总线设备驱动platform_device与platform_driver⭐❤️,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、Linux总线的重要函数
    • 1.1注册与销毁函数
    • 1.2获得资源
    • 1.3获得中断
    • 1.4通过名字获得资源或者中断
    • 1.5同时注册多个dev
  • 二、总线设备里面含有什么结构体?
    • 1.1从platform_device 开始
      • 1.1.2 struct resource资源存储
    • 1.2与platform_driver结合
    • 1.3platform_driver与platform_device 如何进行关联
    • 1.3.1比对规则
    • 1.4 匹配成功后
  • 三.代码示范
    • 3.1平台设备案例
    • 3.2资源设备案例


前言

总线设备驱动的引入是主要解决资源和驱动的问题,简称分离的思想,如果我们在开发引脚时,只需要更换资源就行了,驱动方面则不需要太大的变动,Linux内核提供了latform_device/platform_driver这个个结构体来进行关联,一个是平台设备,一个是平台驱动,本文章的目的是深究资源与驱动具体是如何进行关联的。


一、Linux总线的重要函数

1.1注册与销毁函数

首先,要先了解有什么函数去进行连接之后才能一步步的进行分析

int platform_device_register(struct platform_device *pdev)
void platform_device_unregister(struct platform_device *pdev)
这是两个注册与销毁的函数,我们使用总线设备时需要先进行注册,使用完毕后在进行销毁

1.2获得资源

truct resource *platform_get_resource(struct platform_device *dev,unsigned int type, unsigned int num)

该函数的作用是返回该dev(平台资源)中某类型(type)资源中的第几个(num):

1.3获得中断

int platform_get_irq(struct platform_device *dev, unsigned int num)

功能:获取该dev用到的第几个中断

1.4通过名字获得资源或者中断

struct resource *platform_get_resource_byname(struct platform_device *dev,unsigned int type,const char *name)int platform_get_irq_byname(struct platform_device *dev, const char *name)

顾名思义,可以通过名字来获取到你想要的那个资源或者中断,至于name是什么,可以后面在介绍

1.5同时注册多个dev

int platform_add_devices(struct platform_device **devs, int num)

通过二维数组存储多个dev,然后一一进行注册

二、总线设备里面含有什么结构体?

1.1从platform_device 开始

请添加图片描述

可以看到,里面有很多属性,重点关注上面几个,这个就是存储资源的结构体,那么,他的结构体存储在哪里呢,在 struct resource里面。

1.1.2 struct resource资源存储

在这里插入图片描述
比如我们可以把引脚号放在start里,中断放在flags里面

static struct resource resources[] = {{.start = GROUP_PIN(3,1),.flags = IORESOURCE_IRQ,},{.start = GROUP_PIN(5,8),.flags = IORESOURCE_IRQ,},
}

1.2与platform_driver结合

在这里插入图片描述

1.3platform_driver与platform_device 如何进行关联

在这里插入图片描述

可以说上面这个结构体是连接他们两个的桥梁,通过platform_match这个函数来进行比对,继续深入
在这里插入图片描述
看到了把,回到我们熟悉的C语言逻辑了,通过这几个变量来进行对比

在这之前要先关注平台驱动里的 driver结构体
platform_device
在这里插入图片描述

1.3.1比对规则

  1. 最先比较:platform_device. driver_override和platform_driver.driver.name
    可以设置platform_device的driver_override,强制选择某个platform_driver

  2. 然后比较:platform_device. name和platform_driver.id_table[i].name
    Platform_driver.id_table是“platform_device_id”指针,表示该drv支持若干个device,它里面列出了各个device的{.name, .driver_data},其中的“name”表示该drv支持的设备的名字,driver_data是些提供给该device的私有数据。

  3. 最后比较platform_device.name和platform_driver.driver.name
    platform_driver.id_table可能为空,
    这时可以根据platform_driver.driver.name来寻找同名的platform_device。

1.4 匹配成功后

当有匹配的platform_device时,它的probe函数就会被调用。
当进行设备卸载后remove函数则会被调用,我们可以在里面做自己想多的事

三.代码示范

3.1平台设备案例

#include <linux/module.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/platform_device.h>#include "led_opr.h"
#include "leddrv.h"
#include "led_resource.h"static int g_ledpins[100];
static int g_ledcnt = 0;static int board_demo_led_init (int which) /* 初始化LED, which-哪个LED */       
{   //printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);printk("init gpio: group %d, pin %d\n", GROUP(g_ledpins[which]), PIN(g_ledpins[which]));switch(GROUP(g_ledpins[which])){case 0:{printk("init pin of group 0 ...\n");break;}case 1:{printk("init pin of group 1 ...\n");break;}case 2:{printk("init pin of group 2 ...\n");break;}case 3:{printk("init pin of group 3 ...\n");break;}}return 0;
}static int board_demo_led_ctl (int which, char status) /* 控制LED, which-哪个LED, status:1-亮,0-灭 */
{//printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");printk("set led %s: group %d, pin %d\n", status ? "on" : "off", GROUP(g_ledpins[which]), PIN(g_ledpins[which]));switch(GROUP(g_ledpins[which])){case 0:{printk("set pin of group 0 ...\n");break;}case 1:{printk("set pin of group 1 ...\n");break;}case 2:{printk("set pin of group 2 ...\n");break;}case 3:{printk("set pin of group 3 ...\n");break;}}return 0;
}static struct led_operations board_demo_led_opr = {.init = board_demo_led_init,.ctl  = board_demo_led_ctl,
};struct led_operations *get_board_led_opr(void)
{return &board_demo_led_opr;
}static int chip_demo_gpio_probe(struct platform_device *pdev)
{struct resource *res;int i = 0;while (1){res = platform_get_resource(pdev, IORESOURCE_IRQ, i++);if (!res)break;g_ledpins[g_ledcnt] = res->start;led_class_create_device(g_ledcnt);g_ledcnt++;}return 0;}static int chip_demo_gpio_remove(struct platform_device *pdev)
{struct resource *res;int i = 0;while (1){res = platform_get_resource(pdev, IORESOURCE_IRQ, i);if (!res)break;led_class_destroy_device(i);i++;g_ledcnt--;}return 0;
}static struct platform_driver chip_demo_gpio_driver = {.probe      = chip_demo_gpio_probe,.remove     = chip_demo_gpio_remove,.driver     = {.name   = "100ask_led",},
};static int __init chip_demo_gpio_drv_init(void)
{int err;err = platform_driver_register(&chip_demo_gpio_driver); register_led_operations(&board_demo_led_opr);return 0;
}static void __exit lchip_demo_gpio_drv_exit(void)
{platform_driver_unregister(&chip_demo_gpio_driver);
}module_init(chip_demo_gpio_drv_init);
module_exit(lchip_demo_gpio_drv_exit);MODULE_LICENSE("GPL");

3.2资源设备案例


#include <linux/module.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/platform_device.h>#include "led_resource.h"static void led_dev_release(struct device *dev)
{
}static struct resource resources[] = {{.start = GROUP_PIN(3,1),.flags = IORESOURCE_IRQ,.name = "100ask_led_pin",},{.start = GROUP_PIN(5,8),.flags = IORESOURCE_IRQ,.name = "100ask_led_pin",},
};static struct platform_device board_A_led_dev = {.name = "100ask_led",.num_resources = ARRAY_SIZE(resources),.resource = resources,.dev = {.release = led_dev_release,},
};static int __init led_dev_init(void)
{int err;err = platform_device_register(&board_A_led_dev);   return 0;
}static void __exit led_dev_exit(void)
{platform_device_unregister(&board_A_led_dev);
}module_init(led_dev_init);
module_exit(led_dev_exit);MODULE_LICENSE("GPL");

这篇关于❤️⭐万字长文玩转总线设备驱动platform_device与platform_driver⭐❤️的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/206805

相关文章

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑燃料电池和电解槽虚拟惯量支撑的电力系统优化调度方法》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源程序擅长文章解读,论文与完整源程序,等方面的知识,电网论文源程序关注python

全英文地图/天地图和谷歌瓦片地图杂交/设备分布和轨迹回放/无需翻墙离线使用

一、前言说明 随着风云局势的剧烈变化,对我们搞软件开发的人员来说,影响也是越发明显,比如之前对美对欧的软件居多,现在慢慢的变成了对大鹅和中东以及非洲的居多,这两年明显问有没有俄语或者阿拉伯语的输入法的增多,这要是放在2019年以前,一年也遇不到一个人问这种需求场景的。 地图应用这块也是,之前的应用主要在国内,现在慢慢的多了一些外国的应用场景,这就遇到一个大问题,我们平时主要开发用的都是国内的地

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

Usb Audio Device Descriptor(10) Hid Device

对于 Standard Interface Descriptor, 当 bInterfaceClass=0x03时,即为HID设备。Standard Interface Descriptor如下 struct usb_standard_interface_descriptor{U8 bLength; /*Size of this descriptor in bytes*/U8 bDescrip

src/pyaudio/device_api.c:9:10: fatal error: portaudio.h: 没有那个文件或目录

(venv) shgbitai@shgbitai-C9X299-PGF:~/pythonworkspace/ai-accompany$ pip install pyaudio sounddeviceCollecting pyaudioDownloading PyAudio-0.2.14.tar.gz (47 kB)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

电脑驱动分类

电脑驱动程序(驱动程序)是操作系统与硬件设备之间的桥梁,用于使操作系统能够识别并与硬件设备进行通信。以下是常见的驱动分类: 1. 设备驱动程序 显示驱动程序:控制显卡和显示器的显示功能,负责图形渲染和屏幕显示。 示例:NVIDIA、AMD 显示驱动程序。打印机驱动程序:允许操作系统与打印机通信,控制打印任务。 示例:HP、Canon 打印机驱动程序。声卡驱动程序:管理音频输入和输出,与声卡硬件