Problem:
The firmware image generated when linking with a static library is different to the firmware image generated when linking with the objects directly extracted from the static library.
Both firmware images link without error and load successfully onto the microcontroller.
The latter binary (linked with objects) executes successfully and as expected, while the former (linked to the static library) does not.
The only warnings during compilation are unused-but-set-variable
in the manufacturer-supplied HAL, which due to various macro definitions are not necessary for the compiled implementation; and unused-parameter
in various weak functions, also within the manufacturer-supplied HAL.
Description:
I am developing an embedded application for the STM32F407. Until now I have been working with one code base including the microprocessor's HAL & setup code, a driver for a specific peripheral, and an application utilizing the former two.
Since I wish to develop multiple applications using the same driver & HAL (both are complete and tested, so won't change often), I wish to compile & distribute the HAL and driver as a static library, which can then be linked with the application source.
The problem is that when linking the application and static library, the firmware image does not execute correctly on the microprocessor. When linking the application and the object files directly extracted from the static library, the firmware image executes as expected.
Specifically:
Created binary does not work when linking with static library using:
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(APPOBJECTS) Library/libtest.a
Created binary works when linking with objects extracted from static library using:
@cd Library && $(AR) x libtest.a && cd ..
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(APPOBJECTS) Library/*.o
In both cases:
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
I have compared the outputs of -Wl,--print-gc-sections
as well as the app.map
file, but enough is different between the two builds that no one thing jumps out as being wrong. I have also tried without -Wl,--gc-sections
, to no avail.
The output of arm-none-eabi-size
of the two firmware images is:
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
A similar size discrepancy can be seen when compiling without -Wl,--gc-sections
Using arm-none-eabi-gdb
to debug the microcontroller's execution, the faulty firmware image enters an infinite loop when the WWDG interrupt occurs. This interrupt is not enabled in the firmware and thus the interrupt handler defaults to the Default_Handler
(an infinite loop). This interrupt does not occur when running the working firmware image.
The WWDG interrupt occurring is actually a red herring, as described in the accepted answer
--Mike