cancel
Showing results for 
Search instead for 
Did you mean: 

Possible bug formatting floating point numbers in STM32CubeIDE

rrnicolay
Associate II

I'm facing a problem trying to format floating point numbers in STM32CubeIDE. The uC is STM32F103. I've checked the "use newlib-nano to print floating numbers" in the project settings.

To narrow things down, I used the following code snippet to reproduce the error:

char strP[100];
uint16_t cx = 0;
cx = snprintf(strP, 100, "%6.2f, %6.2f, %6.2f, %6.2f", 0.0115697104, -0.0796313286, -0.0220388453, -0.111881733);

The error doesn't appear on every iteration of the example code. It works most of the time, actually. When it fails, it prints:

26815634999686289245754584189029181710324847797922429453525901675501503951146118153956426275383940846635237101275691881352391832390627762028461487571337216.00,  0.00, -0.00,  0.00"

Or:

0.00 2.00 0.00 2.00

Things I tried to fix the problem:

  • Increased the stack from 0x400 to 0x500 through STM32CubeIDE interface.
  • Changed the linker scripts like told in this link.

I'm sending some floating point numbers to the uart to plot inclinometer data on a PC. This issue is annoying me for some days. Any help would be appreciated. Thanks!

20 REPLIES 20

They are not float's they are double's, use the right formatting

cx = snprintf(strP, 100, "%6.2lf, %6.2lf, %6.2lf, %6.2lf", 0.0115697104, -0.0796313286, -0.0220388453, -0.111881733);

OR

cx = snprintf(strP, 100, "%6.2f, %6.2f, %6.2f, %6.2f", 0.0115697104f, -0.0796313286f, -0.0220388453f, -0.111881733f);

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

Thanks for the reply, @Community member​ . But in my real code I use floats instead of the hardcoded values.

@Community member​ - It doesn't matter due to variadic argument promotion.

Thus I don't think its possible to only use float (and single-only float hardware) via sprintf;

gets promoted to double. Similarly char to integer are promoted?

Right ???

rrnicolay
Associate II

Thanks for the reply @Dave Nadler​ . No, I'm not using FreeRTOS. Sorry, forgot to mention that.

I suppose it depends on the library implementation, floats can be passed as 32-bit values (generally they don't get promoted), and there is enough half-assery in these assorted reduced foot-print libraries, and CubeIDE, that anything is within the realm of possibility. It does look to me as if it is pulling the wrong values off the stack here. This could be an issue with va_arg's or the point on the stack it thinks it has established for the ... parameters, vs local/auto variables.

On Keil I might suspect stack depth, or stack/heap collision, but GNU/GCC generally provides a lot wider berth..

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

@Community member​ - The language spec says variadic arguments get promoted; that's not up to the library. While some specialty compilers can force all float and double to single precision and potentially avoid promotion (ie PIC24 compiler), I don't think this GCC has that option. To be absolutely sure, cast the arguments to match the format string (they'll get promoted anyway in this particular instance, but I have to do this for instance for code that runs on 16-bit to 64-bit processors to avoid excitement with printf diagnostics for fixed-size objects).

Anyway, I did a quick test with the OP's code, which works without error in my test setup (Nucleo F429, FreeRTOS, plenty of heap and stack space).

Here's the generated assembler code, where you can see 8-bytes per double (ie promoted float):

1265 005e 07F10C00         add    r0, r7, #12
 1266 0062 13A4             adr    r4, .L67
 1267 0064 D4E90034         ldrd    r3, [r4]
 1268 0068 CDE90634         strd    r3, [sp, #24]
 1269 006c 12A4             adr    r4, .L67+8
 1270 006e D4E90034         ldrd    r3, [r4]
 1271 0072 CDE90434         strd    r3, [sp, #16]
 1272 0076 12A4             adr    r4, .L67+16
 1273 0078 D4E90034         ldrd    r3, [r4]
 1274 007c CDE90234         strd    r3, [sp, #8]
 1275 0080 11A4             adr    r4, .L67+24
 1276 0082 D4E90034         ldrd    r3, [r4]
 1277 0086 CDE90034         strd    r3, [sp]
 1278 008a 174A             ldr    r2, .L67+56
 1279 008c 6421             movs    r1, #100
 1280 008e FFF7FEFF         bl    snprintf

@rrnicolay​ - Most likely you have a problem with inadequate stack or heap space.

Check this carefully in your project!

As a really quick test change your buffer to static:

static char strP[100];

Please let us know what you find,

Hope that helps, Best Regards, Dave

@Community member​ I did the test. My real code:

float CFangleY= 0.0;
	float CFangleX= 0.0;	
        static char strP[100];
	uint16_t cx = 0;
	cx = snprintf(strP, 100, "%8.2f/%8.2f/%8.2f", CFangleY, CFangleX, 0.0);
	if (cx > 0 && cx < 30) {
		debug_printf("%s\r\n", strP);
	}

It keeps printing invalid values to the serial. A log:

0.02/    0.03/    0.00
    0.02/    0.03/    0.00
    0.02/    0.04/    0.00
    0.01/    0.04/    0.00
    0.01/    0.03/    0.00
    0.01/    0.03/    0.00
    0.02/    0.03/    0.00
    0.02/    0.03/    0.00
    0.02/    0.04/    0.00
   -0.00/   -2.00/    0.00
    0.02/    0.04/    0.00
   -0.00/   -2.00/    0.00

All the lines with value equal to "2.00" are invalid. No value greater than 0.5 should be printed in this case.

@rrnicolay​ - You are probably out of heap space, increase both heap and stack to a large amount. You can also check heap availability by trying malloc and/or sbrk after the snprintf call. Really, snprintf with floats/doubles works just fine if adequate stack and heap are available.

Hope that helps,

Best Regards, Dave