Hello all,
I m seeing a very very weird issue not being able to build freertos into my project.
I m using stm32f103, libopencm3 along with freertos. I have copied the FreeRTOSConfig.h file from the Cortex_STM32F103_GCC_Rowley folder.
My directory structure looks like so
.
├── ceedling
├── CHANGELOG.md
├── Dockerfile
├── project.yml
├── README.md
├── rules.mk
├── src
│ ├── adapters
│ │ ├── apiFreeRTOS.h
│ │ └── apiLibopenCM3.h
│ ├── device_drivers
│ │ ├── ddrvDisp.c
│ │ ├── ddrvDisp.h
│ │ └── Readme.md
│ ├── errorno.h
│ ├── FreeRTOSConfig.h
│ ├── main.c
│ ├── Makefile
│ ├── managers
│ │ ├── dispMan.c
│ │ ├── dispMan.h
│ │ └── Readme.md
│ ├── submodules
│ │ └── freertos
│ └── virtual_devices
│ ├── Readme.md
│ ├── vdevDisp.c
│ └── vdevDisp.h
├── submodules
│ ├── freertos
│ │ ├── cspell.config.yaml
│ │ ├── FreeRTOS
│ │ ├── FreeRTOS-Plus
│ │ ├── FreeRTOS+TCP.url
│ │ ├── GitHub-FreeRTOS-Home.url
│ │ ├── History.txt
│ │ ├── LICENSE.md
│ │ ├── manifest.yml
│ │ ├── Quick_Start_Guide.url
│ │ ├── README.md
│ │ ├── tools
│ │ └── Upgrading-to-FreeRTOS.url
│ └── libopencm3
│ ├── COPYING.GPL3
│ ├── COPYING.LGPL3
│ ├── doc
│ ├── HACKING
│ ├── HACKING_COMMON_DOC
│ ├── include
│ ├── ld
│ ├── lib
│ ├── locm3.sublime-project
│ ├── Makefile
│ ├── mk
│ ├── README.md
│ ├── scripts
│ └── tests
├── test
│ ├── device_drivers
│ │ └── test_ddrvDisp.c
│ ├── managers
│ │ └── test_dispMan.c
│ ├── support
│ └── virtual_devices
│ └── test_vdevDisp.c
└── vendor
└── ceedling
├── bin
├── docs
├── lib
├── plugins
└── vendor
The names of the folders indicate the purpose of the files inside.
The Makefile inside the src folder looks like this
PROJECT = aws
BUILD_DIR = binaries
DEVICE_DRIVERS = device_drivers
MANAGERS = managers
VIRTUAL_DEVICES = virtual_devices
ADAPTERS = adapters
SOURCES_DEVICE_DRIVERS = $(wildcard device_drivers/*.c)
SOURCES_MANAGERS = $(wildcard managers/*.c)
SOURCES_VIRTUAL_DEVICES = $(wildcard virtual_devices/*.c)
SOURCES_ADAPTERS = $(wildcard adapters/*.c)
FREERTOS_SRC = ../submodules/freertos/FreeRTOS/Source
FREERTOS_HEADERS = ../submodules/freertos/FreeRTOS/Source/include
INCLUDES += -I$(FREERTOS_HEADERS)
INCLUDES += -I$(FREERTOS_SRC)/portable/GCC/ARM_CM3
INCLUDES += -I$(DEVICE_DRIVERS)
INCLUDES += -I$(MANAGERS)
INCLUDES += -I$(VIRTUAL_DEVICES)
INCLUDES += -I$(ADAPTERS)
TGT_CFLAGS += -I$(FREERTOS_HEADERS)
TGT_CXXFLAGS += -I$(FREERTOS_HEADERS)
# define TEST for compiledb to generate the lsp compilation database
#TEST?=0
#ifeq ($(TEST),1)
#TGT_CFLAGS += -DTEST
#TGT_CXXFLAGS += -DTEST
#endif
CFILES = main.c
CFILES += $(SOURCES_DEVICE_DRIVERS) $(SOURCES_MANAGERS) $(SOURCES_ADAPTERS) $(SOURCES_VIRTUAL_DEVICES)
CFILES += $(FREERTOS_SRC)/portable/GCC/ARM_CM3/port.c $(FREERTOS_SRC)/tasks.c $(FREERTOS_SRC)/list.c $(FREERTOS_SRC)/queue.c $(FREERTOS_SRC)/portable/MemMang/heap_2.c $(FREERTOS_SRC)/timers.c
# TODO - you will need to edit these two lines!
DEVICE=stm32f103rct6
OOCD_FILE = target/stm32f1x.cfg
# You shouldn't have to edit anything below here.
VPATH += $(SHARED_DIR)
INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
OPENCM3_DIR=../submodules/libopencm3
include $(OPENCM3_DIR)/mk/genlink-config.mk
include ../rules.mk
include $(OPENCM3_DIR)/mk/genlink-rules.mk
and the top level rules.mk file looks like so.
BUILD_DIR ?= binaries
OPT ?= -Os
CSTD ?= -std=c99
# Be silent per default, but 'make V=1' will show all compiler calls.
# If you're insane, V=99 will print out all sorts of things.
V?=0
ifeq ($(V),0)
Q := @
NULL := 2>/dev/null
endif
# Tool paths.
PREFIX ?= arm-none-eabi-
CC = $(PREFIX)gcc
CXX = $(PREFIX)g++
LD = $(PREFIX)gcc
OBJCOPY = $(PREFIX)objcopy
OBJDUMP = $(PREFIX)objdump
OOCD ?= openocd
OPENCM3_INC = $(OPENCM3_DIR)/include
# Inclusion of library header files
INCLUDES += $(patsubst %,-I%, . $(OPENCM3_INC) )
OBJS = $(CFILES:%.c=$(BUILD_DIR)/%.o)
OBJS += $(CXXFILES:%.cxx=$(BUILD_DIR)/%.o)
OBJS += $(AFILES:%.S=$(BUILD_DIR)/%.o)
GENERATED_BINS = $(BUILD_DIR)/$(PROJECT).elf $(PROJECT).bin $(PROJECT).map $(PROJECT).list $(PROJECT).lss
TGT_CPPFLAGS += -MD
TGT_CPPFLAGS += -Wall -Wundef $(INCLUDES)
TGT_CPPFLAGS += $(INCLUDES) $(OPENCM3_DEFS)
TGT_CFLAGS += $(OPT) $(CSTD) -ggdb3
TGT_CFLAGS += $(ARCH_FLAGS)
TGT_CFLAGS += -fno-common
TGT_CFLAGS += -ffunction-sections -fdata-sections
TGT_CFLAGS += -Wextra -Wshadow -Wno-unused-variable -Wimplicit-function-declaration
TGT_CFLAGS += -Wredundant-decls -Wstrict-prototypes -Wmissing-prototypes
TGT_CXXFLAGS += $(OPT) $(CXXSTD) -ggdb3
TGT_CXXFLAGS += $(ARCH_FLAGS)
TGT_CXXFLAGS += -fno-common
TGT_CXXFLAGS += -ffunction-sections -fdata-sections
TGT_CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++
TGT_ASFLAGS += $(OPT) $(ARCH_FLAGS) -ggdb3
TGT_LDFLAGS += -T$(LDSCRIPT) -L$(OPENCM3_DIR)/lib -nostartfiles
TGT_LDFLAGS += $(ARCH_FLAGS)
TGT_LDFLAGS += -specs=nano.specs
TGT_LDFLAGS += -Wl,--gc-sections
# OPTIONAL
TGT_LDFLAGS += -Wl,-Map=$(PROJECT).map
ifeq ($(V),99)
TGT_LDFLAGS += -Wl,--print-gc-sections
endif
# Linker script generator fills this in for us.
ifeq (,$(DEVICE))
LDLIBS += -l$(OPENCM3_LIB)
endif
# nosys is only in newer gcc-arm-embedded...
LDLIBS += -specs=nosys.specs
LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
# Burn in legacy hell fortran modula pascal yacc idontevenwat
.SUFFIXES:
.SUFFIXES: .c .S .h .o .cxx .elf .bin .list .lss
# Bad make, never *ever* try to get a file out of source control by yourself.
%: %,v
%: RCS/%,v
%: RCS/%
%: s.%
%: SCCS/s.%
all: $(PROJECT).elf $(PROJECT).bin
flash: $(PROJECT).flash
# error if not using linker script generator
ifeq (,$(DEVICE))
$(LDSCRIPT):
ifeq (,$(wildcard $(LDSCRIPT)))
$(error Unable to find specified linker script: $(LDSCRIPT))
endif
else
# if linker script generator was used, make sure it's cleaned.
GENERATED_BINS += $(LDSCRIPT)
endif
# Need a special rule to have a bin dir
$(BUILD_DIR)/%.o: %.c
@printf " CC\t$<\n"
@mkdir -p $(dir $@)
$(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $@ -c $<
$(BUILD_DIR)/%.o: %.cxx
@printf " CXX\t$<\n"
@mkdir -p $(dir $@)
$(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $@ -c $<
$(BUILD_DIR)/%.o: %.S
@printf " AS\t$<\n"
@mkdir -p $(dir $@)
$(Q)$(CC) $(TGT_ASFLAGS) $(ASFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $@ -c $<
$(PROJECT).elf: $(OBJS) $(LDSCRIPT) $(LIBDEPS)
@printf " LD\t$@\n"
$(Q)$(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(BUILD_DIR)/$@
%.bin: %.elf
@printf " OBJCOPY\t$@\n"
$(Q)$(OBJCOPY) -O binary $(BUILD_DIR)/$< $(BUILD_DIR)/$@
%.lss: %.elf
$(OBJDUMP) -h -S $< > $@
%.list: %.elf
$(OBJDUMP) -S $< > $@
%.flash: %.elf
@printf " FLASH\t$<\n"
ifeq (,$(OOCD_FILE))
$(Q)(echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \
$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
-f target/$(OOCD_TARGET).cfg \
-c "program $(realpath $(*).elf) verify reset exit" \
$(NULL)
else
$(Q)(echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \
$(OOCD) -f $(OOCD_FILE) \
-c "program $(realpath $(*).elf) verify reset exit" \
$(NULL)
endif
clean:
rm -rf $(BUILD_DIR) $(GENERATED_BINS)
.PHONY: all clean flash
-include $(OBJS:.o=.d)
When I try to run make -C src/
in the project folder I see this error.
root@3bc5b3869e43:/home# make -C src/
make: Entering directory '/home/src'
CC main.c
CC device_drivers/ddrvDisp.c
CC managers/dispMan.c
CC virtual_devices/vdevDisp.c
GENLNK stm32f103rct6
LD aws.elf
/usr/local/bin/arm_gcc/gcc-arm-none-eabi-10.3-2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: binaries/device_drivers/ddrvDisp.o: in function `initDisplayGPIO':
/home/src/device_drivers/ddrvDisp.c:77: undefined reference to `xTimerCreate'
/usr/local/bin/arm_gcc/gcc-arm-none-eabi-10.3-2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /home/src/device_drivers/ddrvDisp.c:78: undefined reference to `xTimerCreate'
/usr/local/bin/arm_gcc/gcc-arm-none-eabi-10.3-2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /home/src/device_drivers/ddrvDisp.c:79: undefined reference to `xTimerGenericCommandFromTask'
/usr/local/bin/arm_gcc/gcc-arm-none-eabi-10.3-2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /home/src/device_drivers/ddrvDisp.c:80: undefined reference to `xTimerGenericCommandFromTask'
/usr/local/bin/arm_gcc/gcc-arm-none-eabi-10.3-2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: binaries/device_drivers/ddrvDisp.o: in function `setDisplayState':
/home/src/device_drivers/ddrvDisp.c:96: undefined reference to `xTimerGenericCommandFromTask'
/usr/local/bin/arm_gcc/gcc-arm-none-eabi-10.3-2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /home/src/device_drivers/ddrvDisp.c:97: undefined reference to `xTimerGenericCommandFromTask'
/usr/local/bin/arm_gcc/gcc-arm-none-eabi-10.3-2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: /home/src/device_drivers/ddrvDisp.c:98: undefined reference to `xTimerGenericCommandFromTask'
/usr/local/bin/arm_gcc/gcc-arm-none-eabi-10.3-2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: binaries/device_drivers/ddrvDisp.o:/home/src/device_drivers/ddrvDisp.c:99: more undefined references to `xTimerGenericCommandFromTask' follow
collect2: error: ld returned 1 exit status
make: *** [../rules.mk:145: aws.elf] Error 1
make: Leaving directory '/home/src'
root@3bc5b3869e43:/home#
The top of the ddrvDisp.h files contains these includes
#include "stdint.h"
#include "stddef.h"
#include "errorno.h"
#include "apiLibopenCM3.h"
#include "apiFreeRTOS.h"
and the contents of apiFreeRTOS.h are so
#ifndef APIFREERTOS_H
#define APIFREERTOS_H
#ifndef TEST
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#else
#include "stdint.h"
#define pdTRUE 1
#define pdFALSE 0
#define pdMS_TO_TICKS(x) (x)
typedef uint8_t QueueHandle_t;
typedef uint8_t TimerHandle_t;
typedef uint32_t UBaseType_t;
typedef uint32_t BaseType_t;
typedef uint32_t TickType_t;
typedef void (*TimerCallbackFunction_t) (void*);
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
QueueHandle_t xQueueReceive( QueueHandle_t QHandle, void *pvBuffer, TickType_t waitTicks);
QueueHandle_t xQueueSend( QueueHandle_t QHandle, void *pvBuffer, TickType_t waitTicks);
BaseType_t xTimerStart(TimerHandle_t xTimer,TickType_t xTicksToWait);
TimerHandle_t xTimerCreate(const char *const pcTimerName, const TickType_t xTimerPeriodInTicks, const BaseType_t xAutoReload, void *const pvTimerID, TimerCallbackFunction_t pxCallbackFunction);
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xBlockTime );
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, TickType_t xNewPeriod, TickType_t xBlockTime );
#endif
#endif // !APIFREERTOS_H
The apiFreeRTOS.h file is just a shim to allow for mocking during unit testing. if TEST is not defined it simply includes the actual freertos headers. But I digress…
For normal compilation, the apiFreeRTOS includes the appropriate timer header and in the makefile the timers.c file is being includes as a list of source files
CFILES = main.c
CFILES += $(SOURCES_DEVICE_DRIVERS) $(SOURCES_MANAGERS) $(SOURCES_ADAPTERS) $(SOURCES_VIRTUAL_DEVICES)
CFILES += $(FREERTOS_SRC)/portable/GCC/ARM_CM3/port.c $(FREERTOS_SRC)/tasks.c $(FREERTOS_SRC)/list.c $(FREERTOS_SRC)/queue.c $(FREERTOS_SRC)/portable/MemMang/heap_2.c $(FREERTOS_SRC)/timers.c
I m not sure why I m seeing the undefined reference to
error… I was hoping that someone else can see what I m not seeing clearly here and help me fix this issue.
I tried to keep the post length short and skipped over some details that I felt were adding noise. Please do let me know if I need to provide any more information to help you guys help me.
Thanks in advance !