简而言之,有效的 DTS 文件在通过 C 预处理器运行后的最终文本状态是什么?
#include
指令到底应该留下什么? dtc
应该容忍多少? Linux 标头是否必须经过特殊布局才能支持包含在 DTS 文件中?
为了乐趣和利润,我正在向 FreeRTOS 项目添加设备树支持。为此,我需要添加构建支持以实际生成 DTB 并将其嵌入到最终的二进制文件中。第一步是在 DTS 上运行预处理器以转换 C 定义。然后将此预处理后的 DTS 馈送到
dtc
以创建最终的 DTB。
我拥有所有的构建集成和此类工作,但我被预处理步骤绊倒了。我在网上看到了很多帖子,这些帖子都是here指定的参数的变体;我的具体咒语(我目前正在使用 CMake)是:
"${CMAKE_C_COMPILER}" "-D$<JOIN:$<TARGET_PROPERTY:${COMPONENT_LIB},COMPILE_DEFINITIONS>,$<SEMICOLON>-D>"
"-I$<JOIN:$<TARGET_PROPERTY:${COMPONENT_LIB},INCLUDE_DIRECTORIES>,$<SEMICOLON>-I>"
-E -P --undef __ASSEMBLER__ -x assembler-with-cpp -o "${CURRENT_DTS_PREPROCESS}" "${CURRENT_DTS}"
此命令成功完成,但后续
dtc
步骤无法解析预处理的 DTS,并出现语法错误。如果我检查这些错误,就会发现它们都在 C 声明中,并且在处理器中仍然存在。例如,以下是预处理输出的前几行:
/dts-v1/;
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef short int __int16_t;
typedef short unsigned int __uint16_t;
typedef int __int32_t;
typedef unsigned int __uint32_t;
typedef long long int __int64_t;
...
大概要考虑的第一个包含文件是
stdint.h
或类似文件,因此首先是所有固定宽度类型的定义。 dtc
报告的第一个语法错误是 /path/to/dts.preprocess:4.1-8 syntax error
,它与第一个 typedef
标记(带有尾随空格)完全对应。
那么,设备树编译器应该容忍这种情况,还是我在咒语中遗漏了一些东西来删除所有不是
#define
替换的 C 定义?还是还有其他事情在起作用?
根据 Linux 内核邮件列表的讨论 以及 @JohnBollinger 和 @sawdust 的评论,看起来 Linux 标头必须经过专门设计才能支持包含到设备树中。具体来说,它们被有意设置为不包含不是有效 DTS 语法的 C 指令。真糟糕。
据我所知,在不复制/重新处理标头的情况下执行此操作的唯一方法是在 C 预处理器之后但在
dtc
调用之前执行另一个处理步骤以去除剩余的 C 垃圾。这是留给读者的练习。