【问题标题】:How are device tree blobs actually used from an embedded application?嵌入式应用程序如何实际使用设备树 blob?
【发布时间】:2020-09-13 23:11:12
【问题描述】:

我正在尝试了解 device tree 的工作原理。我已经阅读了一些文档,或多或少地了解了什么是 dtsdtsidtb 文件。

我不太了解的是如何从最终应用程序访问dtb 文件中的信息。我一直在阅读zephyr os 文档和一些 linux 内核来理解这一点,但对我来说仍然不是很清楚。

我现在所理解的是最终应用程序(可能是操作系统内核)“手动”读取和解析 dtb 文件。这意味着每个操作系统内核都会以自己的方式解析dtb文件,对吗?

但是,据我了解,该应用程序未链接到dtb 文件,后者在某些内存区域中闪存,然后是应用程序。以某种方式访问​​它。那么,如果这些符号在构建时不可用,如何构建应用程序?

【问题讨论】:

    标签: embedded kernel device-tree zephyr-rtos


    【解决方案1】:

    免责声明:我不是 Linux 内核专家。

    我猜你的问题已经回答了here。 是的,每个操作系统内核都会以自己的方式解析 DTB 文件。在 Linux 的情况下, 例如,DTB 将由 u-boot 读取,u-boot 将启动 Linux 内核并传递它加载 DTB BLOB 的地址。

    在下面的示例中,u-boot 会将内核和 DTB 从 FAT 文件系统加载到内存中,然后将控制权转移到地址 0x80300000 处的内核,同时告诉它其 DTB BLOB 将在地址 0x815f0000 处可用:

    fatload mmc 0:1 0x80300000 zImage
    fatload mmc 0:1 0x815f0000 beagle-xm.dtb
    bootz 0x80300000 - 0x815f0000
    

    DTB BLOB 确实包含两个 符号名称及其相关值。应用程序将使用一些专门用于读取 DTB 格式的代码,例如 libfdt,以从其符号名称中检索值。现在不需要在构建它时了解 DTB 内容。这确实允许相同的编译内核在不修改的情况下在不同的硬件上运行,DTB 中描述了各种硬件功能。

    为了让操作系统有效地访问 DTB 中包含的信息,信息将使用 libfdt 从 DTB BLOB 中提取一次,然后放入有效的数据结构中。例如,从“扁平化”格式转换为“扩展”格式。

    我强烈建议阅读:

    请注意,Zephyr 方法不是标准的:当开放固件/设备树方案被设计为允许应用程序和硬件描述的“后期绑定”时,他们选择了更静态的方法。

    Zephyr 实际上使用了一个自定义工具来处理 DTB 文件并生成包含相同信息的 C 头文件,这些文件以符合某些命名约定的宏的形式出现。这可能是您对 DTB 内容和使用它的应用程序绑定在一起的确切阶段感到困惑的原因。

    不要尝试使用 Zephyr 提升设备树概念。 此外,他们的工具还远非完美,在处理完全有效的 DTB 文件时会卡住。

    将 DTB 绑定到驱动程序的 Linux 内核驱动程序代码摘录:

    static const struct platform_device_id mxs_auart_devtype[] = {
        { .name = "mxs-auart-imx23", .driver_data = IMX23_AUART },
        { .name = "mxs-auart-imx28", .driver_data = IMX28_AUART },
        { .name = "as-auart-asm9260", .driver_data = ASM9260_AUART },
        { /* sentinel */ }
    };
    MODULE_DEVICE_TABLE(platform, mxs_auart_devtype);
    
    static const struct of_device_id mxs_auart_dt_ids[] = {
        {
            .compatible = "fsl,imx28-auart",
            .data = &mxs_auart_devtype[IMX28_AUART]
        }, {
            .compatible = "fsl,imx23-auart",
            .data = &mxs_auart_devtype[IMX23_AUART]
        }, {
            .compatible = "alphascale,asm9260-auart",
            .data = &mxs_auart_devtype[ASM9260_AUART]
        }, { /* sentinel */ }
    };
    MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
    

    在 Zephyr 代码中找到一个等效的(虽然不同的驱动程序):

    #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(flexcomm5), nxp_lpc_spi, okay)
        /* Attach 12 MHz clock to FLEXCOMM5 */
        CLOCK_AttachClk(kFRO_HF_to_FLEXCOMM5);
        
        /* reset FLEXCOMM for SPI */
        RESET_PeripheralReset(kFC5_RST_SHIFT_RSTn);
    #endif
    

    【讨论】:

      猜你喜欢
      • 2015-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-23
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多