3. 配置板卡引脚复用
任务目标
在Zephyr板卡设备树中定义pinctrl节点,为UART和GPIO外设配置引脚复用功能,并通过设备树编译与运行时API验证引脚配置正确。
环境依赖
本案例基于Zephyr RTOS 3.4+,使用nRF52840DK作为目标板(引脚定义与Nordic SoC一致)。需要安装Zephyr SDK与west工具链,并已创建基础BSP工程。
实现步骤
在板卡设备树文件(boards/arm/your_board/your_board.dts)中完成以下操作:
- 定义
pinctrl根节点,包含UART0和GPIO0的引脚状态组; - 为UART0配置TX/RX引脚复用(P0.06/P0.08);
- 为GPIO0配置LED引脚(P0.13)为输出模式;
- 在
&uart0和&gpio0节点中通过pinctrl-0引用对应状态。
关键完整代码
以下为your_board.dts中pinctrl配置的核心片段(完整文件需包含SoC头文件与其它外设节点):
#include "your_board_common.dtsi"
&pinctrl {
uart0_default: uart0_default {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 6)>,
<NRF_PSEL(UART_RX, 0, 8)>;
nordic,drive-mode = <NRF_DRIVE_H0H1>;
bias-pull-up;
};
};
gpio0_default: gpio0_default {
group1 {
psels = <NRF_PSEL(GPIO_OUTPUT, 0, 13)>;
drive-push-pull;
};
};
};
&uart0 {
compatible = "nordic,nrf-uarte";
current-speed = <115200>;
pinctrl-0 = <&uart0_default>;
pinctrl-names = "default";
status = "okay";
};
&gpio0 {
status = "okay";
pinctrl-0 = <&gpio0_default>;
pinctrl-names = "default";
};
若SoC使用nrf-gpio而非gpio0节点名,需按实际SoC头文件调整。GPIO的pinctrl状态通常仅用于特殊引脚(如模拟功能),普通数字GPIO可直接在gpio0节点下配置,无需pinctrl——此处为演示完整pinctrl语法而保留。
验证方法
- 编译验证:执行
west build -b your_board,若设备树存在语法错误或引脚冲突,编译将失败并提示具体节点与属性问题。 - 运行时验证:在应用代码中调用以下API确认引脚状态:
#include <zephyr/kernel.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/gpio.h>
void verify_pinctrl(void) {
const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
const struct device *gpio = DEVICE_DT_GET(DT_NODELABEL(gpio0));
// 检查UART设备就绪
if (!device_is_ready(uart)) {
printk("UART not ready\n");
return;
}
// 检查GPIO引脚可写
gpio_pin_configure(gpio, 13, GPIO_OUTPUT);
gpio_pin_set(gpio, 13, 1);
printk("Pinctrl config verified\n");
}
通过条件:编译无错误;烧录后串口输出Pinctrl config verified;用逻辑分析仪或万用表测量P0.13引脚为高电平(3.3V),P0.06/P0.08在UART空闲时为高电平。
常见问题
- 引脚冲突:若两个外设使用同一引脚,编译时会出现
pin already assigned错误,需检查psels定义。 - 状态组命名:Zephyr要求pinctrl状态组名唯一,且
pinctrl-names中的字符串必须与pinctrl-0等属性顺序对应。 - SoC差异:不同SoC的
NRF_PSEL宏参数含义不同,需查阅对应SoC的dts/arm/nordic头文件。