8

我正在开发用于嵌入式系统的紧凑型调试输出/单元测试实用程序。

我创建了一个系统,可以通过串行端口以紧凑的方式将消息输出到 PC。为了节省内存空间/串行端口带宽,我通过为它们提供唯一的 16 位 ID,从嵌入式系统中剥离了消息字符串。

这非常简单,因为我将所有消息都放在了 1 个列表中。一些宏会将其放入枚举中:

项目定义.h:

#define MESSAGE_TABLE(MSG) \
    MSG(HELLO, "Hello World!") \
    MSG(TEST, "Second message #ID 1") \
    MSG(TEST2, "Third message #ID 2")

消息.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预处理器接管任务?

4

2 回答 2

6

我不确定在程序中存储源代码文件名对内存来说有多大意义。如果你可以拥有它们,那么你可以做的一件事是声明一个变量const char *fname = __FILE__;,然后计算某种校验和、哈希或 CRC,并传输这个值而不是文件名。在接收端,您可以将哈希值与其中一个文件名匹配。不过,您需要确保文件名哈希不会发生冲突。

另一种方法是使用您的makefile 或perl 或其他东西来维护文件计数器并将其作为宏提供给gcc,例如,将扩展为文件计数器变量值作为文本的任何表达式gcc [someparams1] -DFILENUMBER=%FILECOUNTER% somefile.c [someparams2]在哪里。%FILECOUNTER%您可能需要在此处引入固定的源文件编译顺序。

您可以将这两种方法结合起来,并使用哈希而不是计数器来提供 gcc,例如-DFILENAMEHASH=%HASH%,其中%HASH%将扩展为您的编译脚本将根据文件名生成的数字常量。

于 2013-04-28T13:54:54.167 回答
1

您是否考虑过根据您从FILE获得的任何内容创建一个 16 位哈希数?它可能并不完美(读取冲突),但可能足以满足您的需求。如果可以接受,您将需要一个外部查找表,以便将您的哈希编号 ID 映射到相关文件。

希望这个想法有所帮助。

于 2013-04-28T14:11:09.893 回答