Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

FreeRTOS_debug_printf double quotes

Posted by friesen on June 5, 2018

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

Posted by rtel on June 5, 2018

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

Posted by heinbali01 on June 6, 2018

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 world\n" ) );

FreeRTOS_debug_printf double quotes

Posted by davidbrown on June 6, 2018

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 FreeRTOSdebugprintf(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

Posted by friesen on June 6, 2018

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

Posted by heinbali01 on June 6, 2018

~~~

define FreeRTOSdebugprintf( X ) PrintUart X

~~~


FreeRTOS_debug_printf double quotes

Posted by friesen on June 7, 2018

Thank you.


FreeRTOS_debug_printf double quotes

Posted by heinbali01 on June 7, 2018

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

Posted by davidbrown on June 7, 2018

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 FreeRTOSdebugprintf( X,... ) PrintUart( X "r",##VA_ARGS) > #endif > ~~~ > > Which fails unless I remove the extra parenthesis. > >


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS v10.2.1 is available for immediate download. MIT licensed, includes 64-bit RISC-V, NXP Cortex-M33 demo & Nuvoton Cortex-M23 demo.

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Cadence Tensilica Cortes

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Mediatek

Renesas

RISC-V

SiFIve RISC-V

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner