Quality RTOS & Embedded Software

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




Loading

sprintf %f corrupts stack

Posted by dnadler on December 26, 2016

I'm not sure this is a FreeRTOS problem, but... Cortex M4F (Kenetis K64), gcc, nano, newlib with float. Only one task uses floating point; no issues there. A sprintf of a floating point number returns the correct string but corrupts the stack. The corruption is miles away from the top of the stack. FreeRTOS-aware debug says I have several kb of extra stack space for this task. Absolutely reproducible; this corrupts stack: sprintf(out.pBuffer,"floatOutTest=%f", 1.2345f); The buffer is in the right place and printing decimal values works fine. Thanks in advance for any ideas! Best Regards, Dave


sprintf %f corrupts stack

Posted by rtel on December 27, 2016

Things to check:

1) The stack is 8 byte aligned at the point sprintf() is called (put a breakpoint on the call to sprintf() and check the value of the stack pointer in the debugger).

2) Are you using a FreeRTOS heap memory allocator other than heap3.c? If so, check sprintf() is not calling malloc(). heap3.c is the only FreeRTOS memory allocator that will need malloc() to be configured correctly, and if it is not configured and sprintf() attempts to call it then anything could happen. Probably the easiest way to check this is to provide your own implementation of malloc() that does nothing but contain an NOP instruction, or trigger an assert, then put a break point in your implementation of malloc() and see if it is ever called.


sprintf %f corrupts stack

Posted by dnadler on December 27, 2016

Stack alignment is AOK. I'm using your heap4. Per your suggestion I added a dummy malloc with asm bkpt, and sure enough the damn thing is calling malloc: ** sprintf -> _svprintfr -> printffloat -> cvt -> dtoar -> malloc ** Unfortunately I don't have a library built with debug info. I suspect malloc is incorrectly set up by NXP/Freescale (dubious linker script with partioned M4F RAM) and/or its run out of the standard RTL heap's memory. I could try stubbing it out with heap_4... Thanks for the help! Best Regards, Dave


sprintf %f corrupts stack

Posted by dnadler on December 28, 2016

Update: Several nano newlib RTL functions (sprintf, strtok) unexpectedly used malloc() or mallocr().

The default heap from Freescale/NXP was set to 1kB (for a processor with 256kB RAM!), and the RTL overflowed the heap without halting and corrupted memory. Very Nice!

Do you guys have a replacement for the nano free storage functions that map to FreeRTOS heap functions, to give a single, debuggable pool? Ideally with hard stop on overrun? Is this a bad idea? Should I write this?

Thanks as always, Best Regards, Dave


sprintf %f corrupts stack

Posted by rtel on December 28, 2016

You can provide your own doing something simple such as:

void *malloc( size_t xBytes )
{
     return pvPortMalloc( xBytes );
}

void free( void *pvBuffer )
{
     vPortFree( pvBuffer );
}

The configASSERT() calls in pvPortMalloc() and vPortFree() will then work as normal. If you are using GCC (and maybe other compilers) then there is a way of redirecting these calls using the command line - but its probably easier and more portable just to add the above functions into your code.


sprintf %f corrupts stack

Posted by dnadler on December 28, 2016

If I understand correctly, its a bit more complicated, as there is a whole family of heap routines included in newlib, and used within newlib. One example above is mallocr(). See newlib's malloc.c source for the entire set. No?


sprintf %f corrupts stack

Posted by richard_damon on December 28, 2016

One issue I have seen with some Librararies is they assume the heap can grow up to the stack, and once the kernal is started, the memory map is no longer what they expect. Sometimes using the heap prior to starting the kernal can help. I would make everything use the same heap either like posted above or making FreeRTOS use the libary heap (adding the needed code to make the library heap thread safe).


sprintf %f corrupts stack

Posted by ammaree on January 5, 2017

Maybe a suggestion to have a look at a complete [v/s/n/f]printf replacement on github. I uses no dynamic memory, supports floats and have a large number of optional extension that can be useful in an embedded environment.

The supported functions can be selected at compile time to minimise the stack space used. Stack usage is completely predictable with no recursion.

The printf functionality relies ()to some extent) on 2 additional modules also there namely xtime.c and xstring_general.c, so scratch around...

Have a look at https://github.com/ksstech/support_common and shout if you have queries or suggestions, but it is fairly well documented in the source code.


sprintf %f corrupts stack

Posted by dnadler on February 26, 2017

Thanks Andre for the suggestion.

Richard, can you point me at a replacement for newlib's malloc and friends, that properly uses FreeRTOS heap functions and reentrancy structures?

Thanks, Best Regards, Dave


sprintf %f corrupts stack

Posted by richarddamon on February 27, 2017

I just downloaded the newlib-nano repository itself and added the defines used to enable the reentrancy callls. These then call functions _malloclock and _mallocunlock which can just call the scheduler suspend/resume functions like in heap_3.c

I will need to get the exact repository address and files from work tomorrow. The queston comes to what options were the library compiled with, if it was compiled with full re-entrancy endabled, you may just need to define the malloc_lock/malloc_unlock functions.


sprintf %f corrupts stack

Posted by hs2sf on February 27, 2017

Alternatively you could make use of the 'wrap symbol' linker feature e.g. let the linker replace all 'malloc' symbols with (your) __wrap_malloc implementation etc. You might even implement your own low level _sbrk function. (I've also overloaded the global new/delete operators with 'noexcept' versions to safe some code space.) Good luck, HS2


sprintf %f corrupts stack

Posted by richarddamon on March 2, 2017

The newlib repository is at sourceware.org

In my case, the enviroment was already using newlib-nano, the package just wasn't quite configured the way I needed. The use of newlib-nano seems fairly common if you have a gcc based development tool.

If so, first I would see if it is configured to use the interlock functions already. See if a _malloclock() / _mallocunlock functions stubs are already being used. If they are, you just need to define the lock function to call vTaskSuspendAll() and the unlock to call vTaskResumeAll() (and then test that these are called by malloc) and you are set.

If not, you can just add the source code for the malloc module (newlib/libc/stdlib/nano-mallocr.c) to your project. There are other files malloc.c and mallocr.c too that you don' need (malloc.c is a stub to allow newlib to have reentrant routines, including malloc, and mallocr.c is a 'big machine' version of the reentrant malloc).

If your library isn't based on newlib, you could still look at the newlib version to build a malloc for your self, but check if your library malloc does the work or if it just forwards to some other function.


sprintf %f corrupts stack

Posted by dnadler on July 1, 2017

Here's what I finally ended up doing to sort the above problem: http://www.nadler.com/embedded/newlibAndFreeRTOS.html Thanks again for the help! Best Regards, Dave


sprintf %f corrupts stack

Posted by heinbali01 on July 2, 2017

Hi Dave, thanks a lot for all these insights!

I just want to confirm that the [v][s][n]printf() implementation in the FreeRTOS Labs TCP/IP ( attached below ) is quite complete and well tested. Unfortunately is misses the floating point formats ( %f, %e, %g, %E, %G ).

These printf() functions only use stack ( about 70 bytes ) and they don't use the heap.

They are thread- and even interrupt-safe.

I added two formats, to print IPv4 and IPv6 addresses :

~~~ /* Dot notation for IP addresses: */

printf( "IP = %xip\n", 0xC0A80164 );
/* will produce "IP = 192.168.1.100\n" */

printf( "IP = %pip\n", pxIPv6_Address );
/* 'pxIPv6_Address' is a pointer to a 16-byte array.
It could produce "IP = fe80::1\n" */

~~~

Memory protection: Printing a string with %s may lead to a crash in case you make a mistake with the parameters. The functions in printf-stdarg.c will check the validity of the pointer by calling :

~~~ /* * Return 1 for readable, 2 for writeable, 3 for both. * Function must be provided by the application. */ extern BaseTypet xApplicationMemoryPermissions( uint32t aAddress ); ~~~

Another habit of printf-stdarg.c is to use an external function to actually write the character to a peripheral.

The function below is called in case sprintf(NULL, xxx) is called. We kept it for backward compatibility.

~~~ void vOutputChar( const char cChar, const TickType_t xTicksToWait ) { /* Eg. send a byte to the UART. */ } ~~~

Attachments

printf-stdarg.c (16451 bytes)

sprintf %f corrupts stack

Posted by dnadler on July 2, 2017

Thanks Hein, I updated web page to note some of this, Best Regards, Dave


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




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

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

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