Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
CDC Emulation buggy
09-01-2014, 05:30 PM, (This post was last modified: 09-01-2014, 05:39 PM by fcapozzi.)
#11
RE: CDC Emulation buggy
The regis example
Quote:void loop()
{
int i;
float b;

for (i=0; i<50; i++)
{
b = (float)i;
CDC.printf("Data = %f\r\n", b);
}
}

for me works in both cases either with float or double but my example does not

Quote:void loop() {
int i=2;
double a;
float b,c=3.14;
u32 ptr = &a;

CDC.printf("* Pinguino Mystery CDC Behaviour *\r\n");
CDC.printf("* Board PIC32MX250F128B *\r\n");
CDC.printf("* 1.ptr-> a = %08x\r\n",ptr);

for (i=1;i<10;i++) {
CDC.printf("* 2.ptr-> a = %08x\r\n",ptr);
a=3.14;
b=i;
c=a+b;
CDC.printf("Data = %f+%f\r\n",a,b);
}
CDC.printf("\n\r");
delay(500);
}

so may be there is some other point to consider apart the type conversion. I guess that something is wrong in the variable arg parameter passing.

Actually the chain is CDCprintf --> psprintf2 --> pprint
and pprint for each argument in the format list call the righ "type to string" conversion function that for float is pprintfl. In pprintfl there is part of the code that say

Quote: helper.f = value;
.......
.......
exponent = ((helper.l >> 23) & 0xFF) - 127;
mantissa = (helper.l & 0x7FFFFF) | 0x800000;

if ( (exponent >= 31) || (exponent < -23) )
{
buffer[0] = 'i';
buffer[1] = 'n';
buffer[2] = 'f';
buffer[3] = '\0';
return pprints(out, buffer, width, pad);
}
what happens here is that the "value" passed as parameter from pprintf came from a call to
the va_arg(args,double) in the pprintf called by pprint
This argument results having the exponent (IEEE754 Standard) out of boundaries. -23,31
Here i changed "helper.f = value" with a fixed "helper.f = 3.14" and everything printed ok
so the number to string conversion algorithm works well. For some reason for me not already known at this point the argument passed by the va_arg() is invalid. Here is where we have to direct our investigation. It's true however that double is 8 byte and float only 4 as pingotg said, so we should check how implicit conversions are carried out.
A C programmer expects that any valid C statement will be processed correctly or .. at least ... the compiler should throw an exception ..
Hope this help ....
:-) Fabio.
Reply
14-01-2014, 02:19 PM,
#12
RE: CDC Emulation buggy
Type float is promoted to double by GCC when used with va_args. All other types (char, short) are promoted to int. As I wish to keep printf as light as possible I think the only way to use floats is to pass them as int (as John said, size of float is 4 bytes or 32 bits or int, at least for GCC) to avoid that promotion.
I joined my new printf.c file :

.c   printf.c (Size: 12.89 KB / Downloads: 8)

You'll find below an example (based on fcapozzi's one) how to use it.
Tell me if it works for you.
If someone has a better solution feel free to improve the code.

Code:
// Pinguino float type
typedef union
{
    float f;
    int   i;
} float_t;

void setup()
{
    pinMode(USERLED, OUTPUT);
}

void loop()
{
    int i;
    
    float_t a,b,c;

    for (i = 1; i < 360; i++)
    {
        a.f = 3.14;
        b.f = (float)i;
        c.f = a.f + b.f;
        CDC.printf("a=%f b=%f c=%f\n", a.i, b.i, c.i);
        toggle(USERLED);
        delay(100);
    }
}
It is easier to complain than it is to do, but it is better to do than it is to complain.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)