You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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函数,问题根源有两点:

  1. 直接使用arm-none-eabi-ld手动链接,无法自动处理标准C库、浮点库的依赖路径,即使添加-lm也无法正确找到库文件;
  2. 代码中混用了单精度(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:05:21