cancel
Showing results for 
Search instead for 
Did you mean: 

Does STM32CubeIDE and Azure RTOS properly support Sprintf?

GreenGuy
Lead

I am having issues using sprintf in an application on a STM32H743 using Azure RTOS.  The function works correctly the first time it is used to convert a float to a string but after the first use, it inserts garbage characters where the decimal point should be while the digits are as expected.  The garbage characters continue to show up on subsequent calls to the routine where the sprintf is used and show up in other routines that use sprintf.  The garbage characters are always the same and only appear for float values that have digits to the right of the decimal point.  An example is when printing the conversion for the internal battery measurement which comes out as ...MCU Bat : 3.15 V on the first pass, then comes out as ...MCU Bat : 3"KOq@=xZ15 V on the second pass.  It is repeatable.  The format string is ...MCU Bat : %.2f V\r.  Changing the format string does not seem to effect the result.

I have gone over numerous posts regarding sprintf and RTOS but none seems to match with what I have implimented and what I am seeing.  There are no hard faults or crashing.  

Version info:

STM32CubeIDE - Version: 1.14.1 - Build: 20064_20240111_1413 (UTC)

STM32CubeMX - STM32 Device Configuration Tool - Version: 6.10.0-RC9 - Build: 20231120-2037 (UTC)

Linux LMint 21

 

20 REPLIES 20

"g3" isn't an optimization option.

 

>Right now my work around is to reduce every thing to non decimal by doing:

For the same effect you can try functions ecvt or  fcvt (in stdlib.h)

that will take a good deal of rearranging since I use threading to send the messages.

Not at all. Simply, add a small test function and call it immediately before MX_ThreadX_Init().

 

 

 

Unfortunately I don't have time to burn on NMP tasks

In days of yore, we'd build the libraries from scratch, or cherry pick what we wanted in them or not. Remove or substitute objects.

There were "Librarian" tools for doing that. Here probably objcopy or objdump type things. But it's a problem as old as time.

There have to be documented ways to get GNU/GCC to collect and piece together what you need. You point the linker at the thing(s) it needs to get closure.

See what the Non-Nano offerings are. The libraries will likely get bigger, and the dead-code elimination of the linker will need to work harder.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

My Bad.  You are right!  It was set to none.  I will step through and see what gives.

Yeah It's probably desirable not to pull in the float libraries, although ST has a history of using floats in the HAL, which causes a lot of headaches trying to make something small that can fit in a Cortex-M0(+) 16KB FLASH

If you can do things with scaled integers and "%d.%02d %%" type formatting go for it.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

OK getting more weird.

Optimization set to Debug (-Og)

Debug set to Maximum (-g3)

The problem does not occur and the debugger steps around sprintf even when trying to step into the function.

I tried all the different optimizations and sprintf works correctly and consistently.

As a light bulb test, I then went back to Optimization set to none and sprintf inserts garbage characters on the second usage.

Using Optimization settings I can turn the failure off and on reliably.

 

 

made a simple set of 6 sprintf functions in main before MX_ThreadX_Init() with a memset between them and in every instance after an sprintf the floats converted to strings were correct without garbage characters in place of the decimal point.

 

GreenGuy
Lead

An an answer with solutions that work this is the summary.

I had to set Optimization to something other than none to get sprintf to work with floats correctly after ThreadX was instantiated.  The other option is to avoid the use of floats by reducing floats to integer values before and after the decimal point and sprintf them separate with %d.%d.

 

I think this is a bug in the compiler since setting Optimization to none does something with the standard c library that affects its runtime code.  So the above solutions are work arounds.  It is noted that there are various valid complaints concerning the lack of reentrancy with respect to the standard C libraries that come with the CubeIDE toolset.

I had to set Optimization to something other than none to get sprintf to work with floats correctly after ThreadX was instantiated.

This sounds worrying, hints to a thread stack overflow or subtle timing issues. 

> I think this is a bug in the compiler 

😎

 

GreenGuy
Lead

It is certain the code runs more than 2x faster even with -Og3.  So ...timing?  I know that I do not have stack problems since after sometime running and exercising the code containing the sprintf calls,  the stacks are good by inspection.  It is not possible to step the sprintf code.  Using the dissassembly window is awful and many times I have tried to get a look at it, CubeIDE crashes out of the debugger back to the C perspective, terminating the debug terminal, if I scroll to far in the disassembly window.

 

I have IAR running and will be testing this in their tool when I get the chance, after porting the cubeIDE code over.  Not on the top of my list so it may be awhile.