Page 1 of 3

Support for float (%f) in chprintf

Posted: Fri Feb 03, 2012 6:57 pm
by utzig
Hi,

I think this could be useful to somebody else! I have some sensors which supply floating point data in a normalized integer form but it's kind of impossible to understand by printing them so I added some very basic support for printing out floats in chprintf. It's kind of "hacky" but it works for common values. No support for engineering notation. Not very much actually but it should work for "common" float values.

Patch is attached.

Att,
Fabio Utzig

Re: Support for float (%f) in chprintf

Posted: Sat Feb 04, 2012 3:48 pm
by Giovanni
Hi,

Thanks for the patch but I can't add a dependency to the floating point code because size issues, the chprintf() function is meant to be minimal. I'll look into making it optional somehow.

Giovanni

Re: Support for float (%f) in chprintf

Posted: Sat Feb 04, 2012 9:18 pm
by DrunkenDonkey
I'm interested into that as well (or will be interested), but floating point adds way too much, maybe some sort of a define? Thanks for sharing it.

Re: Support for float (%f) in chprintf

Posted: Mon Feb 06, 2012 3:28 am
by Xamusk
In my own in-house printf.c, I conditionally compile float support with a #define. Maybe you could set one in chconf.h or halconf.h? Maybe even board.h or Makefile for the projects which need it (most of which would compile the float standard library anyway, so the float support in printf wouldn't get the final binary that much bigger).

Re: Support for float (%f) in chprintf

Posted: Tue Feb 07, 2012 1:13 am
by utzig
Hi Giovanni,

I would suggest you not to merge this code with the current implementation because there are some very nasty things. I would rather clean up the code somewhat and send you another patch. This was only meant to be used by those who felt the necessity of using the functionality.

The basic flow of the code can be divided in these steps:

1) Determine if number is negative by reading most significant bit (IEEE-754) and print '-' if necessary (this is really ugly and can be done in a much simpler/better way)
2) Get integer portion of float (simple cast float -> integer) and print
3) print '.'
4) Multiply floating portion by some power of 10 (which by the way would be better called "precision" or something like that, instead of "mul")
5) Convert this new integer to string (float is lost)
6) Remove zeros from the end of the string and print

I did a copy/paste/modify of the ltoa function to create ftoa but it would be better to reuse ltoa (with small modifications) to print both integers from ftoa. Step 6 above should probably be removed. A did it because printing 2.5 looks much better than 2.500000. A better thing to do would be to add the number of digits after the dot as in "%.2f" which should no be hard at all.

I guess with the modifications above it will use just a little more space than the current implementation. I'll work on it soon.

Fabio Utzig

Re: Support for float (%f) in chprintf

Posted: Wed Feb 22, 2012 9:26 pm
by utzig
Hi Giovanni,

Here's an updated version of the patch which has been cleaned up and should be ok to be merged (IMO) if you decide so. And a nice trivia for anyone. Why must the float value be declared "volatile" in the main function?

I would also suggest updating the following line (125 on trunk):

Code: Select all

if (*fmt == '.') {
  fmt++;
  filler = '0';
}


With:

Code: Select all

if (*fmt == '.' || *fmt == '0') {
  fmt++;
  filler = '0';
}


This would enable using something like "0x%02x" to print 0 padded byte values which is more common syntax than using '.'

Att,
Fabio Utzig

Re: Support for float (%f) in chprintf

Posted: Wed Feb 22, 2012 9:33 pm
by Badger
Hi utzig,

Have you had strange issues with floats? I haven't tested or even looked at your code, but I experienced issues in my own printf library where floats would print fine from some threads but not others. I'll have to try it with volaile. I'm currently writing a cout style c++ library for type safe printing, to get around the problem..

Re: Support for float (%f) in chprintf

Posted: Wed Feb 22, 2012 9:39 pm
by Giovanni
Badger,

That should happen only if the stack size is not aligned to 8 bytes when the printf() is called, could you try to put a breakpoint just where you call the failing printf() and see if it is aligned? I haven't been able to replicate it but I didn't try hard.

Giovanni

Re: Support for float (%f) in chprintf

Posted: Thu Feb 23, 2012 12:49 am
by utzig
I guess alignment would not cause any problem as long as you use floats only (4 bytes) and these are not promoted to double (8 bytes) internally. Does this make sense to you?

Badger,

I'm really not entirely sure about the volatile thing but I had a problem with a line like this:

chprintf("%f, %f", float1, float2);

If there was only one float as in "%f any other string here" and no other args it would always work. If there's any arg after %f (%d, %s, etc) it would give an error and sometimes hang the processor. For me it happened with only one thread when using floats (did not test with many threads). After debugging the problem I found that passing a float as a parameter to the function ftoa, the function would not receive the correct value. But it always worked the first time (first %f).

It looks exactly like a stack corruption but if it was I would happen always (I guess...). When I printed the float as uint32_t (with my own printf implementation that only supports uint32_t) just before calling ftoa(), it started working. I tried to disable optimization removing -O2 but I did not work. So I tried volatile and it worked. Another option that works is to add -ffloat-store to gcc options (it's like adding volatile to every float declaration) which I tested too. My gcc version is 4.5.2 based on CodeSourcery's (arm-none-eabi-) but recompiled to run a Mac.

I would suggest you to add -ffloat-store as an option to USE_OPT for a faster testing.

Re: Support for float (%f) in chprintf

Posted: Thu Feb 23, 2012 11:15 pm
by DrunkenDonkey
Have you tried yagarto or some 4.6 gcc? Had some weird unstability with codesourcery 4.5.2, it is working okay, then adding or removing some random code was making even chSysInit unable to complete and no rebuld helps, then after some changes works again... had enough of it and switched to yagarto, never seen an issue ever since. Maybe totally unrelated, but still...