1. GPIO LED控制

任务目标

在RK3588开发板上编写Linux内核GPIO驱动,控制一个LED引脚实现亮灭与闪烁功能,并提供用户空间验证路径。本案例采用sysfs接口作为控制通道,驱动注册后在 /sys/class/leds/ 下生成设备节点,用户通过写入 brightness 和 trigger 属性即可控制LED。

环境与依赖

  • 内核源码树:RK3588 Linux SDK(内核版本5.10或更高)
  • 交叉编译工具链:aarch64-linux-gnu-gcc
  • 开发板已能启动Linux并支持模块动态加载(CONFIG_MODULES=y)
  • 硬件连接:LED正极经限流电阻接GPIO引脚(本例以GPIO0_B2为例,对应引脚编号计算见下文),负极接GND

GPIO编号计算

RK3588使用GPIO控制器分组管理引脚,每组包含A/B/C/D四组,每组8个引脚。GPIO0_B2的编号计算方式为:组基数 + 组内偏移。RK3588的GPIO0基数为32,B组偏移为8,B2即偏移8+2=10,因此GPIO0_B2对应系统GPIO编号为 32 + 8 + 2 = 42。若使用其他引脚,请按此公式换算。

关键完整代码

以下驱动基于LED子系统(leds-gpio),利用内核标准框架避免重复实现字符设备操作,代码短且完整:

// rk3588_led.c
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>

#define LED_GPIO 42  // GPIO0_B2

static struct gpio_led led_data = {
    .name = "rk3588:user",
    .default_trigger = "none",
    .gpio = LED_GPIO,
    .active_low = 0,
};

static struct gpio_led_platform_data led_pdata = {
    .num_leds = 1,
    .leds = &led_data,
};

static struct platform_device led_device = {
    .name = "leds-gpio",
    .id = -1,
    .dev = {
        .platform_data = &led_pdata,
    },
};

static int __init led_init(void)
{
    return platform_device_register(&led_device);
}

static void __exit led_exit(void)
{
    platform_device_unregister(&led_device);
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("RK3588 GPIO LED driver");

该驱动注册一个 leds-gpio 平台设备,内核的 leds-gpio 驱动会接管该设备,自动完成GPIO申请、方向设置和sysfs节点创建。无需手动实现文件操作接口。

编译与部署

# 在SDK内核目录下创建驱动文件后,添加Makefile条目
obj-m += rk3588_led.o

# 编译(使用SDK提供的环境脚本)
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=$(pwd) modules

# 将生成的 rk3588_led.ko 拷贝到开发板,加载
insmod rk3588_led.ko

验证方法

加载模块后执行以下命令验证功能:

# 1. 确认设备节点已创建
ls /sys/class/leds/
# 预期输出包含:rk3588:user

# 2. 点亮LED
echo 255 > /sys/class/leds/rk3588:user/brightness
# 观察LED应常亮

# 3. 熄灭LED
echo 0 > /sys/class/leds/rk3588:user/brightness
# 观察LED应熄灭

# 4. 闪烁(使用内核心跳触发器)
echo "heartbeat" > /sys/class/leds/rk3588:user/trigger
# 观察LED应以约1Hz频率闪烁

# 5. 恢复手动控制
echo "none" > /sys/class/leds/rk3588:user/trigger
echo 255 > /sys/class/leds/rk3588:user/brightness

通过判定标准:上述5步操作中,LED状态与写入值一一对应,且 trigger 切换后闪烁行为正确,即表示驱动工作正常。若LED无响应,请检查GPIO编号是否与硬件连接一致,以及 dmesg 中是否有GPIO占用冲突提示。

常见问题

  • GPIO被占用:使用 cat /sys/kernel/debug/gpio 查看引脚状态,确认无其他驱动占用。
  • 引脚编号错误:RK3588的GPIO编号需按 组基数(32×组号) + 组内偏移 计算,不同Bank基数为32的整数倍。
  • LED不亮但无报错:检查 active_low 字段,若LED共阳接法需设为1。