Linux Platform 总线 LED 驱动实战代码包

  • 时间:2025-11-27 22:23 作者: 来源: 阅读:9
  • 扫一扫,手机访问
摘要:        本代码包适用于嵌入式 Linux 开发板(如 RK3399、树莓派、香橙派等),包含驱动代码、设备树片段、编译脚本、测试脚本,支持设备树与传统模块两种匹配方式,可直接编译验证 LED 控制功能。 一、代码包目录结构 plaintext platform_led_driver/ ├── d

        本代码包适用于嵌入式 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              # 说明文档(本文件)

二、核心文件内容详解

1. 驱动端代码: 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:通过内存资源控制(适用于寄存器操作)
    // ----------
  • 全部评论(0)
手机二维码手机访问领取大礼包
返回顶部