如何使用 DT_FOREACH_CHILD 在 Zephyr 中访问设备树 (DTS) 中的子节点

How to access the child nodes in a device tree (DTS) in Zephyr using DT_FOREACH_CHILD

我正在为 nRF52 SoC 开发一个应用程序来访问一些外部设备,在这种情况下是一种检测器,所以我为我的设备访问定义了一个自定义格式(及其相应的 yaml 文件)描述节点。它是这样的:

n: detectors {
    compatible = "foo-detectors";
        
    // Definition of first channel
    det0: det_0 {
        irq-pins = <13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
        label = "Bar detector channel 1";
    };
    // Definition of second channel
    det1: det_1 {
        irq-pins = <17 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
        label = "Bar detector channel 2";
    };
};

假设我有一个结构定义来保存关于这些设备物理连接到的引脚的数据,比如说:

struct foo_detector_desc { 
    int irqpin; 
    int irqpin_flags;
}

使用 Zephyr 宏,我可以在我的代码中使用这些节点的各个值。例如,DT_PROP_BY_IDX(DT_NODELABEL(det0), irq_pins, 0) 扩展为 13DT_PROP_BY_IDX(DT_NODELABEL(det0), irq_pins, 1) 扩展为 OR'ed 标志的值 GPIO_PULL_UP | GPIO_ACTIVE_LOW.

但我不想以 DT_NODE_EXISTS(DT_ALIAS(det#)) 的形式创建充满条件的十页代码,而是更紧凑、灵活和可维护的代码。

我遇到了 Zephyr 宏 DT_FOREACH_CHILD,它旨在用于我可以使用标签创建列表的场景,如文档中嵌入的示例所示:

#define LABEL_AND_COMMA(node_id) DT_LABEL(node_id),
const char *child_labels[] = {
    DT_FOREACH_CHILD(DT_NODELABEL(n), LABEL_AND_COMMA)
};

尝试使用它来填充静态结构数组,我尝试了以下代码,但它扩展为数组中的两个元素,结构字段未使用所需值初始化。

#define PIN_INFO_AND_COMMA(node_id) \
    { \
        .pin=DT_PROP_BY_IDX(node_id, irq_pins, 0),\
        .flags=DT_PROP_BY_IDX(node_id, irq_pins, 1),\
    },

const struct detector_data _det_data[] = {
    DT_FOREACH_CHILD(DT_NODELABEL(n), PIN_INFO_AND_COMMA)
};

我正在使用带有 nRF Connect 插件的 Visual Studio 代码。

有没有办法 generate/see 这些宏在编译时如何展开?

初始化结构字段(引脚、标志)的正确方法是什么?

BR

可以在 VS Code 中一次扩展一级宏。需要点击宏,然后 select 通过 double-clicking 它,最终会出现一个灯泡。选项 插入宏 将用扩展替换宏。

关于在代码中使用DTS,我之前post写的代码是可以的,但是我想我在调试器中发现了一个错误。如果我不包含任何使用 _det_data 值的代码,调试器不会说常量是 optimised-out 并在检查其内容时显示错误的值。那让我浪费了很多时间。

对于任何有兴趣在 Zephyr 中为 nRF 设备使用 DTS 文件的人,我 post 在 Nordic 开发者论坛的一个线程中编辑了所有详细信息 (here ).

BR