problems with snprintf and floating point numbers

sedfugit wrote on Tuesday, June 09, 2015:

System Details:
RTOS - FreeRTOSV8.1.2
Compiler - “GNU Tools ARM Embedded” toolchain version 4.8 2014q3
IDE - Eclipse Luna Service Release 1 (4.4.1)
Controller - STM32F429i Discovery board.

2 of the several tasks running in my application use snprintf to format floating point numbers
into independent buffers. One formats a single float, the other a list of about 14 floats.

If both tasks are allowed to call snprintf I receive corruption in the larger buffer.
A null is embedded. Interestingly, snprintf returns the correct string length processed but
strlen obviously reports a shorter string.

Is snprintf thread safe or can you suggest what may be wrong.

Many thanks.

rtel wrote on Tuesday, June 09, 2015:

What is providing the implementation of snprintf()? Is it coming from the C library, is it an implementation you provided yourself, or is it provided by the printf-stdarg.c file found in some of the FreeRTOS demos?


sedfugit wrote on Tuesday, June 09, 2015:


Sorry for the delay. I’ve been checking through the build.
The app is created using a series of makefiles.

When searching through the map file all the references to snprintf are on the path to the GNU ARM install

.data 0x20000a64 0x0 c:/program files (x86)/gnu tools arm embedded/4.8 2014q3/bin/…/lib/gcc/arm-none-eabi/4.8.4/…/…/…/…/arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-snprintf.o)

rtel wrote on Tuesday, June 09, 2015:

In which case I’m afraid I can’t help directly, although you could ask your questions to the tool’s maintainer.

I can provide generic ideas though:

In the past the only problems we have had with sprintf’ing floating point values have been related to stack alignment. However, in those cases it was just a matter of the value not being formatted correctly, whereas in your case it sounds like a thread safety issue. You could check the stack alignment just to be sure. Pause the debugger and look at the stack pointer - is its value divisible by 8?

The other thing you could do, if the function is not thread safe, is to place the code that uses the buffer (from the call to snprintf() to the end of the code that uses the output of snprintf() between calls to vTaskSuspendAll() and xTaskResumeAll(). That will prevent context switch for that duration.

Another option is to use another snprintf() implementation. I don’t think printf-stdarg.c supports floating point though, so you will have to find one elsewhere.


sedfugit wrote on Tuesday, June 09, 2015:

Thank you for your kind attention.

heinbali01 wrote on Wednesday, June 10, 2015:

Hi David,

Maybe I’m getting old-fashioned: I’m still avoiding the use of floating point numbers in embedded projects. The reason for doing so isn’t really valid anymore: floating point operations are now often handled high-speed by an FPU, and also often there is enough space to store the bigger numbers.

In stead I use fixed-point numbers such as the 8.24 format to express decibels. That is a number between -128.0000000 and 127.9999999.

Or, for storing an FM frequency of 98.15 MHz, I would multiply the frequency with 100, and store it as a whole number 9815.

The latest version (V8.2.1) of FreeRTOS-Plus/Demo/Common/Utilities/printf-stdarg.c is pretty complete and well-tested, but it does not support floating numbers.

I have never seen a snprintf() function that is not thread-safe!

I do known that in older versions of GCC, the snprintf() functions were extremely stack-hungry. They could easily use more than 200 bytes of stack. Current GCC implementations are better.

The printf-stdarg.c uses a small and predictable amount of stack space (about 72 bytes).

That snprintf() function is incompatible in one way: if the result does not fit in the provided buffer, the resulting string will be truncated and it will always be terminated with a zero.

char pcBuffer[5];
int rc = snprintf( pcBuffer, sizeof pcBuffer, "%s", "Hello dear world" );

Will result in :

pcBuffer = "Hell" // terminated with a null
rc = 4    

You might want to extend printf-stdarg.c to support floating point numbers :slight_smile: ?