How to forbit to link floating point stuff

Go To Last Post
32 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

I have here a big project and running low on memory. Now I found a small problem in the code which lead to the inclusion of some floating point library stuff (I suppose it is floating point):

c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_fixunssfsi.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_fixunssfsi.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_addsub_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_addsub_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_mul_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_mul_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_gt_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_gt_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ge_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ge_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_lt_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_lt_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_sf_to_si.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_sf_to_si.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_thenan_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_thenan_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_usi_to_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_usi_to_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_prologue.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_prologue.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_prologue.o)
 c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_epilogue.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_epilogue.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_epilogue.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clzsi2.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clzsi2.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_pack_sf.o)
 c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_pack_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_unpack_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_unpack_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_fpcmp_parts_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_fpcmp_parts_sf.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clz.o)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clz.o)

My question is, how to generally forbid the linking of floating point library stuff using AVR-Studio? Because then if someone implements some not sophisticated code it would generate an error instead of blowing the code up with floating point functionality.

And if that is possible, which libs do I have to deny?

Cheers,
Vince

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As you can see, the name of the library that gets pulled in is libgcc.a . That lib contains the generic gcc float implementations, which are not optimized for the AVR . Start by linking explicitly with libm.a instead which contains the AVR optimized variants, and see how much you get out of that.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Baldrian wrote:
My question is, how to generally forbid the linking of floating point library stuff using AVR-Studio?
I don't know of a way of doing that, but...
Quote:
blowing the code up with floating point functionality.
You should try deliberately linking against libm (put -lm at the end of the linker command line, or add libm in the libraries tab of the project options in AVR Studio). You may find that doing this reduces your code size enough to fit because the hand-crafted routines in libm are much smaller than the generic ones supplied by the compiler itself.

Christopher Hicks
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can get GCC to output a cross-reference table which would identify which function(s) are calling those library functions. Then work on that to remove the reliance of the fp lib all together. You cannot just make GCC not link with SOME lib or .o that would at least provide stubs for the called functions and even if you did that the piece of code making the call would cease to function - so that's not a solution anyway.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow, putting libm.a into the project options reduced my code from:

Program:   54048 bytes (82.5% Full)
(.text + .data + .bootloader)

Data:       2732 bytes (66.7% Full)
(.data + .bss + .noinit)
Program:   51186 bytes (78.1% Full)
(.text + .data + .bootloader)

Data:       2468 bytes (60.3% Full)
(.data + .bss + .noinit)

Is it really that much you can easily safe by such a small change to the linker options?!

Are there any other libraries I should include to my project linker options to safe more?

Edit: That's a pitty, that it is not possible to generally forbid floating point inclusion :(

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Baldrian wrote:
Are there any other libraries I should include to my project linker options to safe more?
If you use printf or scanf (or their friends), you should make sure you are linkng the version most suited to your project. The default version is full-featured but does not support floating point. There's a floating point version (inevitably bigger) and there's also a slimmed down version with some of the more obscure formatting features stripped out. Alternatively, rewrite your code to avoid printf/scanf completely as they are quite big in micro-controller terms.

CH
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looking at your code sizes, it seems that you have no chance of using a 32kB AVR. But you have around 13500 bytes spare in a 64kB AVR.

So unless you envisage a lot more functionality in your project, I see no reason to worry. And I would use a full-blown printf() if it suits you. You have plenty of room.

Now if you were using a 2kB AVR ...

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If one is using one's own make file,
the search of the cross reference
could be part of the link step.
Another way is to add another library.
Each book would define a forbidden symbol
and reference an undefined symbol.
The cross reference would still be useful.

Iluvatar is the better part of Valar.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This may be a "dumb" question, but it HAS been bothering me for some time. There must be others with a similar or worse level of experience, being pretty much unfamiliar with Studio/gcc linker flags!

How do you put in a flag to tell it to use libm.a? When Christopher says:

Quote:
add libm in the libraries tab of the project options in AVR Studio
I am not entirely sure what that means.

Thanks
Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

If using a Makefile find the section where LDFLAGS is defined and add:

LDFLAGS += -lm

but if your Makefile was created by Mfile (recommened) this would be there anyway. It has:

MATH_LIB = -lm

then

LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)

If using Studio go to the project configuration and under the "Libraries" section copy the "libm.a" entry from the left pane to the right (this SHOULD be the default but despite being told Atmel continue not to do this in the avr-gcc plugin)

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

Studio -> Project configuration -> Libraries

select libm.a and click Add.

It normally just appends '-lm' to the linker command line.

Yes. Just looked. Scroll back up the build window to see the commands.

David.

p.s. a regular Unix 'cc' uses -l flag and constructs the actual library file name by putting 'lib' + 'm' + '.a' -> libm.a . It will then look along a Libraries path to find the libm.a (archive of .o objects)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, folks -

Never have been a command-line fan and deal with make file as little as I can! Your explanation helps.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
But you have around 13500 bytes spare in a 64kB AVR.

Minus 4096 Bytes for the Bootloader. :(
And what is wondering me is the fact, that in theory I have
61439 Byte of usable memory. In practice, the programm stops working when I exceed ~58000Byte. I don't know why.

david.prentice wrote:

So unless you envisage a lot more functionality in your project, I see no reason to worry. And I would use a full-blown printf() if it suits you. You have plenty of room.
David.

After putting the libm.a into the project, my terminal stops working. I'm using printf in the terminal. Do you have any idea why? How to choose the different printf versions?

Cheers,
Baldrian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok. If you have a bootloader, this will use some FLASH. It is pretty straightforward to have a 2048 byte bootloader written in C. And I am sure you can squeeze an ASM one in 1024 bytes.

As to your libm.a and printf conflict --- post what your make is trying to do. e.g. do the following and copy-paste 'outputfile'

make clean
make -n >outputfile

or if you use the Studio IDE "internal" makefile. --- just copy-paste the output window from a "Rebuild All"

1. do you use any floating point?
2. do you want to use full printf?

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Ok. If you have a bootloader, this will use some FLASH. It is pretty straightforward to have a 2048 byte bootloader written in C. And I am sure you can squeeze an ASM one in 1024 bytes.

As to your libm.a and printf conflict --- post what your make is trying to do. e.g. do the following and copy-paste 'outputfile'
or if you use the Studio IDE "internal" makefile. --- just copy-paste the output window from a "Rebuild All"

OK. Here is the short form with some "***" instead of folder and project names due to security reasons :-)

avr-gcc -I"***" -mmcu=atmega644p -Wall -gdwarf-2 -fno-strict-aliasing -ffunction-sections -Os -funsigned-c
har -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT wado.o -MF dep/wado.o.d  -c  ../wado.c

avr-gcc -mmcu=atmega644p -Wl,--section-start=.noinit=0x801000 -Wl,--gc-sections -Wl,
--section-start=.bootloader=F000 -Wl,-Map=***.map wado.o -lm  -o ***.elf

avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  ***.elf ***.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex ***.elf ***.eep || exit 0
avr-objdump -h -S ***.elf > ***.lss

david.prentice wrote:

1. do you use any floating point?
2. do you want to use full printf?
David.

no floating point at all.
I just want to print out some strings and values to the uart and receive strings and characters from the uart.

Baldrian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

no floating point at all.

You mean you have found and removed that code that was linking to the FP functions in libgcc.a in your original post? In fact if you aren't using FP then why do you even need to link with libm.a ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your commands look fairly normal to me. It appears that you have a single C file called wado.c that you are using as both application and bootloader. It must be a massive source file to need 60000 bytes.

The normal approach is to make a bootloader. Program it into FLASH, set the fuses and lockbits. Then subsequently load any applications via the bootloader.

And a normal 60k application may use some 10 to 20 C files.

libm.a is going to make no difference to you using a UART. And if you do not use any functions or any float expressions, then there will be NO need for libm.a

I have no desire to know your secret filenames. I suggest that you just call it 'project' rather than using asterisks.

And use grep or egrep to see if you have used with a variable delay. or or any floating-point constants in your headers or monster C file.

I presume you know how to use regular expressions for a float constant etc.

And you know how to associate the with your UART. The functions will not work until you tell them your UART i/o functions.

(bald) David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Like I said previously a cref table generated by the linker will identify the function(s) that are inadvertently using the FP functions from libgcc/libm

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My money is on the delightful

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In which case a grep for "_delay_" would be the easy place to start.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
My money is on the delightful
clawson wrote:
In which case a grep for "_delay_" would be the easy place to start.
In particular, look for a call to _delay_ms or _delay_us with a variable as the parameter:
int foo = 35;
. . .
_delay_ms( foo ); // THIS IS BAD!!

These routines expect a constant. The correct approach for "variable" delay is:

int foo = 35;
int bar;
. . .
for ( bar = 0; bar < foo; bar++ )
{
   _delay_ms( 1 );
}

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

int foo = 35;
. . .
_delay_ms( foo ); // THIS IS BAD!!

No it isn't (unless intervening code modifies 'foo'). As shown it's a compile time constant and will be optimised as such - the 'variable' foo will never even be created.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff, I would not put any money on that.

Surely foo is implicitly extern, and another compilation unit could modify the value.

If foo was auto, the optimiser could see.

It may of course be that Baldrian has introduced FP by some other method. The project is classified.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In Stu's example it is auto isn't it? (or is there an invisible set of braces there I cannot see?). I took it that, being at the same indentation level as the for(), that this was within the body of a function. Maybe not?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Your commands look fairly normal to me. It appears that you have a single C file called wado.c that you are using as both application and bootloader. It must be a massive source file to need 60000 bytes.

The normal approach is to make a bootloader. Program it into FLASH, set the fuses and lockbits. Then subsequently load any applications via the bootloader.

And a normal 60k application may use some 10 to 20 C files.

As I wrote that was the short version of the build log. Of course I have plenty of c-files and the Bootloader is in another project.

david.prentice wrote:

libm.a is going to make no difference to you using a UART. And if you do not use any functions or any float expressions, then there will be NO need for libm.a

And use grep or egrep to see if you have used with a variable delay. or or any floating-point constants in your headers or monster C file.


The first error I found and lead to the opening of this thread was from an _delay_ms with a variable. Fixing that saved 400 bytes.
After that, changing to libm.a save another 3k. Now I checked again and found an _delay_us (rand()) (ROFL). Changed to a constant to check and now with or without libm.a I have 4k less than in the beginning. That means: one delay_ms and one delay_us with a variable brings 4k.
Now I have to test if the terminal connection works.

david.prentice wrote:

And you know how to associate the with your UART. The functions will not work until you tell them your UART i/o functions.
(bald) David.

Yes. The terminal worked before. I will find out now, why it is not working. I have the impression that it is a problem with the internal clock calibration. But I will see.

Cheers
Baldrian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You just have to check the map file to see what the linker pulled in. You should have no FP functions at all. And libm.a should make no difference.

When I asked for a "make clean; make -n" it was to see exactly what # of files and your build process.

Now if your project is classified, the obvious thing to do is edit this output: alter all your filenames to anonymous ones like module1.c ... to build project.elf

You could do a similar mangle of the map file. It really depends on whether you want others to help. We only need to know which modules have been pulled from which public library. You can keep your modules secret.

Incidentally if you do an nm -n (I think) you can get all your entry points in address order. Just post the entry points that have come from libraries.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK. Putting -cref to the Linker flags didn't change the map file. So I think the cross reference table is allready inside the map file. I hope this is the cross reference table:

c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_mulsi3.o)
                              modul1.o (__mulsi3)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_udivmodqi4.o)
                              modul1.o (__udivmodqi4)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_udivmodhi4.o)
                              modul2.o (__udivmodhi4)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_divmodhi4.o)
                              modul3.o (__divmodhi4)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_udivmodsi4.o)
                              modul1.o (__udivmodsi4)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_divmodsi4.o)
                              modul1.o (__divmodsi4)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm644p.o (exit)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_copy_data.o)
                              modul4.o (__do_copy_data)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
                              modul4.o (__do_clear_bss)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                              modul5.o (malloc)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(rand.o)
                              modul5.o (rand)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(atol.o)
                              modul6.o (atol)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(toupper.o)
                              modul6.o (toupper)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(memcpy_P.o)
                              modul7.o (memcpy_P)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(strlen_P.o)
                              modul8.o (strlen_P)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(memcmp.o)
                              modul5.o (memcmp)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(memcpy.o)
                              modul9.o (memcpy)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(memset.o)
                              modul2.o (memset)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(strncpy.o)
                              modul10.o (strncpy)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(mulsi10.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(atol.o) (__mulsi_const_10)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ultoa.o)
                              modul6.o (ultoa)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(iob.o)
                              modul8.o (__iob)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(printf.o)
                              modul11.o (printf)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(vfprintf_std.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(printf.o) (vfprintf)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ee_rblk.1F2021.o)
                              modul12.o (__eeprom_read_block_1F2021)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ee_wblk.1F2021.o)
                              modul12.o (__eeprom_write_block_1F2021)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(strnlen_P.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(vfprintf_std.o) (strnlen_P)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(strnlen.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(vfprintf_std.o) (strnlen)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(strrev.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ultoa.o) (strrev)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(fputc.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(vfprintf_std.o) (fputc)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ultoa_invert.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(vfprintf_std.o) (__ultoa_invert)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ee_rb.1F2021.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ee_rblk.1F2021.o) (__eeprom_read_byte_1F2021)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ee_wb.1F2021.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(ee_wblk.1F2021.o) (__eeprom_write_byte_1F2021)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_prologue.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(rand.o) (__prologue_saves__)
c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_epilogue.o)
                              c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(rand.o) (__epilogue_restores__)

And in the map file I also see that:

 .text          0x00000e2e       0x2e c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(printf.o)
                0x00000e2e                printf
 .text          0x00000e5c      0x3f0 c:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(vfprintf_std.o)
                0x00000e5c                vfprintf

are used, while vfprintf is killing 1k of memory :(

How to use the different printf versions? You told me allready that there is a full printf with floating point, one without floating and one really small with limited functionallity.
I'm using printf to print out some strings and variables to the uart. e.g.:printf("Xu.Xu Xd", i,j,k); (forum forbids to use percent sign. So I used an X :-)

Cheers

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Baldrian wrote:
[...]vfprintf is killing 1k of memory :(

How to use the different printf versions? You told me allready that there is a full printf with floating point, one without floating and one really small with limited functionallity.

Essentially, the libraries you need are libprintf_min and possibly libscanf_min. These are on the same "Libraries" tab in project options as the math library "libm", but you also have some other hoops to jump through on the linker command line which I can't remember with sufficient accuracy to type up here.

It is all documented in the library documentation, and there must be a hundred threads on the forum covering this. Look for threads where someone is asking why

float f;
printf("#f", f); // % replaced with # for the usual reason

just prints ?.????

CH
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I hope this is the cross reference table

Nope it looks like this:

Cross Reference Table

Symbol                                            File
__bad_interrupt                                   c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5/crtm16.o
__bss_end                                         c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_clear_bss.o)
__bss_start                                       c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_clear_bss.o)
__data_end                                        c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_copy_data.o)
__data_load_start                                 c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_copy_data.o)
....

after putting a deliberate _delay_ms(PINA) into test.c this caused, amongst other things:

__mulsf3                                          c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5\libm.a(mulsf3.o)
                                                  test.o

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK. Found this linker flags:

-Wl,-u,vfprintf -lprintf_min 

this saves another 400 byte, but the output is not correct due to the fact that this version ignores for example the Zero padding for some values where I need it. So it seems to stick with the normal version.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Re: Much Ado About Foo

In the future I shall use the example:

int foo = some_non_constant_function();
. . .
_delay_ms( foo );

That was my intention.

Stu Foo :D

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Re: Much Ado About Foo

Quote:

but the output is not correct due to the fact that this version ignores for example the Zero padding for some values where I need it.

LOL -- the great thing about AVRFreaks is that >>every possible<< AVR-related topic has been brought up, discussed, and consensus reached.

In this case:
https://www.avrfreaks.net/index.p...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.