[En-Nut-Discussion] printf() variants return 0.00 - stack alignment?

Philipp Burch phip at hb9etc.ch
Mon Aug 12 19:03:52 CEST 2013


Hi everyone,

since some time, I'm facing an annoying problem when it comes to 
printing floating-point numbers using printf() variants (fprintf(), 
sprintf(), etc.). The problem always looks the same, instead of the 
actual value, there is only 0.000000 printed.

The platform is the Stellaris LM3S9D90 (see devnut_lm3s branch), which 
is basically an ARM Cortex-M3 (no FPU). I'm using the ARM-provided GCC 
port of version 4.7-2012-q4:
https://launchpad.net/gcc-arm-embedded/+milestone/4.7-2012-q4-major

The behaviour is somewhat random, after some compilations (debug or 
release) it works, after some other it doesn't. It even differs between 
different locations in the code: Some places work as expected, some 
simply return 0.0. After single-stepping through the code, I found that 
the problem occurs when the function nut/crt/putf.c takes the double 
parameter from the param list, line 454:


    452                 if (prec == -1)
    453                     prec = DEFPREC;
    454                 _double = va_arg(ap, double);
    455                 cp = _dtoa_r(_REENT, _double, 3, prec, &decpt, 
&neg, &rve);
    456                 if (neg)
    457                     sign = '-';
    458                 if (decpt == 9999) {
    459                     /* Infinite or invalid. */
    460                     strcpy(bp, cp);
    461                 } else {


Before and after the call to sprintf(), the value of the argument has 
the correct value, 25.0. In the above mentioned line 454, _double gets 
the value 1.11423...e-313, which is obviously rounded to 0.

My code is nothing special, just formatted output:

         char buf[20];
         sprintf(buf, "%f", (double)(v.f));
         fprintf(resp_str, "%s=%s", vd->name, buf);

I know that fprintf() could do the double conversion as well, but this 
was a desperate try to get it working. Well, it didn't.

I'm using the cm3-gcc and cm3-gccdbg platforms in the Ethernut settings 
for compilation of the whole OS and the program, so there should not be 
incompatibilities between the application and the library.

Does anyone have an idea what could be the cause of this problem? Or, 
even better, how to fix it? The fact that the debugger shows the problem 
when dereferencing the varargs may be a hint that it is a stack issue, 
but I've no idea how I could change that. The underlying thread has 
10000 Bytes of stack space and the "Thread Stack Checking" tells me that 
it always had at least 9000 Bytes free.

As a (temporary) workaround, I would be happy with a simple function to 
convert a float into a string (which should also be somewhat faster than 
when working with doubles). Do you know a good implementation for this? 
I don't need those many formats (g, e, f) as printf() has, all I need is 
a variable number of decimal places and possibly automatic padding.

Many thanks,

Philipp


More information about the En-Nut-Discussion mailing list