How can I do printf style debugging over a slow CAN bus - with constant strings on the remote tool, not the embedded system

醉酒当歌 提交于 2019-12-10 21:01:22

问题


Currently, on my embedded system (coded in C), I have a lot of debug-assistive print statements which are executed when a remote tool is hooked up to the system that can display the messages to a PC. These help to understand the general system status, but as the messages are going over a slow CAN bus, I believe they may be clogging the tubes and causing other problems with trying to get any useful data logged.

The basic gist of it is this:

It's like a printf, but ultimately in a special message format that gets sent from the embedded system to the tool over the CAN bus. For this purpose, I can replace this generic print message with special debugging messages that send it a unique ID followed by only the variable parameters (i.e. the argc/argv). I am wondering if that is the right way to go about it, or if there is a magic bullet I've missed, or something else I haven't thought of.

So, I found this question which starts out well for my purposes:

printf() debugging library using string table "decoder ring"

But I do not have the constraint of making it as easy as a printf. I can maintain a table of strings on the remote tool's side (since it's a Windows executable and therefore not as code size limited). I am the sole person responsible for this code and would prefer to try and lighten up the code size as well as the CAN bus traffic while debugging.

My current thoughts are thus:

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

This becomes

debug(dbgUSER_COMMAND_ANSWER_CALL, job);

dbgUSER_COMMAND_ANSWER_CALL being part of an enum of possible debug messages

and the remote side has something like

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);
}

That's relatively straightforward and it would be fantastic if all my messages came in that same format. Where it gets tricky, though, is where some of my statements have to print strings which are not constant (the name of the device, for example).

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

So, should I make it so that the contents of the debug message are 1) the message type, 2) length of the first parameter, 3) the parameter, 4) length of the next parameter, 5) the parameter, so on and so forth

Or have I overlooked something more obvious or easy?

Thanks


回答1:


I'm assuming you use CAN because that's the connection you already have to your device. You haven't really provided enough information about your diagnostic needs, but I can give an example of what we do where I work. We use a custom build tool to comb through our sources building up a string table. Our code uses something like:

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

This would record some data which could be decoded into:

<timestamp> H Position.00B Id.0235

We allow use of T0000T to have the tool lookup (or generate) a unique number for us. The tool builds up an enum using the TxxxxT numbers for the compiler, and a file containing the ordered list of strings. Every build generates a string table which matches the enum numbering. This system also ties into a database system used for generating internationalized strings, but that's not really relevant to your question.

Each element is a short (16 bits). We allow 12 bits for values and use the high 4 bits for type and flag info. Is the encoded data a string id; Is it a signal (High/Low) or just an event; Is it a value; Is it decimal, hexidecimal, base64url; concatenated (with the preceding item) or separate.

We record data in a large ring buffer for querying if needed. This allows the system to run without interference but the data can be extracted if a problem is noted. It is certainly possible to constantly send the data, and if that's desired I'd suggest limiting any one message to a single CAN payload (that's 8 bytes assuming you only use a single ID). The message I provided above would fit in one CAN message if properly encoded (assuming the receiving side created the timestamps).

We do have the ability to include arbitrary data (ASCII or Hexadecimal), but I never use it. It's usually a waste of precious space in the logs. Logging is always a balance in embedded environments.



来源:https://stackoverflow.com/questions/17864223/how-can-i-do-printf-style-debugging-over-a-slow-can-bus-with-constant-strings

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!