I've ported a program from the arduino environment to a makefile build using winavr, which, in turn, is based on avr-gcc (just like arduino).
However, my program started crashing, and after some investigation I found I was running out of data memory due to a 256 byte increase in the heap, even though I hadn't changed the program at all.
Looking at the map file I see a new table being included, __clz_tab
, which is 256 bytes, and resides in RAM.
How do I get rid of this table and reclaim my RAM?
Best Answer
libc, included with gcc and avr-gcc, has a function that's used to count leading zeros when converting from an
int
oruint
into afloat
or adouble
. This function uses a 256 byte table to speed up the zero counting operation, which is fine for computers with lots of memory, but not so great for microcontrollers where 256 bytes is 1/4 or 1/8 of the total ram available.avr-gcc includes a library,
libm.o
which has alternate definitions for some functions, including the function that requires__clz_tab
. This definition requires less memory, and so you need to instruct the linker to link against libm.This is done by adding
-lm
to the linker command line.However, the position of this command parameter matters - it will only resolve links to symbols before this parameter, so to make the most of it the
-lm
parameter should be as close to the end of the command line as possible.In my
Makefile
it looks like this:Note that the last item on the compiler command line is
$(LIBS)
and the last item inLIBS
is the-lm
which ensures that the compiler gives precedence to the definitions in libm when there are multiple definitions available.Recent versions of avr-gcc have resolved this issue so this doesn't happen even without the
-lm
, however the arduino IDE is still installing and using the older versions of avr-gcc, and winavr hasn't been updated since this bug was fixed.You can read the bug report here:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29524