从零构建RK3566 Linux GPIO驱动点亮LED的完整实战指南当你第一次拿到泰山派RK3566开发板时最令人兴奋的莫过于让硬件真正活起来。而控制GPIO点亮LED无疑是嵌入式Linux开发的Hello World。但不同于简单的代码编写完整的驱动开发涉及环境配置、内核机制理解、设备树修改、编译系统集成等多个环节。本文将带你从零开始用gpio3_B4引脚实现LED控制深入理解Rockchip平台下的Linux驱动开发全流程。1. 环境准备与硬件确认在开始编码前我们需要搭建一个高效的开发环境。推荐使用VS Code配合SSH远程开发既能利用本地编辑器的强大功能又能直接操作开发板。必备工具清单泰山派RK3566开发板及配套电源已安装USB转串口驱动的主机用于调试输出网线或Wi-Fi连接用于SSH传输预装VS Code及Remote-SSH扩展的开发机硬件连接确认步骤通过Type-C线连接开发板的调试串口通常是UART2使用串口工具如Putty或Minicom设置波特率为1500000上电后应能看到Uboot启动日志关键硬件信息确认# 登录开发板后查看GPIO控制器 cat /sys/kernel/debug/gpio # 查找gpiochip3对应的物理地址范围 dmesg | grep gpio提示瑞芯微平台的GPIO编号规则为gpioX_Y X32 Y。因此gpio3_B4对应的Linux GPIO编号为332 12 108B4中的B表示第2组4表示第4个引脚2. Linux GPIO驱动框架解析现代Linux内核通过gpiolib子系统抽象GPIO操作开发者应避免直接操作寄存器。Rockchip平台还引入了pinctrl子系统管理引脚复用。2.1 驱动基本结构典型的平台设备驱动包含以下组件// 设备匹配表 static const struct of_device_id led_match_table[] { { .compatible rockchip,rk3566-user-led }, {} }; // 平台驱动结构体 static struct platform_driver led_driver { .probe led_probe, .remove led_remove, .driver { .name rk3566-led, .of_match_table led_match_table, }, };2.2 GPIO操作关键API函数作用注意事项gpio_request()申请GPIO使用权必须检查返回值gpio_direction_output()设置为输出模式可同时设置初始电平gpio_set_value()改变输出电平需先配置为输出gpio_free()释放GPIO资源在remove函数中调用完整probe函数示例static int led_probe(struct platform_device *pdev) { struct device_node *np pdev-dev.of_node; int led_gpio; // 从设备树获取GPIO编号 led_gpio of_get_named_gpio(np, led-gpio, 0); if (!gpio_is_valid(led_gpio)) { dev_err(pdev-dev, Invalid GPIO\n); return -EINVAL; } // 申请并配置GPIO if (gpio_request(led_gpio, rk3566-led)) { dev_err(pdev-dev, GPIO request failed\n); return -EBUSY; } gpio_direction_output(led_gpio, 1); // 初始点亮LED // 保存GPIO编号到设备私有数据 platform_set_drvdata(pdev, (void *)led_gpio); return 0; }3. 设备树配置详解RK3566的设备树位于内核源码的arch/arm64/boot/dts/rockchip/目录。我们需要添加LED节点并配置pinctrl。3.1 基础节点添加在板级DTS文件中如tspi-rk3566-user-v10-linux.dts的根节点下添加user_led { compatible rockchip,rk3566-user-led; led-gpio gpio3 RK_PB4 GPIO_ACTIVE_HIGH; pinctrl-names default; pinctrl-0 pinctrl_user_led; status okay; };3.2 Pinctrl配置在pinctrl节点中添加引脚控制信息pinctrl { user-led { pinctrl_user_led: user-led-grp { rockchip,pins 3 RK_PB4 RK_FUNC_GPIO pcfg_pull_none; }; }; };关键参数说明RK_PB4Rockchip定义的引脚宏对应GPIO3_B4RK_FUNC_GPIO配置为GPIO功能非复用模式pcfg_pull_none禁用上下拉电阻注意RK3566的GPIO3控制器物理地址为0xFDD60000通过查看TRM手册可确认每个bank的偏移量4. 驱动编译与内核集成4.1 Makefile配置在drivers/gpio/目录下的Makefile中添加obj-$(CONFIG_GPIO_RK3566_LED) rk3566_led.o对应的Kconfig配置config GPIO_RK3566_LED tristate RK3566 User LED support depends on ARCH_ROCKCHIP || COMPILE_TEST default y help This enables support for user LED on RK3566 boards.4.2 内核编译命令使用Rockchip提供的构建脚本# 在内核根目录执行 ./build.sh kernel # 或传统编译方式 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- -j$(nproc)编译产物位置设备树DTBarch/arm64/boot/dts/rockchip/tspi-rk3566-user-v10-linux.dtb内核镜像arch/arm64/boot/Image5. 烧录与调试技巧5.1 烧录工具配置使用RKDevTool烧录时关键分区配置分区文件说明bootboot.img包含内核和dtbrootfsrootfs.img系统根文件系统5.2 驱动加载验证成功烧录后通过以下命令验证# 查看驱动加载日志 dmesg | grep rk3566-led # 检查GPIO状态 cat /sys/kernel/debug/gpio | grep gpio-108 # 手动控制GPIO可选 echo 0 /sys/class/gpio/gpio108/value # 熄灭LED echo 1 /sys/class/gpio/gpio108/value # 点亮LED常见问题排查GPIO申请失败检查设备树节点是否被正确解析无输出变化确认硬件连接测量引脚电压驱动未加载检查内核配置是否启用驱动6. 进阶创建用户空间接口为方便应用层控制可以添加sysfs或字符设备接口// 在probe函数中添加 device_create_file(pdev-dev, dev_attr_led_state); // 属性定义 static ssize_t led_state_show(struct device *dev, struct device_attribute *attr, char *buf) { int gpio (int)platform_get_drvdata(to_platform_device(dev)); return sprintf(buf, %d\n, gpio_get_value(gpio)); } static ssize_t led_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int val; int gpio (int)platform_get_drvdata(to_platform_device(dev)); if (kstrtoint(buf, 10, val)) return -EINVAL; gpio_set_value(gpio, val); return count; } static DEVICE_ATTR(led_state, 0644, led_state_show, led_state_store);使用示例# 查看当前状态 cat /sys/devices/platform/user_led/led_state # 改变LED状态 echo 0 /sys/devices/platform/user_led/led_state通过这个完整的开发流程你不仅学会了如何控制一个简单的LED更重要的是掌握了Rockchip平台下Linux驱动开发的标准方法。下次当开发板上的LED按照你的指令亮起时那闪烁的光芒正是嵌入式开发的魅力所在。