Electronic – ‘undefined reference to’ errors trying to compile with Make

ccompiler

I had a working Makefile that successfully compiled and built a basic program to toggle and LED on my stm32-h103 board. I have since attempted to add and use FreeRTOS in my program. I have added in the FreeRTOS paths into my Makefile however I am getting the following errors when I run make.

src/app.a(startup.o):(.isr_vectors+0x2c): undefined reference to `vPortSVCHandler'
src/app.a(startup.o):(.isr_vectors+0x38): undefined reference to `xPortPendSVHandler'
src/app.a(startup.o):(.isr_vectors+0x3c): undefined reference to `xPortSysTickHandler'
src/app.a(main.o): In function `main':
/home/matthew/Work/22_ARM-Firmware/HomeAutomationControllerPrototype/src/main.c:36: undefined reference to `xTaskGenericCreate'
/home/matthew/Work/22_ARM-Firmware/HomeAutomationControllerPrototype/src/main.c:37: undefined reference to `vTaskStartScheduler'
collect2: error: ld returned 1 exit status

I am very new to Makefiles so am unsure what else I must add to get the code to compile.

My two make files are:

Makefile.common

TOP=$(shell readlink -f "$(dir $(lastword $(MAKEFILE_LIST)))")
PROGRAM=main
LIBDIR=$(TOP)/libs
FREERTOSDIR=$(TOP)/src/FreeRTOS/Source

#Adust the following line to the library in use
STMLIB=$(LIBDIR)/STM32F10x_StdPeriph_Lib_V3.6.1/Libraries

#Adjust TypeOfMCU in use, see CMSIS file "stm32f10x.h"
#STM32F103RBT (128KB FLASH, 20KB RAM) --> STM32F10X_MD
TypeOfMCU=STM32F10X_MD
#STM32F103RET (512KB FLASH, 64KB RAM) --> STM32F10X_HD
#TypeOfMCU=STM32F10X_HD

TC=arm-none-eabi
CC=$(TC)-gcc
LD=$(TC)-ld -v
OBJCOPY=$(TC)-objcopy
AR=$(TC)-ar
GDB=$(TC)-gdb

INCLUDE=-I$(TOP)/inc
INCLUDE+=-I$(STMLIB)/CMSIS/Include
INCLUDE+=-I$(STMLIB)/CMSIS/Device/ST/STM32F10x/Include
INCLUDE+=-I$(STMLIB)/CMSIS/Device/ST/STM32F10x/Source/Templates
INCLUDE+=-I$(STMLIB)/STM32F10x_StdPeriph_Driver/inc
INCLUDE+=-I$(STMLIB)/STM32_USB-FS-Device_Driver/inc
INCLUDE+=-I$(FREERTOSDIR)/include
INCLUDE+=-I$(FREERTOSDIR)/portable/GCC/ARM_CM3
INCLUDE+=-I$(TOP)/src


COMMONFLAGS=-g -mcpu=cortex-m3 -mthumb
COMMONFLAGSlib=$(COMMONFLAGS)

#Commands for general Makefile and src Makefile
ifeq ($(OptSRC),0)
    COMMONFLAGS+=-O0
    InfoTextSrc=src (no optimize, -O0)
else ifeq ($(OptSRC),1)
    COMMONFLAGS+=-O1
    InfoTextSrc=src (optimize time+ size+, -O1)
else ifeq ($(OptSRC),2)
    COMMONFLAGS+=-O2
    InfoTextSrc=src (optimize time++ size+, -O2)
else ifeq ($(OptSRC),s)
    COMMONFLAGS+=-Os
    InfoTextSrc=src (optimize size++, -Os) 
else ifeq ($(OptSRC),3)
    COMMONFLAGS+=-O3
    InfoTextSrc=src (full optimize, -O3)
else
    COMMONFLAGS+=-O3
    CFLAGS += -D RELEASE_PUBLIC
    InfoTextSrc=src (full optimize and readout protected, -O4)
endif
CFLAGS+=$(COMMONFLAGS) -Wall -Werror $(INCLUDE)
CFLAGS+=-D $(TypeOfMCU)
CFLAGS+=-D VECT_TAB_FLASH

#Commands for libs Makefile
ifeq ($(OptLIB),0)
    COMMONFLAGSlib+=-O0
    InfoTextLib=libs (no optimize, -O0)
else ifeq ($(OptLIB),1)
    COMMONFLAGSlib+=-O1
    InfoTextLib=libs (optimize time+ size+, -O1)
else ifeq ($(OptLIB),2)
    COMMONFLAGSlib+=-O2
    InfoTextLib=libs (optimize time++ size+, -O2)
else ifeq ($(OptLIB),s)
    COMMONFLAGSlib+=-Os
    InfoTextLib=libs (optimize size++, -Os)
else
    COMMONFLAGSlib+=-O3
InfoTextLib=libs (full optimize, -O3)
endif
CFLAGSlib+=$(COMMONFLAGSlib) -Wall -Werror $(INCLUDE)
CFLAGSlib+=-D $(TypeOfMCU)
CFLAGSlib+=-D VECT_TAB_FLASH

And my src Makefile

# src Makefile

include ../Makefile.common

OBJS+=startup.o
OBJS+=main.o

all: src

src: app.a

app.a: $(OBJS)
    $(AR) cr app.a $(OBJS)

.PHONY: src clean tshow

clean:
    rm -f app.a $(OBJS)

Best Answer

As well as pointing to the header files so your source knows what functions are available, you also have to link in the code for those functions.

You are referencing the .h files fine, but FreeRTOS also consists of many .c files. Those .c files need to be compiled along with your code and then linked together during the final phase of compilation.

Personally I would compile all of the FreeRTOS files separately as an individual step, then combine them into an archive file, say libFreeRTOS.a which you can then link against using -lFreeRTOS (similar to how you're making app.a, but using the proper libXXX.a format so it works with -l).