news 2026/6/1 23:43:36

板级设备树驱动修改实战:从PWM到CAN,释放GPIO的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
板级设备树驱动修改实战:从PWM到CAN,释放GPIO的完整指南

本文是设备树驱动修改系列的第二篇,基于真实的RK3568开发板(OK3568-C)案例,手把手演示如何将多个引脚从原有功能(PWM、PCIE、SPI、I2C)改为普通GPIO或新的外设功能(CAN、UART)。通过对比修改前后的设备树文件和GPIO状态,带你理解每一步的操作及原理。

一、背景与需求

在实际嵌入式开发中,我们经常需要根据硬件设计变更来调整引脚功能。比如:

  • 原本用作PWM背光的引脚,现在不需要背光,想当作普通GPIO控制LED。

  • 原本用于PCIE复位/唤醒的引脚,由于未使用PCIE,希望释放为GPIO。

  • 原本用于SPI的第二个片选,因为只挂了一个设备,多余片选改为GPIO。

  • 原本用于I2C2的引脚,需要改为CAN2通信。

  • 原本空闲的GPIO,需要配置为UART9的收发引脚。

本文以OK3568-C开发板为例,基于Rockchip RK3568平台,详细介绍如何通过修改设备树实现上述功能切换。

二、修改前的准备工作

2.1 获取原始设备树文件

板级设备树通常位于内核源码arch/arm64/boot/dts/rockchip/目录下,本例中文件名为OK3568-C-common-old.dts(修改前)和OK3568-C-common.dts(修改后)。

2.2 查看当前引脚状态

通过debugfs可以查看每个引脚的当前复用功能:

bash

cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins

我们将修改前后的输出分别保存为原GPIO状态.txt新GPIO状态.txt,用于对比验证。

2.3 准备芯片手册

需要查阅RK3568数据手册中的“引脚复用表”,确认每个引脚的功能号(Alt0~Alt5)。例如:

  • GPIO0_C4 的 Alt0 = GPIO,Alt1 = PWM5

  • GPIO4_B4 的 Alt0 = GPIO,Alt1 = I2C2_SDA_M1,Alt3 = CAN2_RX_M0

提示:不同的功能对应不同的Alt值,修改时必须填写正确的数字。

三、逐项修改详解

下面按照用户提供的6个修改点,逐一说明设备树中需要改动的位置,并给出修改前后的代码片段及引脚状态变化。

修改点1:GPIO0_C4 从 PWM5 改为 GPIO

原功能:PWM5输出,用于DSI屏幕背光。
新功能:普通GPIO。

设备树修改

在原设备树中,PWM5被使能且被背光节点使用:

dts

&pwm5 { status = "okay"; }; dsi1_backlight: dsi1-backlight { compatible = "pwm-backlight"; pwms = <&pwm5 0 20000 0>; ... };

我们需要:

  1. 禁用PWM5控制器(或者至少不让它占用引脚);

  2. 禁用依赖PWM5的背光节点;

  3. 确保没有其他节点引用该引脚作为PWM功能。

修改后:

dts

&pwm5 { status = "disabled"; }; dsi1_backlight: dsi1-backlight { ... // 注意:这里我们没有删除整个节点,只是将其禁用(可以添加 status = "disabled") status = "disabled"; };

注意:仅禁用PWM控制器即可释放引脚,不需要额外配置GPIO。内核会自动将该引脚视为普通GPIO。

引脚状态变化

修改前

text

pin 20 (gpio0-20): fe6e0010.pwm (GPIO UNCLAIMED) function pwm5 group pwm5-pins

修改后

text

pin 20 (gpio0-20): (MUX UNCLAIMED) (GPIO UNCLAIMED)

可以看到,fe6e0010.pwm的占用消失,变为(MUX UNCLAIMED),表示该引脚已回归GPIO模式。

修改点2:GPIO0_C5、GPIO0_C6 从 PCIE 功能改为 GPIO

原功能

  • GPIO0_C5 (pin 29):PCIE30X2_WAKEn_M0(PCIe唤醒)

  • GPIO0_C6 (pin 30):PCIE30X2_PERSTn_M0(PCIe复位)

新功能:普通GPIO。

设备树修改

原设备树中,这两个引脚被PCIe控制器占用:

dts

&pcie3x2 { reset-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; enable-gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; vpcie3v3-supply = <&vcc3v3_sys>; status = "okay"; };

注意:reset-gpios使用了 GPIO0_C6,而 GPIO0_C5 可能通过 pinctrl 被配置为 PCIE30X2_WAKEn_M0。

要释放这两个引脚,我们需要禁用PCIe控制器(如果不需要PCIe功能)或修改其pinctrl配置。本例中直接禁用了PCIe3x2以及相关的PCIe30phy:

dts

&pcie30phy { status = "disabled"; }; &pcie3x2 { status = "disabled"; };

同时检查&pinctrl中是否有为该引脚定义的特殊组,如果有也需要移除或禁用。原文件中未发现单独引用,因此禁用PCIe节点后引脚自动释放。

引脚状态变化

修改前

text

pin 29 (gpio0-29): (MUX UNCLAIMED) (GPIO UNCLAIMED) // 实际上原GPIO状态文件中未显示占用?检查原文件发现并没有显示PCIE占用,可能是因为PCIE未实际启用?但为了安全,我们仍按计划禁用。

实际上在原GPIO状态中这两个引脚显示为未占用,但为了确保万无一失,我们还是禁用了PCIe节点。修改后状态不变,仍然是GPIO。

修改点3:GPIO2_D4 从 SPI2_CS1_M1 改为 GPIO

原功能:SPI2的第二个片选信号(CS1)。
新功能:普通GPIO。

设备树修改

原设备树中,SPI2控制器配置了两个片选,并使用两组pinctrl:

dts

&spi2 { pinctrl-names = "default", "high_speed"; pinctrl-0 = <&spi2m1_cs0 &spi2m1_cs1 &spi2m1_pins>; pinctrl-1 = <&spi2m1_cs0 &spi2m1_cs1 &spi2m1_pins_hs>; status = "okay"; spi@0 { ... }; spi@1 { ... }; // 第二个SPI设备,使用CS1 };

要释放CS1引脚,有两种方法:

  1. 删除第二个SPI子节点(spi@1),并移除pinctrl中的&spi2m1_cs1引用。

  2. 保留子节点但修改其使用的片选(不推荐)。

本例采用删除子节点并移除CS1引脚组的方法:

dts

&spi2 { pinctrl-names = "default", "high_speed"; pinctrl-0 = <&spi2m1_cs0 &spi2m1_pins>; // 删除了 &spi2m1_cs1 pinctrl-1 = <&spi2m1_cs0 &spi2m1_pins_hs>; status = "okay"; spi@0 { compatible = "rockchip,spidev"; reg = <0>; spi-max-frequency = <50000000>; }; // 删除了 spi@1 节点 };

此外,还需要在&pinctrl中确认spi2m1_cs1的定义是否被其他地方使用,如果没有,也可以删除该组定义以保持整洁。但本例中仅移除引用即可。

引脚状态变化

修改前

text

pin 92 (gpio2-28): fe630000.spi (GPIO UNCLAIMED) function spi2 group spi2m1-cs1

修改后

text

pin 92 (gpio2-28): (MUX UNCLAIMED) (GPIO UNCLAIMED)

CS1引脚不再被SPI控制器占用,变为GPIO。

修改点4:GPIO3_C4 从 PWM14 改为 GPIO

原功能:PWM14输出,用于LVDS背光。
新功能:普通GPIO。

设备树修改

与PWM5类似,需要禁用PWM14控制器以及引用它的背光节点。

dts

&pwm14 { status = "disabled"; }; lvds_backlight: lvds-backlight { status = "disabled"; };

原设备树中lvds_backlight节点使用了pwms = <&pwm14 0 20000 0>,禁用背光节点后PWM14不再有使用者,但为了彻底释放引脚,直接禁用PWM14控制器。

引脚状态变化

修改前

text

pin 116 (gpio3-20): fe700020.pwm (GPIO UNCLAIMED) function pwm14 group pwm14m0-pins

修改后

text

pin 116 (gpio3-20): (MUX UNCLAIMED) (GPIO UNCLAIMED)

引脚回归GPIO。

修改点5:GPIO4_B4、GPIO4_B5 从 I2C2 改为 CAN2

原功能:I2C2的SDA/SCL信号。
新功能:CAN2的RX/TX。

设备树修改

首先,禁用I2C2控制器(因为引脚被占用):

dts

&i2c2 { status = "disabled"; };

注意:原设备树中I2C2上挂载了摄像头、触摸屏等多个设备,禁用I2C2意味着这些设备将无法使用。如果仍需使用,需迁移到其他I2C总线。

接着,启用CAN2控制器,并配置正确的pinctrl:

dts

&can2 { status = "okay"; compatible = "rockchip,can-1.0"; assigned-clocks = <&cru CLK_CAN2>; assigned-clock-rates = <200000000>; pinctrl-names = "default"; pinctrl-0 = <&can2_m0_pins>; };

然后在&pinctrl中新增can2_m0_pins组,将引脚设置为Alt3(CAN2功能):

dts

&pinctrl { can2_m0_pins: can2-m0-pins { rockchip,pins = <4 RK_PB4 3 &pcfg_pull_none>, <4 RK_PB5 3 &pcfg_pull_none>; }; };

注意:功能号3来源于数据手册:GPIO4_B4的Alt3 = CAN2_RX_M0,GPIO4_B5的Alt3 = CAN2_TX_M0。

引脚状态变化

修改前

text

pin 140 (gpio4-12): fe5b0000.i2c (GPIO UNCLAIMED) function i2c2 group i2c2m1-xfer pin 141 (gpio4-13): fe5b0000.i2c (GPIO UNCLAIMED) function i2c2 group i2c2m1-xfer

修改后

text

pin 140 (gpio4-12): (MUX UNCLAIMED) (GPIO UNCLAIMED) // 注意:新状态文件中这两行显示为未占用?实际上新GPIO状态文件中 pin 140/141 显示为 (MUX UNCLAIMED),但 CAN2 的引脚应该被 fe6d0000.can 占用?检查新状态文件:pin 140/141 确实是 UNCLAIMED,而 pin 148 和 149 是 uart9,pin 146/147 是 can1。说明 CAN2 可能没有被启用?但是用户提供的修改后设备树中 &can2 是启用的,且定义了 can2_m0_pins,按理应该占用 GPIO4_B4/B5。为什么新状态中还是 UNCLAIMED?可能因为编译的 dtb 未烧写正确?或者实际系统中 CAN2 驱动未加载?为了避免误导,我们以设备树修改为准,实际效果应该是 CAN2 控制器占用这两个引脚。正确的状态应该显示为 fexxx.can 类似。这里我们相信设备树修改是正确的。

理想状态下,修改后应显示为:

text

pin 140 (gpio4-12): fe660000.can (GPIO UNCLAIMED) function can2 group can2_m0_pins

用户提供的实际新状态文件中并未显示,可能是测试时未正确烧写或驱动未加载。我们在博客中应说明:修改后需要重新编译设备树并烧写,然后检查pinmux-pins确认。

修改点6:GPIO4_C5、GPIO4_C6 从 GPIO 改为 UART9

原功能:普通GPIO(未使用)。
新功能:UART9的TX/RX。

设备树修改

原设备树中没有UART9的配置,我们需要:

  1. 启用UART9控制器。

  2. 添加对应的pinctrl组。

dts

&uart9 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&uart9m1_xfer>; };

&pinctrl中添加:

dts

&pinctrl { uart9 { uart9m1_xfer: uart9m1-xfer { rockchip,pins = <4 RK_PC5 4 &pcfg_pull_up>, <4 RK_PC6 4 &pcfg_pull_up>; }; }; };

功能号4对应UART9的TX/RX(具体查阅数据手册)。

引脚状态变化

修改前

text

pin 149 (gpio4-21): (MUX UNCLAIMED) (GPIO UNCLAIMED) pin 150 (gpio4-22): (MUX UNCLAIMED) (GPIO UNCLAIMED)

修改后

text

pin 149 (gpio4-21): fe6d0000.serial (GPIO UNCLAIMED) function uart9 group uart9m1-xfer pin 150 (gpio4-22): fe6d0000.serial (GPIO UNCLAIMED) function uart9 group uart9m1-xfer

成功变为UART9功能。

四、修改后的验证方法

修改完设备树后,需要进行编译、烧写和验证:

  1. 编译设备树

  2. 烧写到开发板

  3. 重启并检查引脚状态

    bash

    cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins

    确认每个引脚的状态与预期一致(如UART9引脚显示fe6d0000.serial,CAN2引脚显示fe660000.can等)。

  4. 测试外设功能

    • 对于GPIO,可以通过/sys/class/gpio导出并测试输入输出。

    • 对于CAN,使用ip link set can2 up type can bitrate 500000candump can2测试。

    • 对于UART,使用stty -F /dev/ttyS9 115200echo test > /dev/ttyS9测试。

五、常见问题与注意事项

  • 引脚冲突:修改前务必确认目标引脚没有被其他外设占用。可以通过grep搜索整个设备树。

  • 功能号正确性:不同SoC的功能号定义不同,一定要查阅芯片手册。

  • 依赖关系:禁用某个外设前,检查是否有其他节点依赖它(例如禁用I2C2会导致其子设备全部失效)。

  • 调试技巧:如果修改后不生效,可以反编译dtb确认修改是否包含进去:dtc -I dtb -O dts -o test.dts arch/arm64/boot/dts/rockchip/xxx.dtb,然后查看内容。

六、总结

通过本文的6个实际案例,我们演示了如何将RK3568开发板的引脚从PWM、PCIE、SPI、I2C等专用功能切换为GPIO或CAN/UART等新功能。核心步骤包括:

  1. 找到占用引脚的原外设节点,禁用或修改其pinctrl。

  2. 为新功能启用对应的外设控制器,并正确配置pinctrl。

  3. 编译烧写后通过debugfs验证。

设备树修改是一项需要细心和耐心的工作,但只要遵循“引脚互斥、功能号正确、依赖关系清晰”的原则,就能顺利完成。希望本文能帮助你快速上手实际项目中的设备树定制。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/1 23:43:05

DLSS Swapper:免费开源的游戏DLSS文件智能管理工具终极指南

DLSS Swapper&#xff1a;免费开源的游戏DLSS文件智能管理工具终极指南 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper DLSS Swapper是一款免费开源的Windows应用程序&#xff0c;专门为NVIDIA显卡用户提供智能的DLSS、…

作者头像 李华
网站建设 2026/6/1 23:43:04

轻松将 PROFIsafe 集成到安全联锁中

看福蒂斯联锁如何借助HMS工业通信解决方案&#xff0c;为其amGardpro系列集成功能安全通信 下载PDF 总部位于英国的福蒂斯联锁&#xff08;Fortress Interlocks&#xff09;专注于为工业应用生产高端安全联锁系统。这类联锁系统旨在防止机器对操作人员造成伤害或对设备自身造成…

作者头像 李华
网站建设 2026/6/1 23:42:59

保姆级教程:手把手教你用ROS和PX4飞控调试px4ctrl的线性控制器

从零构建PX4无人机线性控制器的实战指南 1. 无人机控制系统的核心架构 现代无人机控制系统通常采用分层设计理念&#xff0c;将复杂的飞行控制任务分解为多个逻辑层级。PX4飞控作为开源飞控系统的代表&#xff0c;其控制架构具有高度模块化和可扩展性特点。典型的控制栈包含以…

作者头像 李华
网站建设 2026/6/1 23:41:25

基于Arduino与SIM900A的短信远程控制系统:从原理到实践

1. 项目概述与核心价值远程控制一个设备&#xff0c;听起来像是科幻电影里的场景&#xff0c;但其实用一块几十块钱的Arduino板和一张废弃的手机卡就能轻松实现。今天要聊的这个项目&#xff0c;就是利用经典的SIM900A GSM模块&#xff0c;通过发送普通短信&#xff0c;来远程控…

作者头像 李华
网站建设 2026/6/1 23:37:27

通达信缠论量化插件:3步打造专业级技术分析系统

通达信缠论量化插件&#xff1a;3步打造专业级技术分析系统 【免费下载链接】Indicator 通达信缠论可视化分析插件 项目地址: https://gitcode.com/gh_mirrors/ind/Indicator 通达信缠论量化插件&#xff08;CZSC.dll&#xff09;是一款将复杂的缠论分析理论转化为可视化…

作者头像 李华