libc, included with gcc and avr-gcc, has a function that's used to count leading zeros when converting from an
uint into a
float or a
double. 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.
Makefile it looks like this:
CFLAGS=$(MCU) $(CPU_SPEED) -g -Os -w -Wl,--gc-sections -ffunction-sections -fdata-sections
LIBS=-L ../lib -larduino -lm
avr-objcopy -O ihex $< $@
program.elf: bcu_usb.cpp main.cpp programmer.cpp
$(CXX) $(CFLAGS) $(LFLAGS) $(INCLUDE) $^ -o $@ $(LIBS)
Note that the last item on the compiler command line is
$(LIBS) and the last item in
LIBS 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: