cancel
Showing results for 
Search instead for 
Did you mean: 

Fragility of Keil printf() for doubles on Cortex-M0(+) platforms

I generally don't open threads, but one recurring frustration I've had with Keil on CM0(+) platforms is with printf() going off the rails with "%.2lf"  "%.3lf" type formats.

I've seen more often than I care for, a situation where code working elsewhere fails with massive format failures, where it wants to prints tens of digits before/after the decimal point, and where it seems it trashes it own environment.

It's gone away for the moment, with me making the stack as large as possible, I think I had a 1500 byte stack, it was using less the 940 bytes according to the high/low water mark analysis I did. So I'm a little skeptical that is the underlying issue.

I'm using a G031 today, but seen on L011 too. Have seen in past issues with locale, heap and stack collide.

Another annoyance is with "unsigned long" becoming 64-bit on the v6 compiler, and also with structure size alignment.

 

Anyway, looking to read the temperature in the room (figuratively), and see if others have seen this behaviour.

This install of MDK is using the STM32 Free License for CM0(+) parts, v5.38a here, but seen this oddness across 5.2x thru 5.4x. Just want to not be only Me seeing this.

This isn't the GNU/GCC issue were it's not enabled in the library, but I only see it on CM0, not CM3,CM4 or CM7 builds.

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

"... It's gone away for the moment ..." - never a good sign. Sympathies. I can't help you with your specific problem, but can make some general comments. 

I have had occasional trouble with Keil doing large integer calculations, I've had to break a larger calculation into smaller steps to make sure they work properly - unfortunately I can't find/remember the specific calculation. 

I also haven't been impressed with the "compile as you type" feature of the later versions. It sometimes gets confused and fails to recognise changes. I would rather do without that feature and have a rock-solid compiler that is tested thoroughly. I remember years (3 decades!) ago working on a project when we received the latest version of an Ada compiler, we chased so many bugs that ended up actually being bugs in the compiler.  I am always wary of new versions/updates of any software - I would much prefer to stick with an old version if it is stable.

All I can suggest is that you create your own test program that you can use to test different versions of compilers on different platforms - but one would hope that is what the compiler makers do already....

I'm touching the same code again, and a "%+15.12lf" is working where as the "%.12lf" trashes it's buffers such that subsequent printf() repeat the same data.

Might be some code folding or LTO (link time optimization) specific to the less rich CM0 ISA. The tight RAM might be an issue and reuse of the resource.

Then again it's been a year and no one else seems to have landed on this.

So some unscoped length in the format composition, where I want to limit the decimal places of precision, mainly for temperature printing where I want a couple of digits where 4 or 6 dp is beyond realistic, but don't want to limit the sign and digits of the whole degrees.

At compile time it might be scanning the format strings to allocate an intermediate buffer and then ordering becomes an issue as there are other things where I need to resolve ppt with 12 dp. It's this mix of dp output that's been giving me problems. The NMEA GNSS output forms don't want spaces, can live with signs and have many fields too expected dp precision. ie metre altitudes to cm or mm precision. 

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

I haven't used Keil for a while, maybe in their CM0 software-float library this is implemented differently. But per the standard, specifier %lf  is meaningless for printf. It has meaning  only for scanf. Single-precision floats passed to printf are implicitly promoted to double. Try to remove the ?