问题
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