Ubuntu下ARM Cortex-M4项目math.h与Makefile链接错误求助
解决ARM Cortex-M4中math.h链接错误问题
我在Ubuntu系统上基于ARM Cortex-M4芯片开发项目,使用Makefile和gcc-arm-none-eabi工具链。添加math.h库并调用log10f函数时,链接器报错退出,尝试添加-lm参数无效。以下是我的Makefile和错误信息:
原Makefile
# PROJECT: name of the output file PROJECT = main SRCS = $(wildcard src/*.c) \ $(wildcard libs/*.c) OBJ = obj/ # OBJS: list of object files OBJS = $(addprefix $(OBJ),$(notdir $(SRCS:.c=.o))) #Flag points to the INC folder containing header files INC = -Iinc # LD_SCRIPT: linker script LD_SCRIPT = ld/GD32f30x.ld #UTILITY VARIABLES CC = arm-none-eabi-gcc #compiler LD = arm-none-eabi-ld #linker OBJCOPY =arm-none-eabi-objcopy #final executable builder RM = rm -rf MKDIR = @mkdir -p $(@D) #creates folders if not present #GCC FLAGS CFLAGS = -ggdb -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 CFLAGS += -mfloat-abi=softfp -Os -MD -std=c99 -c #LINKER FLAGS LDFLAGS = -T $(LD_SCRIPT) -e Reset_Handler # Rules to build bin all: bin/$(PROJECT).bin $(OBJ)%.o: src/%.c #turns .c source files into object files $(MKDIR) $(CC) -o $@ $^ $(INC) $(CFLAGS) $(OBJ)%.o: libs/%.c #turns .c source files into object files $(MKDIR) $(CC) -o $@ $^ $(INC) $(CFLAGS) bin/$(PROJECT).elf: $(OBJS) ##contains debug symbols for GNU GDB $(MKDIR) $(LD) -o $@ $^ $(LDFLAGS) bin/$(PROJECT).bin: bin/$(PROJECT).elf #debug symbols for GNU GDB stripped by objcopy,finished binary ready for flashing $(OBJCOPY) -O binary $< $@ #Flashes bin to TM4C flash: $(FLASHER) -S $(DEV) bin/$(PROJECT).bin #remove object and bin files clean: -$(RM) obj -$(RM) bin .PHONY: all clean
链接器错误信息
arm-none-eabi-gcc -o obj/ntc_sensor.o libs/ntc_sensor.c -Iinc -I/usr/lib/arm-none-eabi/include -ggdb -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -Os -MD -std=c99 -c arm-none-eabi-ld -o bin/main.user obj/main.o obj/gd32f30x_rcu.o obj/gd32f30x_gpio.o obj/ntc_sensor.o obj/HT1621B.o obj/temp_ctrl.o obj/gd32f30x_it.o obj/systick.o obj/gd32f30x_pmu.o obj/system_gd32f30x.o obj/startup.o obj/gd32f30x_adc.o -T ld/GD32f30x.ld -e Reset_Handler arm-none-eabi-ld: obj/ntc_sensor.o: in function `ln': /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:51: undefined reference to `__aeabi_dsub' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:51: undefined reference to `__aeabi_dadd' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:51: undefined reference to `__aeabi_ddiv' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:56: undefined reference to `__aeabi_dcmpgt' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:64: undefined reference to `__aeabi_dadd' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:58: undefined reference to `__aeabi_dadd' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:60: undefined reference to `__aeabi_dadd' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:61: undefined reference to `__aeabi_dmul' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:61: undefined reference to `__aeabi_dmul' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:62: undefined reference to `__aeabi_ddiv' arm-none-eabi-ld: obj/ntc_sensor.o: in function `log10': /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:70: undefined reference to `__aeabi_dmul' arm-none-eabi-ld: obj/ntc_sensor.o: in function `get_ntc_Temperature': /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:121: undefined reference to `__aeabi_f2d' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:121: undefined reference to `__aeabi_dmul' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:121: undefined reference to `__aeabi_dadd' arm-none-eabi-ld: /home/user/project/embedded/ARM/GigaDevice/GD32f30x/Termostat/libs/ntc_sensor.c:121: undefined reference to `__aeabi_d2f' make: *** [Makefile:51: bin/main.user] Error 1
错误原因分析
报错中的__aeabi_dxxx是双精度浮点运算的ABI函数,问题根源有两点:
- 直接使用
arm-none-eabi-ld手动链接,无法自动处理标准C库、浮点库的依赖路径,即使添加-lm也无法正确找到库文件; - 代码中混用了单精度(float)和双精度(double)运算,编译器生成了双精度调用,而Cortex-M4的FPU仅支持单精度(fpv4-sp-d16),缺少双精度运算的支持库。
解决步骤
1. 改用gcc而非ld进行链接
arm-none-eabi-gcc会自动处理库的搜索路径和依赖关系,修改Makefile中的链接相关配置:
- 将
LD变量改为arm-none-eabi-gcc - 在
LDFLAGS中添加-lm(数学库),保留原链接脚本和入口参数
2. 强制单精度浮点编译
在CFLAGS中添加参数,确保编译器默认使用单精度,避免不必要的双精度转换:
- 添加
-fsingle-precision-constant:将所有浮点常量视为float类型,而非默认的double - 代码中确保使用
log10f()(单精度)而非log10()(双精度),所有浮点变量用float声明
修改后的Makefile
# PROJECT: name of the output file PROJECT = main SRCS = $(wildcard src/*.c) \ $(wildcard libs/*.c) OBJ = obj/ # OBJS: list of object files OBJS = $(addprefix $(OBJ),$(notdir $(SRCS:.c=.o))) #Flag points to the INC folder containing header files INC = -Iinc # LD_SCRIPT: linker script LD_SCRIPT = ld/GD32f30x.ld #UTILITY VARIABLES CC = arm-none-eabi-gcc #compiler LD = arm-none-eabi-gcc # 改用gcc执行链接 OBJCOPY =arm-none-eabi-objcopy #final executable builder RM = rm -rf MKDIR = @mkdir -p $(@D) #creates folders if not present #GCC FLAGS CFLAGS = -ggdb -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 CFLAGS += -mfloat-abi=softfp -Os -MD -std=c99 -c CFLAGS += -fsingle-precision-constant # 强制单精度浮点常量 #LINKER FLAGS LDFLAGS = -T $(LD_SCRIPT) -e Reset_Handler -lm # 添加数学库-lm # Rules to build bin all: bin/$(PROJECT).bin $(OBJ)%.o: src/%.c #turns .c source files into object files $(MKDIR) $(CC) -o $@ $^ $(INC) $(CFLAGS) $(OBJ)%.o: libs/%.c #turns .c source files into object files $(MKDIR) $(CC) -o $@ $^ $(INC) $(CFLAGS) bin/$(PROJECT).elf: $(OBJS) ##contains debug symbols for GNU GDB $(MKDIR) $(LD) -o $@ $^ $(LDFLAGS) # 用gcc执行链接 bin/$(PROJECT).bin: bin/$(PROJECT).elf #debug symbols for GNU GDB stripped by objcopy,finished binary ready for flashing $(OBJCOPY) -O binary $< $@ #Flashes bin to TM4C flash: $(FLASHER) -S $(DEV) bin/$(PROJECT).bin #remove object and bin files clean: -$(RM) obj -$(RM) bin .PHONY: all clean
3. 代码层面检查
确保ntc_sensor.c中:
- 所有浮点变量使用
float类型,避免double - 调用
log10f()而非log10() - 浮点运算优先使用单精度函数(如
sinf、cosf而非sin、cos)
推荐学习资源
- GCC ARM嵌入式编译指南:官方文档,详细讲解编译选项、ABI规则和库链接逻辑
- ARM Cortex-M4技术参考手册:深入了解FPU架构、浮点运算支持细节
- Makefile嵌入式实战教程:掌握嵌入式项目的Makefile编写技巧,包括库链接、依赖管理
- 嵌入式C浮点编程优化:学习如何在MCU上高效使用浮点运算,避免不必要的精度开销
内容的提问来源于stack exchange,提问作者mohsen setodeh
相关产品推荐
相关产品推荐

