I'm using the arm-none-eabi-gcc toolchain onlinux and am having trouble creating archives that link to other archives. As a specific example, the base archive (libstm32f4_hal.a) should have a function HAL_SPI_GetState
and using nm
, it seems that it does
$ nm libstm32f4_hal.a
stm32f4xx_hal_spi.o:
...
0000158d T HAL_SPI_GetState
00001495 T HAL_SPI_IRQHandler
00000271 T HAL_SPI_Init
...
I then want to make another archive (libstm32f4_bsp.a) which makes use of libstm32f4_hal.a. The second archive seems to build correctly, but when I try and link against these libraries, the linker throws the following error.
cube/Drivers/BSP/STM32F4-Discovery/libstm32f4_bsp.a(stm32f4_discovery.o): In function `SPIx_Init':
cube/Drivers/BSP/STM32F4-Discovery/stm32f4_discovery.c:313: undefined reference to `HAL_SPI_GetState'
When I check libstm32f4_bsp.a using nm
, indeed the function HAL_SPI_GetState
is not defined.
$ nm libstm32f4_bsp.a
stm32f4_discovery.o:
...
U HAL_SPI_GetState
U HAL_SPI_Init
...
Here is the makefile I'm using to build the second archive.
CC=arm-none-eabi-gcc
AR=arm-none-eabi-ar
HAL_DIR = ../../STM32F4xx_HAL_Driver
###########################################
vpath %.c
CFLAGS = -g -O2 -Wall
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 -mthumb-interwork
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
CFLAGS += -ffreestanding -nostdlib
CFLAGS += -I$(HAL_DIR)/Inc
CFLAGS += -I../../CMSIS/Device/ST/STM32F4xx/Include
CFLAGS += -I../../CMSIS/Include
SRCS = stm32f4_discovery.c stm32f4_discovery_accelerometer.c stm32f4_discovery_audio.c
OBJS = $(SRCS:.c=.o)
.PHONY: all clean
all: libstm32f4_bsp.a
%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $^ -L$(HAL_DIR) -lstm32f4_hal
libstm32f4_bsp.a: $(OBJS)
$(AR) -rvs $@ $(OBJS)
clean:
rm -f $(OBJS) libstm32f4_bsp.a
Could someone explain why this might be happening? I'd be happy to provide more details but am relatively inexperienced with what I'm trying to do here and am not completely sure what else would be helpful.
The context is, I'm trying to build the demonstration code for the STM32F4-Discovery board. It basically sets up the board to act as a USB mouse. Since the USB stack is huge, my plan is to build the hardware abstraction layer (HAL) as an archive, then build the board-specific middleware as an archive linked to the HAL archive, and then in my final build link the demonstration code to these two archives.
Thanks for the help.
EDIT:
Here is the makefile I'm using to build the project.
# STM32 Makefile for GNU toolchain and openocd
#
# This Makefile fetches the Cube firmware package from ST's' website.
# This includes: CMSIS, STM32 HAL, BSPs, USB drivers and examples.
#
# Usage:
# make cube Download and unzip Cube firmware
# make program Flash the board with OpenOCD
# make openocd Start OpenOCD
# make debug Start GDB and attach to OpenOCD
# make dirs Create subdirs like obj, dep, ..
# make template Prepare a simple example project in this dir
#
# Copyright 2015 Steffen Vogel
# License http://www.gnu.org/licenses/gpl.txt GNU Public License
# Author Steffen Vogel <post@steffenvogel.de>
# Link http://www.steffenvogel.de
#
# edited for the STM32F4-Discovery
# A name common to all output files (elf, map, hex, bin, lst)
TARGET = demo
# Take a look into $(CUBE_DIR)/Drivers/BSP for available BSPs
BOARD = STM32F4-Discovery
BSP_BASE = stm32f4_discovery
OCDFLAGS = -f board/stm32f4discovery.cfg
GDBFLAGS =
#EXAMPLE = Templates
EXAMPLE = Demonstrations
# MCU family and type in various capitalizations o_O
MCU_FAMILY = stm32f4xx
MCU_LC = stm32f401xc
MCU_MC = STM32F407xx
MCU_UC = STM32F407VG
# Your C files from the /src directory
SRCS = main.c
SRCS += system_$(MCU_FAMILY).c
SRCS += stm32f4xx_it.c
# Basic HAL libraries
#SRCS += stm32f4xx_hal_rcc.c stm32f4xx_hal_rcc_ex.c stm32f4xx_hal.c stm32f4xx_hal_cortex.c stm32f4xx_hal_gpio.c $(BSP_BASE).c
# USB .c
SRCS += usbd_conf_template.c usbd_core.c usbd_ctlreq.c usbd_ioreq.c
SRCS += usbd_hid.c
SRCS += usbd_desc.c
SRCS += stm32f4xx_hal_pcd.c
SRCS += stm32f4_discovery_accelerometer.c stm32f4xx_hal_tim.c
# Directories
OCD_DIR = /usr/share/openocd/scripts
CUBE_DIR = cube
BSP_DIR = $(CUBE_DIR)/Drivers/BSP/$(BOARD)
HAL_DIR = $(CUBE_DIR)/Drivers/STM32F4xx_HAL_Driver
CMSIS_DIR = $(CUBE_DIR)/Drivers/CMSIS
DEV_DIR = $(CMSIS_DIR)/Device/ST/STM32F4xx
CUBE_URL = http://www.st.com/st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stm32cubef4.zip
# that's it, no need to change anything below this line!
###############################################################################
# Toolchain
PREFIX = arm-none-eabi
CC = $(PREFIX)-gcc
AR = $(PREFIX)-ar
OBJCOPY = $(PREFIX)-objcopy
OBJDUMP = $(PREFIX)-objdump
SIZE = $(PREFIX)-size
GDB = $(PREFIX)-gdb
OCD = openocd
###############################################################################
# Options
# Defines
DEFS = -D$(MCU_MC) -DUSE_HAL_DRIVER
# Debug specific definitions for semihosting
DEFS += -DUSE_DBPRINTF
# Include search paths (-I)
INCS = -Itemplate/inc
INCS += -I$(BSP_DIR)
INCS += -I$(CMSIS_DIR)/Include
INCS += -I$(DEV_DIR)/Include
INCS += -I$(HAL_DIR)/Inc
# USB .h
INCS += -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Inc
INCS += -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc
# Library search paths
LIBS = -L$(CMSIS_DIR)/Lib
# Compiler flags
CFLAGS = -Wall -g -std=c99 -Os
CFLAGS += -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb
CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += $(INCS) $(DEFS)
CFLAGS += -mthumb-interwork
# Linker flags
LDFLAGS = -Wl,--gc-sections -Wl,-Map=$(TARGET).map $(LIBS) -Ttemplate/$(MCU_LC).ld
# Enable Semihosting
LDFLAGS += --specs=rdimon.specs -lc -lrdimon
# Source search paths
VPATH = ./template/src
VPATH += $(BSP_DIR)
VPATH += $(HAL_DIR)/Src
VPATH += $(DEV_DIR)/Source/
VPATH += $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src
VPATH += $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src
OBJS = $(addprefix template/obj/,$(SRCS:.c=.o))
DEPS = $(addprefix template/dep/,$(SRCS:.c=.d))
# Prettify output
V = 0
Q = @
P = > /dev/null
endif
###################################################
.PHONY: all dirs program debug template clean
all: $(TARGET).elf
-include $(DEPS)
dirs: template/dep template/obj cube
template/dep template/obj template/src template/inc:
@echo "[MKDIR] $@"
$Qmkdir -p $@
template/obj/%.o : %.c | dirs
@echo "[CC] $(notdir $<)"
$Q$(CC) $(CFLAGS) -c -o $@ $< -MMD -MF template/dep/$(*F).d -L$(HAL_DIR) -lstm32f4_hal -L$(BSP_DIR) -lstm32f4_bsp
$(TARGET).elf: $(OBJS)
@echo "[LD] $(TARGET).elf"
$Q$(CC) $(CFLAGS) $(LDFLAGS) template/src/startup_$(MCU_LC).s $^ -o $@ -L$(HAL_DIR) -lstm32f4_hal -L$(BSP_DIR) -lstm32f4_bsp
@echo "[OBJDUMP] $(TARGET).lst"
$Q$(OBJDUMP) -St $(TARGET).elf >$(TARGET).lst
@echo "[SIZE] $(TARGET).elf"
$(SIZE) $(TARGET).elf
openocd:
$(OCD) -s $(OCD_DIR) $(OCDFLAGS)
program: all
$(OCD) -s $(OCD_DIR) $(OCDFLAGS) -c "program $(TARGET).elf verify reset"
debug:
@if ! nc -z localhost 3333; then \
echo "\n\t[Error] OpenOCD is not running! Start it with: 'make openocd'\n"; exit 1; \
else \
$(GDB) -ex "target extended localhost:3333" \
-ex "monitor arm semihosting enable" \
-ex "monitor reset halt" \
-ex "load" \
-ex "monitor reset init" \
$(GDBFLAGS) $(TARGET).elf; \
fi
cube:
rm -fr $(CUBE_DIR)
wget -O /tmp/cube.zip $(CUBE_URL)
unzip /tmp/cube.zip
mv STM32Cube* $(CUBE_DIR)
chmod -R u+w $(CUBE_DIR)
rm -f /tmp/cube.zip
template: cube template/src template/inc
cp -ri $(CUBE_DIR)/Projects/$(BOARD)/$(EXAMPLE)/Src/* template/src
cp -ri $(CUBE_DIR)/Projects/$(BOARD)/$(EXAMPLE)/Inc/* template/inc
cp -i $(DEV_DIR)/Source/Templates/gcc/startup_$(MCU_LC).s template/src
cp -i $(CUBE_DIR)/Projects/$(BOARD)/$(EXAMPLE)/TrueSTUDIO/STM32F4-DISCO/$(MCU_UC)_FLASH.ld template/$(MCU_LC).ld
clean:
@echo "[RM] $(TARGET).elf"; rm -f $(TARGET).elf
@echo "[RM] $(TARGET).map"; rm -f $(TARGET).map
@echo "[RM] $(TARGET).lst"; rm -f $(TARGET).lst
@echo "[RMDIR] template/dep" ; rm -fr template/dep
@echo "[RMDIR] template/obj" ; rm -fr template/obj
rm:
rm -rf template
ifeq ($V, 0)
Here is the failed linking command.
`arm-none-eabi-gcc -Wall -g -std=c99 -Os -mlittle-endian -mcpu=cortex-m4 -march=armv7e-m -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -Itemplate/inc -Icube/Drivers/BSP/STM32F4-Discovery -Icube/Drivers/CMSIS/Include -Icube/Drivers/CMSIS/Device/ST/STM32F4xx/Include -Icube/Drivers/STM32F4xx_HAL_Driver/Inc -Icube/Middlewares/ST/STM32_USB_Device_Library/Core/Inc -Icube/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc -DSTM32F407xx -DUSE_HAL_DRIVER -DUSE_DBPRINTF -mthumb-interwork -Wl,--gc-sections -Wl,-Map=demo.map -Lcube/Drivers/CMSIS/Lib -Ttemplate/stm32f401xc.ld --specs=rdimon.specs -lc -lrdimon template/src/startup_stm32f401xc.s template/obj/main.o template/obj/system_stm32f4xx.o template/obj/stm32f4xx_it.o template/obj/usbd_conf_template.o template/obj/usbd_core.o template/obj/usbd_ctlreq.o template/obj/usbd_ioreq.o template/obj/usbd_hid.o template/obj/usbd_desc.o template/obj/stm32f4xx_hal_pcd.o template/obj/stm32f4_discovery_accelerometer.o template/obj/stm32f4xx_hal_tim.o -o demo.elf -Lcube/Drivers/STM32F4xx_HAL_Driver -lstm32f4_hal -Lcube/Drivers/BSP/STM32F4-Discovery -lstm32f4_bsp'
I loaded the project to github here in case anyone is motivated enough to try and build the project themselves. As a side note, I am running Arch linux.