GPIO 配置与使用

GPIO, 全称 General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚。

以下通过控制 ROC-RK3399-PC Pro 的 LED 为例,对于其他设备,方法是类似的。

ROC-RK3399-PC Pro 的主控是 RK3399,RK3399 有 5 组 GPIO bank:GPIO0~GPIO4,每组又以 A0~A7, B0~B7, C0~C7, D0~D7 作为编号区分。

GPIO 编号计算

ROC-RK3399-PC Pro 板载两个 LED,如下:

_images/gpio_led_1.png

DIY_LED 网络是接到引脚 GPIO0_B5:

_images/gpio_led_2.png

PIO pin 脚计算公式:

pin = bank * 32 + number

GPIO 小组编号计算公式:

number = group * 8 + X

例如 GPIO0_B5:

bank = 0;      // GPIO0_B5 => 0, bank ∈ [0,4]
group = 1;     // GPIO0_B5 => 1, group ∈ {(A=0), (B=1), (C=2), (D=3)}
X = 5;         // GPIO0_B5 => 5, X ∈ [0,7]
number = group * 8 + X = 1 * 8 + 5 = 13;
pin = bank * 32 + number = 0 * 32 + 13 = 13;

注意:这个引脚在官方发布的固件中默认已被 LED 子系统占用,因此首先需要找到以下节点将其 disable!

ROC-RK3399-PC Pro 是定义在arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi

user {
        status = "disabled"; // 添加这一行
        label = "firefly:yellow:user";
        linux,default-trigger = "ir-user-click";
        default-state = "off";
        gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
        pinctrl-names = "default";
        pinctrl-0 = <&led_user>;
};

然后编译与重新烧写内核固件。

用户态使用 GPIO

1、申请 GPIO

echo 13 > /sys/class/gpio/export

2、配置引脚方向

查看默认引脚方向:

cat /sys/class/gpio/gpio13/direction

配置成输出方向:

echo out > /sys/class/gpio/gpio13/direction

3、配置引脚输出电平

从前面的原理图可知,输出高电平为点亮 LED:

echo 1 > /sys/class/gpio/gpio13/value

熄灭 LED:

echo 0 > /sys/class/gpio/gpio13/value

设备树使用 GPIO

在设备树中配置 GPIO,需要配置引脚的功能复用与电气属性

对于 rockchip 引脚,配置如下:

rockchip,pins = <PIN_BANK PIN_BANK_IDX MUX &phandle>

其中:

  • PIN_BANK:引脚所在的 bank

  • PIN_BANK_IDX:引脚所在 bank 的引脚号

  • MUX:功能复用配置,0 表示普通 GPIO,1-N 表示特殊的功能复用

  • phandle:引脚一般配置,例如内部上拉、电流强度等,在Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt文件中描述

配置 GPIO0_B5 引脚:

rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_none>;

此处的含义:

  1. PIN_BANK等于0

  2. PIN_BANK_IDX等于13

  3. RK_FUNC_GPIO代表使用普通 GPIO 功能

  4. pcfg_pull_none代表普通配置

对于 LED,Linux 定义了一套 GPIO 子系统,设备树的配置如下:

/ {
	gpio_led: gpio-led {
		compatible = "gpio-leds";

		diy_led: diy-led {
			label = "diy-led";
			default-state = "on"; // 默认打开
			linux,default-trigger = "default-on"; // 默认触发
			gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; // 引脚设置
			pinctrl-names = "default";
			pinctrl-0 = <&diy_led_pin>; // 引用 pinctrl
		};
	};
};

&pinctrl {
	gpio-led-pin {
		diy_led_pin: diy-led-pin {
			rockchip,pins =
				<0 13 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
};

然后编译与重新烧写内核固件,重启系统会看到 LED 默认点亮。

如果希望 LED 具有闪烁效果,可以修改linux,default-trigger属性实现:

linux,default-trigger = "timer";

配置该属性后,LED 默认每 500ms 间隔闪烁。

更多属性配置可以参考Documentation/devicetree/bindings/leds/leds-gpio.txt

以上设备树配置可以在arch/arm64/boot/dts/rockchip/firefly-gpio-demo.dtsi找到!有需求的用户在板极设备树中包含该文件即可(记得要首先 disable rk3399-roc-pc.dtsi里面冲突部分):

#include "firefly-gpio-demo.dtsi"