当前位置: 首页 > news >正文

平台设备总线相关概念(RK3588)

平台设备总线

平台设备总线相关概念

平台设备总线是一条虚拟的总线

平台设备总线会将驱动程序划分成两部分

设备端

主要的作用就是向内核注册设备的资源信息

向内核注册用来匹配的信息:比如说 led 灯

设备端需要向内核注册的资源的信息主要有:

gpio 口引脚的编号

有效电平

数据和控制寄存器的地址和值

驱动端

首先向内核注册一个用来匹配设备端的信息

当设备端和驱动端匹配成功之后

驱动端就需要取获取设备端注册的资源

拿获取的资源来实现驱动程序

平台设备总线的意义

平台设备总线将一个完整的驱动程序拆分成了两部分,这样写驱动程序的好处是能够提高代码复用率,在有设备树的时候可以不写代码就可以实现驱动程序

平台设备总线的分层

平台设备总线将驱动拆分成了两部分

设备端

向内核注册资源的信息

向内核注册匹配的信息

驱动端

向内核注册匹配的信息

获取设备端向内核注册的资源信息

拿着获取到的资源的信息实现驱动程序

平台设备总线代码的实现

设备树+平台设备总线的驱动端

设备端+平台设备总线的驱动端

平台设备总线设备层的实现方法

led 灯需要的资源主要有:gpio 口引脚的编号,有效电平

也是就是说在设备端需要向内核注册的资源信息主要就是这两项

除了资源信息以外,还需要向内核注册一个用来匹配驱动端的一个名字,总体来说设备端要向内核注册的东西

匹配的名字

gpio 口引脚的编号

有效电平

platform_device_register向内核注册平台设备总线的设备的信息

函数的头文件

linux/platform_device.h

函数的原型

int platform_device_register(struct platform_device *pdev)

函数的参数

struct platform_device *pdev: 平台设备总线设备端的核心结构体

函数的返回值

成功返回 0

失败返回 -1

核心结构体

struct platform_device {
const char *name; 	名字 用来跟平台设备总线的驱动端做匹配
int id; 			-1
struct device dev; 	设备相关的结构体
这个结构体里的 release 	函数必须要实现哪怕是一个空的函数体都可以
u32 num_resources; 		资源的数目 多少类资源
struct resource *resource; 用来存放要向内核注册的资源的结构体
};
struct resource {
resource_size_t start; 	资源的起始位置
resource_size_t end; 	资源的结束的位置
const char *name;		资源的名字
unsigned long flags; 	资源的类型 内存资源
};

platform_device_unregiste取消平台设备总线设备端的注册

函数的头文件

linux/platform_device.h

函数的原型

void platform_device_unregister(struct platform_device *pdev)

函数的参数

struct platform_device *pdev: 平台设备总线设备端的核心结构体

函数的返回值

实例

#include <linux/kernel.h>// 包含内核相关头文件
#include <linux/module.h>// 包含模块相关头文件
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>struct platform_device mypdev;
struct resource	myres[2];int myopen (struct inode *inode, struct file *file)
{return 0;
}int myclose (struct inode *inode, struct file *file)
{return 0;
}
void myrelease (struct device *dev)
{}static int __init myled_init(void)
{myres[0].start = 0;//无效电平myres[0].end = 1;//有效电平myres[0].name = "led1";myres[0].flags = IORESOURCE_MEM;//内存资源myres[1].start = 21;//引脚起始位置myres[1].end = 22;//引脚结束位置myres[1].name = "led2";myres[1].flags = IORESOURCE_MEM;//内存资源mypdev.name = "lqhled";//与驱动端名字相匹配mypdev.id = -1;mypdev.dev.release = myrelease;mypdev.num_resources = 2;//两类资源mypdev.resource = 	myres;//1向内核注册平台设备总线的设备的信息platform_device_register(&mypdev);return 0;
}static void __exit myled_exit(void)
{platform_device_unregister(&mypdev);//取消注册
}module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");

平台设备总线驱动层的实现方法

平台设备总线驱动端,最终想要的是获取平台设备总线设备端注册的资源,并使用获取到的资源的信息来实现驱动的框架。

平台设备总线下(内核里)有很多的设备端,驱动端要想拿到准确的那个设备端注册的资源信息,就需要找到合适那个设备端,需要有一个能够相互匹配的东西。平台设备总线驱动端在获取资源之前要先向内核注册用来匹配的信息。

platform_driver_register平台设备总线的驱动端向内核注册用来匹配的信息

函数的头文件

linux/platform_device.h

函数的原型

int platform_driver_register(struct platform_driver *drv)

函数的参数

struct platform_driver *drv: 平台设备总线驱动端的核心结构体

函数的返回值

成功返回 0

失败返回 -1

结构体

struct platform_driver {
int (*probe)(struct platform_device *); 设备端和驱动端匹配成功以后调用的函数
int (*remove)(struct platform_device *); 设备端和驱动端有一端被卸载会调用的函数
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver; 这个结构体里的 name就是用来匹配设备端
const struct platform_device_id *id_table; 另外的一种匹配的方式
};

platform_driver_unregister取消平台设备总线驱动端的注册

函数的头文件

linux/platform_device.h

函数的原型

void platform_driver_unregister(struct platform_driver *drv)

函数的参数

struct platform_driver *drv: 平台设备总线驱动端的核心结构体

函数的返回值

platform_get_resource获取平台设备总线设备端注册的资源

函数的头文件

linux/platform_device.h

函数的原型

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

函数的参数

struct platform_device *dev, 设备端的结构体

unsigned int type, 资源的类型

unsigned int num 资源的数组的下标

函数的返回值

成功返回 资源的结构体指针

失败返回 NULL

实例

#include <linux/kernel.h>// 包含内核相关头文件
#include <linux/module.h>// 包含模块相关头文件
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>struct platform_driver mydrv;int myopen (struct inode *inode, struct file *file)
{return 0;
}int myclose (struct inode *inode, struct file *file)
{return 0;
}int myprobe (struct platform_device *dev)
{printk("匹配成功\n");return 0;
}int myremove(struct platform_device *dev)
{printk("有一端被删除了\n");return 0;}static int __init myled_init(void)
{mydrv.driver.name = "lqhled";mydrv.probe = myprobe;mydrv.remove = myremove;platform_driver_register(&mydrv);//平台设备总线的驱动端向内核注册用来匹配的信息return 0;
}static void __exit myled_exit(void)
{platform_driver_unregister(&mydrv);}module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");

平台设备总线和设备树的使用

平台设备总线配合设备树使用的时候

设备树相当于平台设备总线的设备层

设备树用来跟平台设备总线的驱动层匹配的是 compatibe 属性

实例

#include <linux/kernel.h>// 包含内核相关头文件
#include <linux/module.h>// 包含模块相关头文件
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/device.h>struct file_operations myfops;struct miscdevice  mymsic;
int gpio_num,level;
enum of_gpio_flags  myflags;struct platform_driver mydrv;struct of_device_id	myid={.compatible="LQHXX",};
int myopen (struct inode *inode, struct file *file)
{gpio_set_value(gpio_num, level);return 0;
}int myclose (struct inode *inode, struct file *file)
{gpio_set_value(gpio_num, !level);return 0;
}int myprobe (struct platform_device *dev)
{printk("设备树匹配成功\n");gpio_num= of_get_named_gpio(dev->dev.of_node, "LQH-gpios", 2);of_get_named_gpio_flags(dev->dev.of_node, "LQH-gpios", 2, &myflags);if(myflags==OF_GPIO_ACTIVE_LOW){level=0;}else{level=1;}gpio_request(gpio_num,"led");gpio_direction_output(gpio_num,!level);myfops.owner = THIS_MODULE;myfops.open = myopen;myfops.release = myclose;mymsic.minor = 255;mymsic.name = "myled";mymsic.fops =  &myfops;misc_register(&mymsic);return 0;
}int myremove(struct platform_device *dev)
{printk("有一端被删除了\n");return 0;}
static int __init myled_init(void)
{mydrv.driver.name ="test";mydrv.driver.of_match_table =&myid ;mydrv.probe = myprobe;mydrv.remove = myremove;platform_driver_register(&mydrv);return 0;
}static void __exit myled_exit(void)
{platform_driver_unregister(&mydrv);
}module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");
http://www.dtcms.com/a/268096.html

相关文章:

  • 多模态大模型推理技术突破:从 CoT 数据到 RL 优化,AI 推理如何征服复杂任务?
  • 开源!RAG竞技场(2):标准RAG算法
  • 编程语言艺术:C语言中的属性attribute笔记总结
  • RPC/gRPC入门学习
  • GM DC Monitor和WGCLOUD,能比吗?
  • 深入理解原子类与CAS无锁编程:原理、实战与优化
  • 【大模型LLM】 Megatron-LM 大模型训练框架吞吐率计算吞吐率优化策略
  • Rust实战:中医丹方智能管理系统
  • ipmitool 使用简介(ipmitool sel list ipmitool sensor list)
  • WebRTC 的 ICE candidate 协商
  • 【卫星语音】基于神经网络的低码率语音编解码(ULBC)方案架构分析:以SoundStream为例
  • 开关电源抄板学习
  • linux chrome浏览器打不开了
  • 线程——基础全解
  • 第一个Flink 程序:词频统计 WordCount(流处理)
  • Peek-Ubuntu上Gif录制工具-24.04LTS可装
  • rxcpp--composite_subscription
  • Kotlin lazy 委托的底层实现原理
  • bottles安装网易云出现的问题02任务卡死没法关闭
  • 【AI大模型】Spring AI 基于mysql实现对话持久存储详解
  • QT6 源(157)模型视图架构里的列表窗体视图 QListWidget :属性,成员函数,槽函数与信号函数,以及源代码带注释。
  • 【运算放大器专题】基础篇
  • 11.进程间通信
  • nginx的使用
  • Qt:QPushButton、QRadioButton、QCheckBox
  • 数据结构:数组:反转数组(Reverse the Array)
  • SQL Server从入门到项目实践(超值版)读书笔记 20
  • 二进制安全-汇编语言-02-寄存器
  • CPT208-Human-Centric Computing: Field Study and Analytics实地研究与分析
  • 【网络安全基础】第六章---Web安全需求