本代码包适用于嵌入式 Linux 开发板(如 RK3399、树莓派、香橙派等),包含驱动代码、设备树片段、编译脚本、测试脚本,支持设备树与传统模块两种匹配方式,可直接编译验证 LED 控制功能。
plaintext
platform_led_driver/
├── driver/ # 驱动端代码
│ ├── platform_led_drv.c # 平台驱动核心代码(含字符设备接口)
│ └── Kconfig # 内核配置文件(可选,用于内核集成)
├── device/ # 传统设备端代码(可选,非设备树方式)
│ └── platform_led_dev.c # 平台设备代码(手动注册设备)
├── dts/ # 设备树片段(主流方式,推荐)
│ └── led_dts.dtsi # LED设备树节点(需集成到开发板DTS)
├── script/ # 辅助脚本
│ ├── led_test.sh # 一键加载/测试/卸载脚本
│ └── clean.sh # 清理编译产物脚本
├── Makefile # 通用编译脚本(支持跨平台)
└── README.md # 说明文档(本文件)
driver/platform_led_drv.c支持设备树匹配(优先级最高)和传统 id_table 匹配,实现 LED 点亮 / 熄灭逻辑,提供字符设备接口给用户空间。
c
运行
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
// 1. 基础配置(可根据开发板修改)
#define LED_DEV_NAME "platform-led" // 字符设备名称
#define LED_MAJOR 240 // 主设备号(若为0则自动分配)
#define LED_MINOR 0 // 次设备号
// 2. 全局变量
static int led_major = LED_MAJOR;
static int led_minor = LED_MINOR;
static dev_t led_devno; // 设备号
static struct cdev led_cdev; // 字符设备对象
static void __iomem *led_reg_base; // LED寄存器虚拟地址(内存映射用)
static int led_gpio; // LED引脚(GPIO方式用,二选一)
// 3. 字符设备操作:LED点亮(open)
static int led_open(struct inode *inode, struct file *filp) {
// 方式1:内存映射(控制寄存器,如RK3399 GPIO寄存器)
if (led_reg_base) {
writel(readl(led_reg_base) | (1 << 0), led_reg_base); // 第0位置1(点亮)
}
// 方式2:GPIO函数(直接控制GPIO引脚,更通用)
if (gpio_is_valid(led_gpio)) {
gpio_set_value(led_gpio, 1); // 输出高电平(点亮)
}
printk(KERN_INFO "[LED-DRV] LED opened (turned ON)
");
return 0;
}
// 4. 字符设备操作:LED熄灭(release)
static int led_release(struct inode *inode, struct file *filp) {
// 方式1:内存映射
if (led_reg_base) {
writel(readl(led_reg_base) & ~(1 << 0), led_reg_base); // 第0位清0(熄灭)
}
// 方式2:GPIO函数
if (gpio_is_valid(led_gpio)) {
gpio_set_value(led_gpio, 0); // 输出低电平(熄灭)
}
printk(KERN_INFO "[LED-DRV] LED closed (turned OFF)
");
return 0;
}
// 5. 字符设备操作集合
static const struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.release = led_release,
};
// 6. 设备树匹配表(优先级1:设备树方式)
static const struct of_device_id led_of_match[] = {
{ .compatible = "vendor,platform-led" }, // 与设备树compatible对应
{ /* Sentinel */ } // 数组结尾必须为空
};
MODULE_DEVICE_TABLE(of, led_of_match); // 告知内核该匹配表
// 7. 传统id匹配表(优先级2:非设备树方式)
static const struct platform_device_id led_dev_id[] = {
{ "platform-led-dev", 0 }, // 与platform_led_dev.c的name对应
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(platform, led_dev_id);
// 8. 核心probe函数:匹配成功后执行(初始化硬件+注册字符设备)
static int led_probe(struct platform_device *pdev) {
int ret;
struct resource *mem_res; // 内存资源(方式1用)
struct device_node *np = pdev->dev.of_node; // 设备树节点(方式2用)
printk(KERN_INFO "[LED-DRV] Probe matched! Starting init...
");
// --------------------------
// 方式1:通过内存资源控制(适用于寄存器操作)
// ----------