Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #27079

Re: Efficient debug log

From David Brown <david.brown@hesbynett.no>
Newsgroups comp.arch.embedded
Subject Re: Efficient debug log
Date 2017-07-27 11:35 +0200
Organization A noiseless patient Spider
Message-ID <olcbta$891$1@dont-email.me> (permalink)
References <okpt2m$sok$1@dont-email.me> <nnd$5a9c0de5$7bdbc657@f8f0cd39675aa771> <ol482a$b09$1@dont-email.me> <nnd$2c7d62f4$0355e474@d9499a4098fdcb40>

Show all headers | View raw


On 27/07/17 10:06, Stef wrote:
> On 2017-07-24 David Brown wrote in comp.arch.embedded:
>> On 20/07/17 23:14, Stef wrote:
>>> On 2017-07-20 pozz wrote in comp.arch.embedded:
>>>> I usually prints some messages on a free UART used as a debug port. 
>>>> They are very useful during debugging to understand the flow of execution.
>>>>
>>>> Most of the time, I don't compile the debug log facility in release build.
>>>>
>>>> I sometimes need to disable messages from some modules and enable 
>>>> messages from other modules under debugging.
>>>> Moreover I sometimes need to enable/disable less important messages.
>>>>
>>>> Do you suggest some efficient implementation of debug log macros that 
>>>> include all the features above?
>>>
>>> If I have a output stream available for this purpose, I often use the
>>> following (assuming you use C):
>>>
>>> #ifdef DEBUG_ENABLE
>>> #define DEBUG_PRINTF(level, ...) ((level) <= (DebugLevel) ? fprintf(stderr, __VA_ARGS__) : (level))
>>> #else
>>> #define DEBUG_PRINTF(level, ...)
>>>
>>> Call like a normal printf, except there is an initial parameter for the 
>>> level of that paticular call.
>>>
>>> Lower the value of 'DebugLevel' to reduce the output.
>>>
>>
>> Yes, something like that is the way to do it.  That means in the code
>> itself, you avoid having any extra "#ifdef DEBUG_ENABLE" conditional
>> compilation that /really/ messes up the readability of the code.  You
>> just use DEBUG_PRINTF, safe in the knowledge that it does nothing when
>> debugging is disabled.
>>
>> The only unpleasant thing about this method is that if you have local
>> data that is only used for debugging, you are going to get warnings
>> about it when you disable debugging.  Since I like to have most of my
>> compiler warnings enabled, and like my code to be warning-free when
>> compiled, this bugs me.
> 
> This is true, but you could also argue that data only used for debugging
> should be removed as well when debugging is disabled. That will require
> inserting some additional #ifdefs in the code in places where debug-only
> data is used.

You certainly /can/ argue that.  It is not a good idea, usually, to have
code or data that is not in use.  It is a balance of choices, and you
have to pick the method that is clearest, most maintainable, and easiest
to be sure is correct.

> But mostly, i use the construct to print values of variables that are in
> use in normal code. And most often de DEBUG_PRINTF is not disabled at all,
> only the level lowered to a point where only things like startup and
> critical messages are emitted.
> 
>> So I have this definition:
>>
>> static inline int emptyFunctionX(int x, ...) { (void) x; return 0; }
>> #define emptyFunction(...) emptyFunctionX(0, ## __VA_ARGS__)
>>
>> Then when disabling debugging, I have:
>>
>> #define debugPrintf emptyFunction
>>
>> (I don't like defining a function as an expression in the way you did,
>> and I hate all-caps macro names for constants or function-like macros.)
> 
> But this requires you to write an actual debugPrintf function to handle
> the level comparison before calling the actual printf? But I look into
> it, might be a better solution is some situations.

I often have something like "debugPrintf" which would use snprintf to
put the formatted data into a buffer, then send it out on a UART.  It is
typically a good deal more efficient than using a library printf with a
fake file/stream output.

> And i love all-caps macro names for constants or function-like macros ;-)
> 

Many people use them.  Actually, I like that /other/ people use them,
such as in microcontroller peripheral definition headers - it means the
names don't conflict with my identifiers!

And I use all-caps for any macros that are passed via compiler command
lines (I don't use these much, but they can be a fine way to do parallel
builds of different variations of the same code).

But I have never been able to comprehend why someone would think you
should use all caps for:

#define SQRT2 1.4142135623730951

but not for

static const double sqrt2 = 1.4142135623730951;


Or why you should write:

#define VALID_PERCENT(x) (((x) >= 0) && ((x) <= 100))

and

static inline bool valid_percent(int x) {
	return ((x >= 0) && (x <= 100));
}


If the code that calls a "function" cares whether it is a real function
or a function-like macro, then that code is bad or the macro is bad.
Put braces on your if statements, put "do {...} while (0)" wrappers in
your multi-statement macros, never use expressions with side-effects in
your function arguments.


>>
>> "emptyFunction" uses a gcc extension here, but that's a common compiler
>> for many people.  It swallows any arguments without generating code, and
>> without requiring the arguments to be calculated at all (assuming you
>> have optimisation enabled), but considers the arguments "used" as far as
>> warnings are concerned.
> 
> Indeed a common compiler for me as well, but I have a few projects that
> use other compilers.
> 

Yes, me too.  I use gcc of preference whenever there is a choice - it is
one of the criteria I have for picking a microcontroller for a project.
 It is, in many ways, the best choice of tool for most of my work (I am
fully aware that one of the reasons gcc is a good choice for me is that
I use gcc so much).

If I have to use a different compiler, I will often also use gcc (for
any target) in parallel to do extra error checking.  Things like
__attributes__ are wrapped in conditional checks on __GNUC__.

Back to comp.arch.embedded | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Efficient debug log pozz <pozzugno@gmail.com> - 2017-07-20 11:31 +0200
  Re: Efficient debug log Anders.Montonen@kapsi.spam.stop.fi.invalid - 2017-07-20 10:35 +0000
  Re: Efficient debug log Stef <stef33d@yahooI-N-V-A-L-I-D.com.invalid> - 2017-07-20 23:14 +0200
    Re: Efficient debug log David Brown <david.brown@hesbynett.no> - 2017-07-24 09:40 +0200
      Re: Efficient debug log pozz <pozzugno@gmail.com> - 2017-07-26 11:15 +0200
        Re: Efficient debug log David Brown <david.brown@hesbynett.no> - 2017-07-26 14:24 +0200
        Re: Efficient debug log Stef <stef33d@yahooI-N-V-A-L-I-D.com.invalid> - 2017-07-27 10:23 +0200
          Re: Efficient debug log David Brown <david.brown@hesbynett.no> - 2017-07-27 11:14 +0200
      Re: Efficient debug log Stef <stef33d@yahooI-N-V-A-L-I-D.com.invalid> - 2017-07-27 10:06 +0200
        Re: Efficient debug log David Brown <david.brown@hesbynett.no> - 2017-07-27 11:35 +0200
  Re: Efficient debug log Clifford Heath <no.spam@please.net> - 2017-07-21 12:57 +1000
  Re: Efficient debug log Jack <jack4747@gmail.com> - 2017-07-20 23:17 -0700
  Re: Efficient debug log Chris <xxx.syseng.yyy@gfsys.co.uk> - 2017-07-29 12:47 +0000
    Re: Efficient debug log pozz <pozzugno@gmail.com> - 2017-07-31 10:45 +0200
      Re: Efficient debug log Chris <xxx.syseng.yyy@gfsys.co.uk> - 2017-07-31 16:44 +0000

csiph-web