注册 platform 设备实验

Linux 系统可以支持不同架构处理器和不同的开发板,例如迅为的 RK3568、2K1000 等开发
板都可以运行 Linux 系统。使用平台总线模型编写驱动程序可以让驱动程序有更好的重用性和
跨平台的能力。比如在 RK3568 开发板上编写的 LED 驱动程序,只需要很小的改动就可以放在
2K1000 开发板上运行。
平台总线模型也叫 platform 总线模型,平台总线是 Linux 虚拟出来的一条总线,并没有实际的 物理总线。平台总线模型把驱动分成了 device 和 driver 两部分,即 platform 设备与 platform 驱
动两部分。device 部分是硬件相关代码,因为不同的开发板或处理器描述硬件资源的代码不通
用,所以这部分代码被归类到 device 部分。driver 部分是通用的驱动逻辑代码,如在驱动代码
中操作 LED 灯亮灭,不同的开发板操作逻辑是一样的,所以把驱动代码单独拿出来归类到 driver
部分可以避免重复造轮子的工作。这样在不同开发板上移植相同驱动的时候,只需要单独编写
device 部分的硬件资源描述代码即可,driver 部分几乎无需改动,从而大幅提升驱动的兼容性
和可移植性。
platform_device.c 代码

cpp 复制代码
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>

#define MEM_START_ADDR 0xFDD60000
#define MEM_END_ADDR 0xFDD60004
#define IRQ_NUMBER 101

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, // 标记为中断资源
    },
};

static void my_platform_device_release(struct device *dev)
{
    // 释放资源的回调函数
}

static struct platform_device my_platform_device = {
    .name = "guosite_platform_device", // 设备名称
    .id = -1, // 设备 ID
    .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 v2");
MODULE_AUTHOR("topeet");

Makefile

cpp 复制代码
# 移除ARM64架构和交叉编译器配置,默认使用x86本地编译环境
# export ARCH=arm64  # 注释掉ARM64架构设置
# export CROSS_COMPILE=aarch64-linux-gnu-  # 注释掉交叉编译器前缀

obj-m += platform_devices.o  # 驱动源文件名称,保持不变

# 修改内核目录为x86系统的本地内核源码/头文件目录
# 方案1:使用系统当前运行内核的头文件(推荐,无需手动下载内核源码)
KDIR := /lib/modules/$(shell uname -r)/build
# 方案2:如果你有本地下载的x86内核源码,替换成对应的路径,例如:
# KDIR := /home/yourname/linux-x86-kernel  # 根据实际路径修改

PWD ?= $(shell pwd)

all:
	make -C $(KDIR) M=$(PWD) modules  # 本地编译x86内核模块

clean:
	make -C $(KDIR) M=$(PWD) clean  # 清理编译产物


cd /sys/bus/platform/devices

ls guosite_platform_device


sudo rmmod platform_devices.ko

相关推荐
xiaoye-duck10 分钟前
《Linux 网络编程》深入理解 IP 协议(二):网段划分、私有 IP 与 NAT 地址转换
linux·网络·ip
zx_741484811 小时前
【Linux入门】Shell 函数、正则表达式与文本处理:cut 与 awk
linux·运维·正则表达式
Zenova EdgeOS1 小时前
Linux dmesg 工业边缘实战:内核日志过滤、持久化与故障定位
linux·运维·边缘计算·工业边缘·dmesg·内核日志
金士顿1 小时前
System.Text.Json Source Generator 深度解析:为什么 Native AOT 不喜欢反射
linux·asp.net core·arm64·net·native aot
做运维的阿瑞2 小时前
Python 标准库汇总:分类速览与常用模块清单
linux·运维·python
百万蹄蹄向前冲3 小时前
密码都对Node.js却连不上Linux数据库
linux·mysql
彧azz3 小时前
Linux 网络编程学习总结
linux·网络·笔记·学习·面试
susplus4 小时前
【ARM 裸机开发 (IMX6ULL-mini)】GNU工具、Makefile 工程构建、链接脚本详解|C 语言点灯 + 蜂鸣器驱动
linux·arm·makefile·imx6ull
Shadow(⊙o⊙)4 小时前
Linux进阶知识1.0
linux·运维·服务器
>Andre<4 小时前
UFS5.0标准中文全译·卷一:范围、术语与架构
android·linux·嵌入式硬件