我正在开发一个紧凑的调试输出/单元测试实用程序,用于嵌入式系统。
我创建了一个系统,我可以通过串口将信息以紧凑的方式输出到PC。 为了节省内存空间/串行端口带宽,我通过为它们提供唯一的16位ID来剥离嵌入式系统中的消息字符串。
这非常简单,因为我将所有消息放在1个列表中。一些宏将把它放入枚举中:
projectdefs.h:
#define MESSAGE_TABLE(MSG) \
MSG(HELLO, "Hello World!") \
MSG(TEST, "Second message #ID 1") \
MSG(TEST2, "Third message #ID 2")
messages.h:
#define MACRO_STR_CONCAT(a,b) a##b
#define MESSAGE_ENUM(codeName, str) MACRO_STR_CONCAT(MSG_, codeName)
typedef enum messageNumbers_e {
MESSAGE_TABLE(MESSAGE_ENUM),
MESSAGE_COUNT
};
#define MESSAGE(codeName) messageSend(MACRO_STR_CONCAT(MSG_, codeName), __LINE__, file_number);
通过串口传输的唯一数据是消息ID,行号和文件号(注意;不是字符串!)。
我遇到的问题是如何使用 C 预处理器/编译器为每个文件分配唯一的ID。我不想将每个文件名字符串存储在嵌入式程序中。这会在串行端口上使用(太多)内存或带宽。
我的想法是用宏定义每个文件中的常量file_number。我会在每个源文件的顶部使用此定义:
#define ASSIGN_FILENUMBER() enum { file_number = __COUNTER__ };
但是,由于每个文件是单独编译的,这意味着__COUNTER__
语句在调用时始终从0开始,并且不知道是否存在其他文件或它自己的ID。
另一个考虑因素是编辑MakeFile(脚本)并在那里添加文件ID号。但是,这会将项目构建/功能紧密地绑定到我的IDE配置,这是不可取的。 此外,我不确定我目前的IDE(Mplab X IDE或IAR Embedded Workbench上的XC16 / XC32编译器)的可能性。
我想知道是否还有其他创造性方法可以让标准 C 预处理器接管任务?
答案 0 :(得分:6)
我不确定在程序中存储源代码文件名对内存来说是如此重要。如果你可以拥有它们,那么你可以做的一件事就是声明一个像const char *fname = __FILE__;
之类的变量然后计算某种校验和,散列或CRC并传输这个值而不是文件名。在接收端,您可以将哈希值与其中一个文件名匹配。但是,您需要确保文件名哈希不会发生冲突。
另一种方法是使用您的makefile或perl或其他东西来维护文件计数器并将其作为宏提供给gcc,例如: gcc [someparams1] -DFILENUMBER=%FILECOUNTER% somefile.c [someparams2]
,其中%FILECOUNTER%
是任何表达式,它将作为文本扩展到文件计数器变量的值中。您可能需要在此处引入固定的源文件编译顺序。
您可以将这两种方法结合起来,并使用哈希而不是计数器来输入gcc,例如: -DFILENAMEHASH=%HASH%
,其中%HASH%
将扩展为编译脚本将根据文件名生成的数字常量。
答案 1 :(得分:1)
您是否考虑过根据 FILE 获得的内容创建一个16位哈希值?它可能不完美(读取碰撞),但如果可能足够满足您的需求。如果可以接受,则需要外部查找表,以便将哈希编号ID映射到相关文件。
希望这个想法有所帮助。