FreeRTOS_debug_printf double quotes

What is the purpose of wrapping all the FreeRTOSdebugprintf params in double quotes in freertos+tcp? This makes it rather awkward to port to an existing output. In other words, everything is like FreeRTOSdebugprintf((“Hello %irn”,123)); which looks like one param, at least to xc32

FreeRTOS_debug_printf double quotes

It is because it is a macro rather than a function, and having the double quotes allows a variable number of parameters to be passed as a single parameter.

FreeRTOS_debug_printf double quotes

FreeRTOSdebugprintf double quotes
Not double quotes but double parentheses. This way of logging is not uncommon in public libraries. In every FreeRTOSIPConfig.h you will see this code that should explain it: ~~~ extern int lUDPLoggingPrintf( const char *pcFormatString, … ); /* Set to 1 to print out debug messages. If ipconfigHASDEBUGPRINTF is set to 1 then FreeRTOSdebugprintf should be defined to the function used to print out the debugging messages. */

ifndef ipconfigHASDEBUGPRINTF

#define ipconfigHAS_DEBUG_PRINTF    1

endif

if( ipconfigHASDEBUGPRINTF == 1 )

#define FreeRTOS_debug_printf(X)    lUDPLoggingPrintf X

else

/* Define it as an empty statement so that a semicolon can be placed safely after it. */
#define FreeRTOS_debug_printf(X)    do {} while( 0 )

endif

/* Set to 1 to print out non debugging messages, for example the output of the FreeRTOSnetstat() command, and ping replies. If ipconfigHASPRINTF is set to 1 then FreeRTOS_printf should be set to the function used to print out the messages. */

ifndef ipconfigHAS_PRINTF

#define ipconfigHAS_PRINTF            1

endif

if( ipconfigHAS_PRINTF == 1 )

#define FreeRTOS_printf(X)            lUDPLoggingPrintf X

else

#define FreeRTOS_printf(X)            do {} while( 0 )

endif

~~~ The FreeRTOS_debug_printf() is quite detailed, whereas FreeRTOS_printf() will only log essential events and problems. Once you release your device, you may want to disable all logging. The GNU compiler has ellipses in its macro syntax, so we could wwrite:
#define FreeRTOS_printf( format, ... )
but many other compilers get stuck on the three dots. We could also demand that a user defines a function:
void FreeRTOS_printf( const char *pcFormat, ... )
and use single parenthesis. You will get used to the double parentheses:
FreeRTOS_printf( ( "Hello worldn" ) );

FreeRTOS_debug_printf double quotes

Hi, Note that it is not gcc that has the variadic macro support – it is C99. Any C99 compiler will support it (though gcc has a couple of neat extensions to make it better). But FreeRTOS, AFAIU, is C90 compatible and thus does not use any C99 features. (Personally, I’d like to see C90 support dropped in future versions of FreeRTOS – compilers and C programmers have had about 20 years to catch up, and have no excuse for not supporting C99. C99 would bring a lot of benefits to FreeRTOS, such as in this case. Of course, changing to a better syntax here would mean backwards incompatible changes – these things are never pain-free.) An alternative way to handle this sort of thing would have been to write:

if( ipconfigHASDEBUGPRINTF == 1 )

#define FreeRTOS_debug_printf    lUDPLoggingPrintf

else

/* Define it as an empty statement so that a semicolon can be placed
safely after it. */ #define FreeRTOS_debug_printf(X) do {} while( 0 )

endif

Then the FreeRTOSdebugprintf macro would have taken exactly the same arguments as lUDPLoggingPrintf. mvh., David

FreeRTOS_debug_printf double quotes

Thanks for that explanation, and yes, I mean parenthesis, not quotes. What is the proper way to define this then? I did it like ~~~ void PrintUart(const char* format, …) { //My print code here } ~~~ In FreeRTOSIPConfig.h ~~~

define ipconfigHASDEBUGPRINTF 1

if ( ipconfigHASDEBUGPRINTF == 1 )

#define FreeRTOS_debug_printf( X,... )    PrintUart( X "r",##__VA_ARGS__)

endif

~~~ Which fails unless I remove the extra parenthesis.

FreeRTOS_debug_printf double quotes

~~~

define FreeRTOSdebugprintf( X ) PrintUart X

~~~

FreeRTOS_debug_printf double quotes

Thank you.

FreeRTOS_debug_printf double quotes

Hi David, thanks for this information again. ~~~

define FreeRTOSdebugprintf lUDPLoggingPrintf

define FreeRTOSdebugprintf(X) do {} while( 0 )

~~~ … and the above would have been a nicer solution.

FreeRTOS_debug_printf double quotes

Hi, The way you are defining it is the C99 way. It will then look like a normal function or function-like macro – you don’t need double parenthesis. But it also means that you /can’t/ have double parenthesis, and it is thus inconsistent with the current FreeRTOS way (which is designed to work with C90). It would be nice if FreeRTOS could take advantage of the improvements in modern C, but consistency and backwards compatibility are vital – so my advice is to use Hein’s recommendation. Don’t forget that your version added a “r”, while Hein’s does not. Incidentally, if your code is going to be compiled with gcc, then I strongly recommend a gcc extension here: extern void PrintUart(const char* format, …) attribute((format(printf, 1, 2))); This well let gcc check that your format string and the parameters match up. mvh., David On 06/06/2018 15:38, Erik wrote:
Thanks for that explanation, and yes, I mean parenthesis, not quotes. What is the proper way to define this then? I did it like ~~~ void PrintUart(const char* format, …) { //My print code here } ~~~ In FreeRTOSIPConfig.h ~~~

define ipconfigHASDEBUGPRINTF 1

if ( ipconfigHASDEBUGPRINTF == 1 )

 #define FreeRTOS_debug_printf( X,... )    PrintUart( X "r",##__VA_ARGS__)

endif

~~~ Which fails unless I remove the extra parenthesis.