如何通过慢速CAN总线进行printf样式调试 – 在远程工具上使用常量字符串,而不是嵌入式系统

目前,在我的嵌入式系统(用C编码)中,我有很多调试辅助打印语句,当远程工具连接到可以向PC显示消息的系统时执行。 这些有助于理解一般系统状态,但由于消息通过慢速CAN总线,我相信它们可能会堵塞管道并导致其他问题,试图获取任何有用的数据。

它的基本要点是:

它就像一个printf,但最终采用特殊的消息格式,通过CAN总线从嵌入式系统发送到工具。 为此,我可以使用特殊的调试消息替换此通用打印消息,该消息向其发送唯一ID,后跟仅变量参数(即argc / argv)。 我想知道这是否是正确的方法,或者是否有一个我错过的魔法子弹,或者其他我没有想到的东西。

所以,我发现这个问题很适合我的目的:

printf()使用字符串表“解码器环”调试库

但我没有限制使它像printf一样简单。 我可以在远程工具端维护一个字符串表(因为它是Windows可执行文件,因此不受代码大小限制)。 我是负责此代码的唯一负责人,并且希望在调试时尝试减轻代码大小以及CAN总线流量。

我现在的想法是这样的:

printf("[%d] User command: answer call\n", (int)job); 

这变成了

 debug(dbgUSER_COMMAND_ANSWER_CALL, job); 

dbgUSER_COMMAND_ANSWER_CALL是可能的调试消息枚举的一部分

而遥远的一面有类似的东西

 switch(messagetype) { case dbgUSER_COMMAND_ANSWER_CALL: /* retrieve an integer from the data portion of the message and put it into a variable */ printf("[%d] User command: answer call\n", (int)avariable); } 

这是相对简单的,如果我的所有消息都采用相同的格式,那就太棒了。 但是,它变得棘手,我的一些语句必须打印不是常量的字符串(例如,设备的名称)。

 printf("[%d] %02X:%02X:%02X:%02X:%02X:%02X (%s)\n", /* a bunch of parameters here */); 

所以,我应该这样做,以便调试消息的内容是1)消息类型,2)第一个参数的长度,3)参数,4)下一个参数的长度,5)参数,等等和等等

或者我忽略了一些更明显或更容易的事情?

谢谢

我假设您使用CAN,因为这是您已经拥有的设备连接。 您还没有真正提供有关诊断需求的足够信息,但我可以举例说明我们在哪里工作。 我们使用自定义构建工具来梳理构建字符串表的源代码。 我们的代码使用类似:

  log( LOGH(T0722T), //"Position" LOG_DOT_HEX_VALUE(i), LOG_TEXT(T0178T), //"Id" LOG_DOT_VALUE(uniqueId % 10000), 0 ); 

这会记录一些可以解码成的数据:

H Position.00B Id.0235

我们允许使用T0000T让工具查找(或生成)一个唯一的数字给我们。 该工具使用编译器的TxxxxT编号和包含有序字符串列表的文件构建枚举。 每个构建都会生成一个与枚举编号匹配的字符串表。 该系统还与用于生成国际化字符串的数据库系统相关联,但这与您的问题无关。

每个元素都是一个短(16位)。 我们允许12位用于值,并使用高4位用于类型和标志信息。 编码数据是否为字符串id; 它是一个信号(高/低)还是只是一个事件; 这是一个价值; 是十进制,hex,base64url; 连接(与前面的项目)或分开。

我们将数据记录在一个大的环形缓冲区中,以便在需要时进行查询。 这允许系统在没有干扰的情况下运行,但是如果注意到问题则可以提取数据。 当然可以不断发送数据,如果需要,我建议将任何一条消息限制为单个CAN有效负载(假设您只使用一个ID,则为8个字节)。 如果正确编码,我上面提供的消息将适合一条CAN消息(假设接收方创建了时间戳)。

我们确实能够包含任意数据(ASCII或hex),但我从不使用它。 这通常浪费了原木中的宝贵空间。 记录始终是嵌入式环境中的平衡。