How to build with OpenCM3 + FreeRTOS + CMake to ARM CM4?

I am trying to program an ARM STM32F407 on an STM32F4Discovery board. First, I built a project with OpenCM3 + CMakeLists.txt. It worked! The LED flashed. :wink: Now, I’m trying to make the same project with OpenCM3 + FreeRTOS + CMakeLists.txt. Is not working! :frowning: It is not able to link xTaskCreate and vTaskDelay.

Please can anyone see where I’m going wrong?

Below I show the error messages and my CMakeLists.txt file.

[100%] Linking C executable TesteRTOS.elf
/usr/local/Cellar/arm-none-eabi-gcc/10.3-2021.07/gcc/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/TesteRTOS.dir/src/Teste.c.o: in function `GreenLEDTask':
Teste.c:(.text.GreenLEDTask+0x16): undefined reference to `vTaskDelay'
/usr/local/Cellar/arm-none-eabi-gcc/10.3-2021.07/gcc/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/TesteRTOS.dir/src/Teste.c.o: in function `main':
Teste.c:(.text.main+0x20): undefined reference to `xTaskCreate'
/usr/local/Cellar/arm-none-eabi-gcc/10.3-2021.07/gcc/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: Teste.c:(.text.main+0x24): undefined reference to `vTaskStartScheduler'
collect2: error: ld returned 1 exit status
make[2]: *** [TesteRTOS.elf] Error 1
make[1]: *** [CMakeFiles/TesteRTOS.dir/all] Error 2
make: *** [all] Error 2
cmake_minimum_required(VERSION 3.13)

set(HAVE_FLAG_SEARCH_PATHS_FIRST 0)
set(CMAKE_C_COMPILER_WORKS 1)
set(CMAKE_CXX_COMPILER_WORKS 1)
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

project(TesteRTOS C CXX ASM)

set(PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)

set(MCU_LINKER_SCRIPT ${PROJECT_DIR}/linkerscript.ld)
set(MCU_ROM_ADDRESS 0x08000000)


set(CPU_PARAMETERS
    -mcpu=cortex-m4
    -mthumb
    -mfpu=fpv4-sp-d16
    -mfloat-abi=hard
)
set(OPENCM3_COMPILER_FLAGS -DSTM32F4)
set(OPENCM3_MCU_LIB opencm3_stm32f4)

set(RTOS_PATH ~/Documents/STM32/FreeRTOS-Kernel)
set(RTOS_PORTABLE ARM_CM4F)

enable_language(C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)

# Specify the cross compiler
SET(CMAKE_C_COMPILER /usr/local/bin/arm-none-eabi-gcc)
SET(CMAKE_CXX_COMPILER /usr/local/bin/arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER /usr/local/bin/arm-none-eabi-gcc)
set(CMAKE_AR /usr/local/bin/arm-none-eabi-ar)
SET(CMAKE_OBJCOPY /usr/local/bin/arm-none-eabi-objcopy)
SET(CMAKE_SIZE /usr/local/bin/arm-none-eabi-size)

file(GLOB_RECURSE PROJECT_SOURCES FOLLOW_SYMLINKS
    ${PROJECT_DIR}/*.cpp
    ${PROJECT_DIR}/*.c
)

add_executable(${CMAKE_PROJECT_NAME}
        ${PROJECT_SOURCES}
        )

set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
        SUFFIX ".elf"
        )

target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
    	$ENV{OPENCM3_PATH}/include
    	${PROJECT_DIR}
		${RTOS_PATH}/include
)

FILE(GLOB FreeRTOS_src ${RTOS_PATH}/*.c)

add_library(FreeRTOS STATIC
		${FreeRTOS_src}
		${RTOS_PATH}/portable/GCC/${RTOS_PORTABLE}/port.c
		${RTOS_PATH}/portable/MemMang/heap_4.c
)

target_include_directories(FreeRTOS PUBLIC
		${RTOS_PATH}/include
		${RTOS_PATH}/portable/GCC/${RTOS_PORTABLE}/
		${PROJECT_DIR}
	)

target_compile_options(FreeRTOS PRIVATE
		${CPU_PARAMETERS}
		${OPENCM3_COMPILER_FLAGS}
		-Wall -Wextra -Wundef -Wshadow -Wredundant-decls
		-fno-common -ffunction-sections -fdata-sections -MD
		$<$<CONFIG:Debug>:-Og -g3 -ggdb>
		$<$<CONFIG:Release>:-Og -g0>
		)

target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE
        ${CPU_PARAMETERS}
        ${OPENCM3_COMPILER_FLAGS}
        -Wall -Wextra -Wundef -Wshadow -Wredundant-decls
        -fno-common -ffunction-sections -fdata-sections -MD
        $<$<CONFIG:Debug>:-Og -g3 -ggdb>
        $<$<CONFIG:Release>:-Og -g0>
)

target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
        --static -nostartfiles
        --specs=nosys.specs
        -T${MCU_LINKER_SCRIPT} -L$ENV{OPENCM3_PATH}/lib
        ${CPU_PARAMETERS}
        -ggdb3 -Wl,-Map=${CMAKE_PROJECT_NAME}.map
        -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
        -Wl,--cref -Wl,--gc-sections
)

target_link_libraries(${CMAKE_PROJECT_NAME} ${OPENCM3_MCU_LIB} FreeRTOS)

add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
        COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${CMAKE_PROJECT_NAME}>)

add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
        ${CMAKE_PROJECT_NAME}.hex
        COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
        ${CMAKE_PROJECT_NAME}.bin
        COMMENT "Creating ${PROJECT_NAME}.bin and ${PROJECT_NAME}.hex."
        )

add_custom_target(FLASH
        st-flash --reset write ${PROJECT_NAME}.bin ${MCU_ROM_ADDRESS}
        DEPENDS ${CMAKE_PROJECT_NAME}
        COMMENT "Flashing ${PROJECT_NAME}"
        )

You should put your compiler details that describe your toolchain in a toolchain file, not directly in the project. And definitely don’t set variables like CMAKE_C_COMPILER_WORKS, that’s going to bypass CMake’s various toolchain checks and you’re more or less lying to CMake when you set those (and those variables are not documented for public use anyway).

I recommend you read through CMake’s toolchain manual to understand how to set up a cross-compiling arrangement in the appropriate way.

Hi!

Thanks for your help! I read the article you showed me. I found the problem. I was entering “project(TesteRTOS C CXX ASM)” before setting the variables in my toolchain. Everything is ok now.

Thank you very much!

You can share how you built OpenCM3 + CMakeLists .txt :slightly_smiling_face: :slightly_smiling_face: