This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Trouble with floating point calculations

Hi all,

When trying to do the following floating point operation: 

temp = -46.85 + 175.72 * (temp/65536.0);

I receive the following errors:

/Users/Nipun/Documents/TivaWare/Tiva Test/SHT21/sht21.c:172: undefined reference to `__aeabi_f2d'
/Users/Nipun/Documents/TivaWare/Tiva Test/SHT21/sht21.c:172: undefined reference to `__aeabi_dmul'
/Users/Nipun/Documents/TivaWare/Tiva Test/SHT21/sht21.c:172: undefined reference to `__aeabi_dmul'
/Users/Nipun/Documents/TivaWare/Tiva Test/SHT21/sht21.c:172: undefined reference to `__aeabi_dsub'
/Users/Nipun/Documents/TivaWare/Tiva Test/SHT21/sht21.c:172: undefined reference to `__aeabi_d2f'

The variable temp is initialized by converting a uint16_t to a float. I assume that this is a problem with my linker flags, so I've included my makefile below:

# ----------------------------------------------------------------------------------------------------
# Definitions
# ----------------------------------------------------------------------------------------------------

FILENAME=sht21

# Compiler, linker, etc.
CC=arm-none-eabi-gcc
LD=arm-none-eabi-ld
OBJCOPY=arm-none-eabi-objcopy

# Compiler CPU/FPU options
CPU=-mcpu=cortex-m4
FPU=-mfpu=fpv4-sp-d16 -mfloat-abi=softfp

# Filepaths
ROOT=/Users/Nipun/Documents/TivaWare
DRIVOBJROOT=${ROOT}/driverlib/gcc

# Compiler flags
CFLAGS=${FILENAME}.c       \
       startup_gcc.c       \
       ${ROOT}/utils/uartstdio.c \
       -g                  \
       -mthumb             \
       ${CPU}              \
       ${FPU}              \
       -ffunction-sections \
       -fdata-sections     \
       -MD                 \
       -std=c99            \
       -Wall               \
       -pedantic           \
       -DPART_TM4C123GH6PM \
       -c                  \
       -Os                 \
       -I${ROOT}           \
       -DTARGET_IS_BLIZZARD_RB1 \

# Linker flags
# Note: Any object files from any driverlib files needs to be appended to the LDFLAGS below in the 
#	format of ${DRIVEOBJROOT}/driverlibfile.o
LDFLAGS=-T                 \
        ${FILENAME}.ld     \
        --entry ResetISR   \
	--gc-sections      \
	-o a.out startup_gcc.o ${FILENAME}.o \
        ${DRIVOBJROOT}/fpu.o    \
	${DRIVOBJROOT}/gpio.o   \
        ${DRIVOBJROOT}/interrupt.o \
	${DRIVOBJROOT}/i2c.o    \
	${DRIVOBJROOT}/sysctl.o \
        ${DRIVOBJROOT}/uart.o   \
        uartstdio.o \



# ----------------------------------------------------------------------------------------------------
# Rules
# ----------------------------------------------------------------------------------------------------
all:
	${CC} ${CFLAGS}
	${LD} ${LDFLAGS} 
	${OBJCOPY} -O binary a.out ${FILENAME}.bin

upload:
	lm4flash ${FILENAME}.bin

clean:
	rm -fv *.o *.d a.out ${FILENAME}.bin

If anyone has any insight it would be greatly appreciated, I have no idea where to even start!

  • Not sure about the CCS environment, but adding -lm to your linker flags should do the trick. Is is general C/Unix 'standard' that libm.a is not linked against automatically (in difference to libc).

      >  temp = -46.85 + 175.72 * (temp/65536.0);

    BTW, are you aware that this is double, and not float ? It should be obvious by the names the linker is missing.

    One option to force float would be :

      temp = -46.85f + 175.72f * (temp/65536.0f);

  • Hi f. m.,

    Thank you very much! In the end, adding the -lm did not end up working, I got a 

    "arm-none-eabi-ld: cannot find -lm" error. However, if I left -lm off and I forced float as you pointed out, it works great.

    Thanks again for your help, I'm off to make sure I properly understand the difference between floats and doubles!

  • "arm-none-eabi-ld: cannot find -lm" error. However, if I left -lm off and I forced float as you pointed out, it works great.

    The actual setup depends on your toolchain. Since I am using Crossworks for 'historical' reasons, I cannot speak about CCS. But usually, the toolchain selects the proper math library (or library path), depending on your core and ABI settings, so that one is fine with adding '-lm'. BTW, the m in '-lm' is an abbreviation for libm.a.

    Since the M4 FPU supports only float (single precision) directly, it could be advisable to avoid double if the 'excess' accuracy is not required. Some toolchains offer options to generally force double to float. However,I prefer to make it obvious in the code, as this hidden conversion can break code relying on double precision for no obvious reason.