跳到主要内容

设备树

Kconfig 决定要不要编译 GPIO 支持,但它不能说明背光接在哪个引脚。这个信息来自设备树。Zephyr 在构建时处理它,不是像部分 Linux 场景那样在启动时装载一份 DTB。

设备树文件​

SoC 的 .dtsi 描述芯片控制器、地址、中断等;板卡 .dts 描述这些控制器在板上连到哪里;应用 overlay 在这份板卡描述上补充或覆盖本次应用需要的配置。

修改已有板子的一个应用,一般先写 overlay,不直接改上游板卡 DTS。新 PCB 才考虑独立板卡定义。

节点与属性​

learning-app 的 boards/waveshare.overlay 中有:

/ {
aliases {
learning-output = &learning_backlight;
};
learning_outputs {
compatible = "gpio-leds";
learning_backlight: backlight {
gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
};
};
};

逐项读:

  • learning_backlight: 是节点标签,其他属性用 &learning_backlight 引用。
  • backlight 是节点名,不等于 C 变量。
  • learning-output 是应用约定的别名,换板时可让它指向另一节点。
  • gpios 引用 GPIO 控制器、引脚 2 和有效电平;具体 cell 含义由控制器 binding 定义。
  • compatible 与 YAML binding 匹配,描述节点应具有什么属性。字符串本身不会凭空提供驱动。

这里借用 gpio-leds 的子节点描述背光 GPIO,不要求打开 LED 子系统;应用直接调用 GPIO API。

设备树访问宏​

static const struct gpio_dt_spec output =
GPIO_DT_SPEC_GET(DT_ALIAS(learning_output), gpios);

C 宏中的别名把连字符改为下划线。gpio_dt_spec 保存控制器设备、pin 和 flags。程序随后:

if (!gpio_is_ready_dt(&output)) {
return 0;
}
int ret = gpio_pin_configure_dt(&output, GPIO_OUTPUT_INACTIVE);

配置成功后才调用 gpio_pin_set_dt。这个 API 的 1 表示逻辑有效,是否输出物理高电平还取决于 ACTIVE_HIGH / ACTIVE_LOW。因此可通过设备树改变极性,不在业务代码里到处取反。

引脚复用​

GPIO2 若同时交给 LEDC PWM 和普通 GPIO,两个功能会争用同一硬件。完整 overlay 关闭了 ledc0 和原 pwmleds 节点,prj.conf 也关闭 PWM。本例只做背光开关,不同时做调光。

SPI、I2C、UART 通常还要配置 pinctrl:把芯片内部控制器信号映射到实际引脚。给设备写了 status="okay",不会自动替你查原理图挑引脚。

构建与核对​

执行 Kconfig 页的背光构建命令,检查日志里加载了 waveshare.overlay。然后:

cd ~/Projects/zephyr-main-workspace/zephyr
rg -n 'learning-output|learning_outputs|ledc|backlight' \
build/learning-backlight/zephyr/zephyr.dts

最终设备树应该能找到应用别名和 GPIO2,LEDC 节点应为 disabled。若想看生成宏,可检查:

build/learning-backlight/zephyr/include/generated/zephyr/devicetree_generated.h

这是排错材料,不直接修改。

烧录后预期背光每 500 ms 改变一次状态,完整亮灭周期约一秒。串口仍输出计数。仅背光变化,不会出现文字画面。

常用属性​

属性/概念要回答的问题
reg这个设备在所属总线上的地址是什么?I2C 常为器件地址,不能统一当内存地址
status这个实例是否参与当前配置?
pinctrl控制器信号走哪些引脚?
chosen系统应使用哪个实例做 console、display 等角色?
aliases应用约定的名称指向哪个节点?
compatible / binding该设备使用哪种属性定义和驱动匹配方式?

驱动通常通过设备树实例化并结合 Kconfig 编入;仍需检查驱动的具体实现与依赖。常见 __device_dts_ord_... 链接错误意味着代码引用了设备,但对应设备对象没有生成,可能是驱动配置或实例状态问题,不是让你手工定义该符号。

练习:只把 ACTIVE_HIGH 改为 ACTIVE_LOW,先预测日志不变而亮灭相反,再上板观察;结束后恢复。不要随意换 GPIO 验证,未查原理图的引脚可能连接其他器件。

来源:Devicetree HOWTO、本地板卡 DTS 和 dts/bindings/gpio/gpio-leds.yaml。