avr-gcc floating point problems

In response to another thread, I am still getting these problems with WinAVR 2010. I think the linker is hitting some AVR limits. There are similar reports on the web as well.

-------------------------------------------------------------------------------------------------

unsigned char u; float f;

u = (unsigned char) f;

--------------------------------------------------------------------------------------------------- c:/wavr10/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/ avr35\libc.a(fp_powsodd.o): In function `__fp_powsodd': (.text.avr-libc.fplib+0x10): relocation truncated to fit: R_AVR_13_PCREL against symbol `__mulsf3' defined in .text section in c:/wavr10/bin/../lib/gcc/avr/4.3.3/avr35\libgcc.a(_mul_sf.o) c:/wavr10/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/ avr35\libc.a(fp_powsodd.o): In function `__fp_powsodd': (.text.avr-libc.fplib+0x20): relocation truncated to fit: R_AVR_13_PCREL against symbol `__mulsf3' defined in .text section in c:/wavr10/bin/../lib/gcc/avr/4.3.3/avr35\libgcc.a(_mul_sf.o)

Reply to
linnix
Loading thread data ...

-------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------

"relocation truncated to fit" sure sounds ominous.

Altavista-ing that phrase pops up with a discussion on an Intel board of

32-bit vs. 64-bit immediate addressing, and the comment "If you're seeing this and you're not hand-coding, you probably want to check out the -mmodel argument to gcc."

So it appears that it's not really doing anything serious other than completely screwing up your addressing.

--
Tim Wescott
Control system and signal processing consulting
 Click to see the full signature
Reply to
Tim Wescott

Le Thu, 18 Mar 2010 10:47:44 -0700, linnix a écrit :

In what kind of situation you need to cast a float to that unsigned char ??? If you want to extract the integer part of the float, let me tell you that this way is a bit silly.

Question yourself before asking to C.

Habib

Reply to
Habib Bouaziz-Viallet

f is result of k1 * sine x + k2 * cosine y.

How would you extract the integer part without casting? I thought that's the job of the compiler.

Reply to
linnix

-------------------------------------------------------------------------------------------------

Approach it a little at a time: Try casting to a (signed) int first. If that works, then unsigned (assuming your value truly is "non negative"). Finally, shrink it to a char.

Sometimes compilers get upset if you do things that it doesn't expect.

You might also experiment with real doubles to see if there are any subtle differences.

---------------------------------------------------------------------------------------------------

Reply to
D Yuniskis

Well, technically, there are a lot of ways you *could* do it -- but most are not as efficient as a simple cast. Remember that a cast *discards* the fractional part (i.e., doesn't round). Also, the cast will misbehave if the argument doesn't fit in the data type.

Reply to
D Yuniskis

--------------------------

Noop, this does not work either:

int i; unsigned char u;

i =3D (int) f; u =3D (unsigned char) i;

---------------------------------------------------

All these ops works on x86 gcc. I guess AVR is not ready for floating points. Any one got FP apps working for AVR? For me, I am ready to ARM, as soon as my LPC (ARM Cortex M0) kit arrival.

----------------------------

Reply to
linnix

Le Thu, 18 Mar 2010 12:39:32 -0700, linnix a écrit :

Sure that's the compiler job, so please cast a float to an integer (signed int). Remember char are not meant to be used for math.

Keep It Simple.

Habib

Reply to
Habib Bouaziz-Viallet

The cast isn't necessary but it may give a hint to the compiler that what you've written is what you've intended. In a simple assignment, the operator itself causes the type of the right operand to be converted to the type of the left and the resulting value to then be stored in the object indicated by the left operand. Absent the cast, you're likely to get an "Are you sure you meant to do this?" type of warning.

When a real (e.g., not a NAN or otherwise) floating point type is converted to an integer type, the fractional part is simply discarded (no rounding, truncate towards zero). You will hit undefined behavior, though, if the resulting integral value can't be represented in the intended integer type.

So, "u = f;" is perfectly legal, no cast required, but f would have to be in the open interval (-1, UCHAR_MAX + 1) to avoid undefined behavior.

An explicit cast doesn't hurt and also lets the maintenance programmer know that yes, this is what I meant to do.

--
Rich Webb     Norfolk, VA
Reply to
Rich Webb

But the real world (as least in my case) is unsigned char (8 bits).

Now, the strange thing is:

i =3D (int) f; works or u =3D (unsigned char) i; works

but not together i =3D (int) f; u =3D (unsigned char) i;

Unless my apps is very unique (USB CDC A2D), I have to conclude that AVR is not ready for it.

Reply to
linnix

I do heavy floating point computations with AVR (IAR workbench compiler), and it works nicely. BTW, the math on the AVR at 20MHz is somewhat 3 times faster then the same math on 40MHz PIC18.

My experience is not all compilers provide for every possible cast between the standard types; I have seen bugs in float int conversions also. But you can always do a function for explicit conversion.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

I don't use your tools or the AVR, of late. But these linker errors look suspiciously as though the linker is struggling to include pieces of the floating point library that you've required by your code and is truncating code so that it fits.

I'm sure you know all this, but the linker usually creates relocatable segments and piles code and constants into them as it works. But at some point, these segments have to be positioned and their lengths compared against what is available on the target part. When that step happens, a linker may discover that a code segment cannot be placed _and_ fitted and will issue a relocation error like what you are getting.

Those errors are "not good."

I don't know what your linker produces in terms of a map file, but that is where I'd usually go next to find out the size of these routines that it is complaining about. You may find that they are "large", or that some other large routine was successfully placed but then forcing these onto the scrap heap. Your specific part and it's memory map is important here. If you are using a small part it's not at all uncommon for floating point routines to cause trouble.

Jon

Reply to
Jon Kirwan

g

n.

Then I guess it's a avr-gcc porting problem. I'll check if arm-gcc works or not.

Reply to
linnix

-------------------------------------------------------------------------------------------------

Try ICC's AVR compiler. There's a free trial that decays to a code-size limited version after 45 days. Imagecraft produces compilers for quite a few microcontrollers but their AVR offering is far and away their most popular.

I tried your test above and it compiles cleanly. Don't have an AVR dev board or breadboard set up right now but I'll give it a run this evening. I expect it to work as per spec, though.

formatting link

--
Rich Webb     Norfolk, VA
Reply to
Rich Webb

Le Thu, 18 Mar 2010 13:29:24 -0700, linnix a écrit :

...

oh no you cannot conclude that AVR or avr-gcc or AVR and avr-gcc are not ready for doing math, no you cannot !

Habib

Reply to
Habib Bouaziz-Viallet

It sounds like it's at least partially an optimizer bug.

Try lowering the optimization level (and hope that whoever wrote it was paying attention).

Or make a function

int cast_float_to_int_boy_gcc_is_stupid(float f) { return (int) f; }

in extreme cases you may need to put it in a separate file to _really_ confound an over-eager optimizer.

--
Tim Wescott
Control system and signal processing consulting
 Click to see the full signature
Reply to
Tim Wescott

-------------------------

---------------------------

I am using a 32K AVR, but the program is around 8K. I agree that it is a linker relocation problem due to the floating point library. AVR might have a 8K relative addressing limit somewhere.

Reply to
linnix

If you insert some printfs (or just single-step a debugger), what does it produce for i and u (assuming, say, f was... 123.456 to begin with?)?

Just the compiler. :-)

Reply to
Joel Koltner

Now it works if I remove some other functions. I guess I am hitting some kinds of compiler limits.

Yes, I got correct result of 123.

Yes, it is taking too much time for me. I'll try other options.

Reply to
linnix

That is a bit too harsh. This may be an optimisation problem or a problem in the libraries. Check the assembler to see what is going on. Try to compile with -O0 to turn off all optimisation first and try again.

--
Failure does not prove something is impossible, failure simply
indicates you are not using the right tools...
 Click to see the full signature
Reply to
Nico Coesel

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.