问题:
使用静态库链接生成的固件映像与使用直接从静态库中提取的对象链接生成的固件映像不同。
两个固件映像都可以成功链接并成功加载到微控制器上。
后者(链接对象)执行正常,符合预期,而前者(链接静态库)则不然。
编译期间唯一的警告是生产商提供的HAL中的 unused-but-set-variable
,由于各种宏定义在已编译的实现中不必要;以及各种弱函数中的unused-parameter
,也在生厂商提供的HAL中。
描述:
我正在为STM32F407开发嵌入式应用程序。到目前为止,我一直在使用一个代码库,其中包括微处理器的HAL和设置代码、特定外设的驱动程序以及利用前两者的应用程序。
由于我希望使用相同的驱动程序和HAL开发多个应用程序(两者都是完整且经过测试,所以不会经常更改),因此我希望将HAL和驱动程序编译并分发为静态库,然后可以将其与应用程序源代码链接。
问题在于,在链接应用程序和静态库时,固件映像在微处理器上无法正确执行。当直接从静态库中提取对象文件并将其与应用程序链接时,固件映像会按预期执行。
具体而言:
使用以下方法链接静态库时创建的二进制文件无法正常工作:
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(APPOBJECTS) Library/libtest.a
当使用以下方式链接从静态库中提取的对象时,创建二进制文件:
@cd Library && $(AR) x libtest.a && cd ..
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(APPOBJECTS) Library/*.o
两种情况下:
CFLAGS = $(INCLUDES) $(DEFS) -ggdb3 -O0 -std=c99 -Wall -specs=nano.specs -nodefaultlibs
CFLAGS+= -fdata-sections -ffunction-sections -mcpu=cortex-m4 -march=armv7e-m -mthumb
CFLAGS+= -mfloat-abi=hard -mfpu=fpv4-sp-d16 -MD -MP -MF $@.d
LDFLAGS = -T$(LDSCRIPT) -Wl,-static -Wl,-Map=$(@:.elf=.map),--cref -Wl,--gc-sections
我已经比较了
-Wl,--print-gc-sections
的输出以及app.map
文件,但是两个构建之间有足够的不同,没有一件事情突出为错误。我也尝试了没有-Wl,--gc-sections
,但无济于事。两个固件映像的
arm-none-eabi-size
输出如下: text data bss dec hex filename
43464 76 8568 52108 cb8c workingapp.elf
text data bss dec hex filename
17716 44 8568 26328 66d8 brokenapp.elf
如果不使用-Wl,--gc-sections
编译,则会出现类似的大小差异。
使用arm-none-eabi-gdb
来调试微控制器的执行,当WWDG中断发生时,错误的固件映像进入无限循环。该中断在固件中未启用,因此中断处理程序默认为Default_Handler
(无限循环)。运行工作的固件映像时不会发生此中断。
实际上,WWDG中断发生是一个误导,如被接受的答案所述
--Mike