[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