news 2026/10/30 4:22:32

6-Platform总线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
6-Platform总线

什么是平台总线:

平台总线(Platformbus)是Linux内核中提供的一种虚拟总线,用于管理和组织与特定硬 件平台相关的设备和驱动。它充当了平台设备(platformdevice)和平台驱动(platformdriver) 之间的桥梁,负责将它们进行匹配和绑定。

但Linux 驱动开发里,几乎所有 “嵌入式硬件设备” 最终都会挂在某个总线上(平台总线只是其中最常用、最简单的一种)。IIC,SPI等等

平台总线模型的使用:

平台总线模型将一个驱动分成了两个部分,分别是device.c和driver.c:这样方便移植

  • device.c:用来描述硬件(比如硬件资源、寄存器地址、中断号等)
  • driver.c:用来控制硬件(比如初始化、读写、业务逻辑等)

通过名字匹配成功进入probe函数,deiver.c可以拿到device.c里面的硬件资源

platform_device:

两个重要结构体

struct platform_device { const char *name; int id; bool id_auto; struct device dev; u32 num_resources; //这个非常重要 struct resource *resource; };

start,end是起始,终止资源,flag是具体的资源类型,描述硬件

static struct resource my_device_resources[] = { [0] = { .start = 0xFDD60000, .end = 0xFDD60004, .flags = IORESOURCE_MEM, }, //中断资源 [1] = { .start = 13, .end = 13, .flags = IORESOURCE_IRQ, }, };

注册platform设备device

#include <linux/module.h> #include <linux/platform_device.h> #include <linux/ioport.h> #define MEM_START_ADDR 0xFEC30004 #define MEM_END_ADDR 0xFEC30008 #define IRQ_NUMBER 112 /* 硬件资源定义 */ static struct resource my_resources[] = { { .start = MEM_START_ADDR, .end = MEM_END_ADDR, //表示是一段地址 .flags = IORESOURCE_MEM, }, { //中断号 .start = IRQ_NUMBER, .end = IRQ_NUMBER, .flags = IORESOURCE_IRQ, }, }; /* 必须实现的 release 函数 */ static void my_platform_device_release(struct device *dev) { } /* 定义平台设备 */ static struct platform_device my_platform_device = { //用于driver匹配 .name = "my_platform_device", //id没啥用,就是显示的名字后面带一个序号比如a.1,-1不显示 .id = -1, .num_resources = ARRAY_SIZE(my_resources), .resource = my_resources, .dev.release = my_platform_device_release, }; /* 注册设备 */ static int __init my_platform_device_init(void) { int ret; ret = platform_device_register(&my_platform_device); if (ret) { printk(KERN_ERR "Failed to register platform device\n"); return ret; } printk(KERN_INFO "Platform device registered\n"); return 0; } /* 注销设备 */ static void __exit my_platform_device_exit(void) { platform_device_unregister(&my_platform_device); printk(KERN_INFO "Platform device unregistered\n"); } module_init(my_platform_device_init); module_exit(my_platform_device_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("topeet");

platform_driver:

#include <linux/module.h> #include <linux/platform_device.h> /* 探测函数:设备与驱动匹配成功后执行 */ static int my_platform_probe(struct platform_device *pdev) { printk(KERN_INFO "my_platform_probe: Probing platform device\n"); return 0; } /* 移除函数 */ static int my_platform_remove(struct platform_device *pdev) { printk(KERN_INFO "my_platform_remove: Removing platform device\n"); return 0; } /* 平台驱动结构体 */ static struct platform_driver my_platform_driver = { .probe = my_platform_probe, .remove = my_platform_remove, .driver = { .name = "my_platform_device", .owner = THIS_MODULE, }, }; /* 驱动注册 */ static int __init my_platform_driver_init(void) { int ret; ret = platform_driver_register(&my_platform_driver); printk(KERN_INFO "Platform driver initialized\n"); return 0; } /* 驱动注销 */ static void __exit my_platform_driver_exit(void) { platform_driver_unregister(&my_platform_driver); printk(KERN_INFO "Platform driver exited\n"); } module_init(my_platform_driver_init); module_exit(my_platform_driver_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("topeet");

probe函数编写:

注意参数为struct platform_device *,说明可以拿到硬件资源了,匹配成功的话 static int my_platform_driver_probe(struct platform_device *pdev) { }

获取资源类型API

/* pdev:指向要获取资源的平台设备(platform_device)结构体的指针。 type:指定资源的类型,可选值包括: IORESOURCE_MEM:表示内存资源 IORESOURCE_IO:表示 I/O 资源 IORESOURCE_IRQ:表示中断资源 其他资源类型的宏定义可在 <linux/ioport.h> 和 <linux/irq.h> 头文件中找到。 num:指定要获取的资源的索引。当一个设备中存在多个相同类型的资源时,通过该索引选择特定资源。 */ struct resource *platform_get_resource(struct platform_device *pdev, unsigned int type, unsigned int num);

比如下面,就可以拿到资源了

// 方法2:使用 platform_get_resource() 获取硬件资源 res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res_mem) { dev_err(&pdev->dev, "Failed to get memory resource\n"); return -ENODEV; } res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res_irq) { dev_err(&pdev->dev, "Failed to get IRQ resource\n"); return -ENODEV; }

编写LED驱动:只写了主要的

unsigned int* vir_gpio_dr; res_mem=platform_get_resource(pdev,IORESOURCE_MEM,0); vir_gpio_dr=ioremap(res_mem->start,4); //将物理地址转化为虚拟地址

接下来就可以操作vir_gpio进行点灯了

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/30 4:21:54

传感器融合实战:从卡尔曼滤波到HyperFrame超帧框架

第一次在自动驾驶项目里预研传感器融合方案时&#xff0c;我看到了 HyperFrame 这个名字。坦白说&#xff0c;最初我以为这只是又一个卡尔曼滤波的封装库&#xff0c;随手 clone 下来准备跑个 demo 交差。真正把它用起来之后才发现&#xff0c;这个框架对“传感器融合”这件事的…

作者头像 李华
网站建设 2026/10/30 4:18:59

Hy3-oQ2e常见问题解答:新手入门到高级使用的10大痛点解决

Hy3-oQ2e常见问题解答&#xff1a;新手入门到高级使用的10大痛点解决 Hy3-oQ2e是HuggingFace镜像项目mlx-community中的重要组成部分&#xff0c;为用户提供高效的模型访问与使用体验。本文将针对新手入门到高级使用过程中可能遇到的10大痛点问题进行详细解答&#xff0c;帮助用…

作者头像 李华
网站建设 2026/10/30 4:17:45

打造专属智能音箱:小米设备自定义固件改造全攻略

打造专属智能音箱&#xff1a;小米设备自定义固件改造全攻略 【免费下载链接】xiaoai-patch Patching for XiaoAi Speakers (小爱音箱), add custom binaries and open source software. Tested on LX06, LX01, LX05, L09A 项目地址: https://gitcode.com/GitHub_Trending/xi…

作者头像 李华
网站建设 2026/10/30 4:15:27

如何快速上手Qwen3.5-122B-A10B-OptiQ-2bit:5分钟在Mac上部署超大语言模型

如何快速上手Qwen3.5-122B-A10B-OptiQ-2bit&#xff1a;5分钟在Mac上部署超大语言模型 Qwen3.5-122B-A10B-OptiQ-2bit是一款基于Apple Silicon优化的2bit量化超大语言模型&#xff0c;通过OptiQ技术实现了在普通Mac设备上运行1220亿参数模型的突破。本文将带你5分钟完成从环境准…

作者头像 李华
网站建设 2026/10/30 4:13:40

Kimi-K3-mlx-reap160-2bit完全指南:从模型特性到部署优化的终极教程

Kimi-K3-mlx-reap160-2bit完全指南&#xff1a;从模型特性到部署优化的终极教程 Kimi-K3-mlx-reap160-2bit是一款基于MLX框架构建的高效能AI模型&#xff0c;通过专家剪枝和量化技术&#xff0c;实现了在192GB Apple Silicon设备上的本地运行。本教程将全面介绍该模型的核心特…

作者头像 李华