Stm32 framework with micro_ros_stm32cubemx_utils undefined references to `__sync_synchronize`

I am trying to use the micro_ros_stm32cubemx_utils package with my nucleo-f446re. I have followed the README and watched a youtube video and successfully compiled a basic script, but the video demonstrator uses Eclipse, and I want to use PlatformIO. This may be a question for microROS, but since it seems to work on Eclipse I figured I’d ask here first.

The microROS utils package has the user generate code from STM’s .ioc files, then provides a sample_main.c. I copied the inc/src file content to PlatformIO, built/copied the microros library, and copied the linker file. I did not add any microROS content to my inc/lib/src directories. Builds are successful until I try running the following:

status = rclc_support_init(&support, 0, NULL, &freeRTOS_allocator);

giving me the following error:

micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a(librcutils-atomic_64bits.c.obj): In function `unlock_memory':
atomic_64bits.c:(.text+0xa0): undefined reference to `__sync_synchronize'
micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a(librcutils-atomic_64bits.c.obj): In function `__atomic_load_8':
atomic_64bits.c:(.text+0x11c): undefined reference to `__sync_synchronize'
micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a(librcutils-atomic_64bits.c.obj): In function `__atomic_store_8':
atomic_64bits.c:(.text+0x198): undefined reference to `__sync_synchronize'
micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a(librcutils-atomic_64bits.c.obj): In function `__atomic_exchange_8':
atomic_64bits.c:(.text+0x214): undefined reference to `__sync_synchronize'
micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a(librcutils-atomic_64bits.c.obj): In function `__atomic_fetch_add_8':
atomic_64bits.c:(.text+0x2a8): undefined reference to `__sync_synchronize'

I’ve tried searching for __sync_synchronize in the microROS src files, but it isn’t there. There were quite a few .c files that were compiled into the library generation, but PlatformIO still seems to have trouble finding the references after linking the library in build_flags. Given that, I created a build_src_filter to include them all, but I’m worried I’m making it worse. Perhaps there’s an issue with the framework linking? At a loss on where to go from here. Thank you for the help.

platform.ini

[env:nucleo_f446re]
platform = ststm32
board = nucleo_f446re
; select linker file generated by CubeMX
board_build.ldscript = STM32F446RETx_FLASH.ld
; make build system use our HAL config file
board_build.stm32cube.custom_config_header = yes
framework = stm32cube
; lib_deps = FreeRTOS
build_flags = 
    -mfpu=fpv4-sp-d16
    -mfloat-abi=softfp    
    -fno-builtin
    # Includes
    -I"Middlewares/Third_Party/FreeRTOS/Source/include"
    -I"Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2"
    -I"Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F"
    -I"micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/microros_include"
    -I"micro_ros_stm32cubemx_utils/extra_sources"
    -I"micro_ros_stm32cubemx_utils/extra_sources/microros_transports"
    # Libraries
    -L"micro_ros_stm32cubemx_utils/microros_static_library/libmicroros"
    -l"microros"

build_src_filter = 
    +<*>
    +<../Middlewares/Third_Party/FreeRTOS/Source/*.c>
    +<../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/*.c>
    +<../Middlewares/Third_Party/FreeRTOS/Source/portable/*.c>
    +<../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/*.c>
    +<../Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c>
    +<../micro_ros_stm32cubemx_utils/extra_sources/*.c>
    +<../micro_ros_stm32cubemx_utils/extra_sources/microros_transports/dma_transport.c> # change here for UDP transport
    
lib_archive = no

Project file structure:

.
├
├── include
│   ├── FreeRTOSConfig.h
│   ├── main.h
│   ├── rcl_utils.h
│   ├── README
│   ├── stm32f4xx_hal_conf.h
│   ├── stm32f4xx_it.h
│   └── system_state.h
├── lib
├── micro_ros_stm32cubemx_utils
│   ├── extra_sources
│   │   ├── microros_transports
│   │   │   ├── dma_transport.c
│   │   │   ├── it_transport.c
│   │   │   ├── udp_transport.c
│   │   │   └── usb_cdc_transport.c
│   │   ├── custom_memory_manager.c
│   │   ├── microros_allocators.c
│   │   └── microros_time.c
│   ├── microros_static_library
│   │   ├── libmicroros
│   │   │   ├── microros_include
│   │   │   │   ├── # message type headers...
│   │   │   └── libmicroros.a # compiled 
├── Middlewares
│   └── Third_Party
│       └── FreeRTOS
│           └── Source
│               ├── CMSIS_RTOS_V2
│               │   ├── cmsis_os.h
│               │   ├── cmsis_os2.c
│               │   ├── cmsis_os2.h
│               │   ├── freertos_mpool.h
│               │   └── freertos_os2.h
│               ├── include
│               │   # freeRTOS headers...
│               ├── portable
│               │   ├── GCC
│               │   │   └── ARM_CM4F
│               │   │       ├── port.c
│               │   │       └── portmacro.h
│               │   └── MemMang
│               │       ├── heap_1.c
│               │       ├── heap_2.c
│               │       ├── heap_3.c
│               │       ├── heap_4.c
│               │       └── heap_5.c
│               ├── croutine.c
│               ├── event_groups.c
│               ├── list.c
│               ├── queue.c
│               ├── stream_buffer.c
│               ├── tasks.c
│               └── timers.c
├── src
│   ├── freertos.c
│   ├── main.c
│   ├── rcl_utils.c
│   ├── stm32f4xx_hal_msp.c
│   ├── stm32f4xx_hal_timebase_tim.c
│   ├── stm32f4xx_it.c
│   └── system_stm32f4xx.c
├── .gitignore
├── Makefile
├── nucleo-f446re-microROS-demo.ioc
├── platformio.ini
├── README.md
├── startup_stm32f446xx.s
└── STM32F446RETx_FLASH.ld

Are you sure this file needs to be compiled at all? Your MCU for sure is not 64 bits. __sync_synchronize is a function provided by the compiler for a atomic synchronization barrier. I’d try removing it from the build alltogether or chosing a NUL-implementation.

another issue suggests downgrading the compiler version

see

https://docs.platformio.org/en/latest/projectconf/sections/env/options/platform/platform_packages.html

https://registry.platformio.org/tools/platformio/toolchain-gccarmnoneeabi/versions

Great point, it definitely is 32-bit. I hadn’t seen either of those issues in the utils github yet, thanks for the references. I checked the colcon.meta as suggested by the first issue and I already have -DRCUTILS_NO_64_ATOMIC=ON. I can try downgrading the compiler.

Another thing I noticed, the suggestion in that first link points to the solution in the micro_ros_static_library_ide, whereas I have been using micro_ros_static_library.

Using -mfloat-abi=softfp or -mfloat-abi=hard with microros_static_library gives me an error /home/user/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ld: error: micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a(libbranch_detection_interfaces__rosidl_typesupport_c-vl53l8cx8x8__type_support.cpp.obj) uses VFP register arguments, .pio/build/nucleo_f446re/firmware.elf does not. This is similar to this post here, but I didn’t find their solutions to work.

Using either of these flags with microros_static_library_ide just ends up with the compiler being unable to find <rcl/rcl.h>. Maybe the _ide version expects rcl.h to be sourced elsewhere?

Here’s my toolchain.cmake file for the microros_static_library generation:

SET(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_CROSSCOMPILING 1)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

set(CMAKE_C_COMPILER $ENV{TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN_PREFIX}g++)

SET(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")
SET(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")

set(FLAGS $ENV{RET_CFLAGS} CACHE STRING "" FORCE)
set(MICROROSFLAGS "-DCLOCK_MONOTONIC=0 -D'__attribute__(x)='" CACHE STRING "" FORCE)

set(CMAKE_C_FLAGS_INIT "-std=c11 ${FLAGS} ${MICROROSFLAGS} " CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_INIT "-std=c++14 ${FLAGS} -fno-rtti ${MICROROSFLAGS} " CACHE STRING "" FORCE)

set(__BIG_ENDIAN__ 0)

Can you upload your original project which had the __sync_synchronize error?

Unfortunately I rebuilt the micro_ros_stm32cubemx_utils package and haven’t seen the __sync_synchronize error again. This was after turning DRCUTILS_NO_64_ATOMIC=OFF and then back to DRCUTILS_NO_64_ATOMIC=ON again, as well as building microros_static_library_ide. Now, the only error I’m only seeing is the libmicroros.a uses VFP register arguements, .pio/../.elf does not.

Here’s the repo I’m working on. Cloning and building micro_ros_stm32cubemx_utils is pretty straightforward, if you’re interested in trying. You may need a sample STM32CubeMX project for the flags to work. I built this library in the MX project format, then moved it to PlatformIO.

Edit: In following the previously-referenced video, the author uses a Makefile build rather than the default STM32CubeIDE build. My Makefile knowledge is poor, but surely between this and the startup_stm32f446xx.s and STM32F446RETx_FLASH.ld files, I’m doing something incorrectly…
Edit2: changed the Makefile to build on the PlatformIO project. Still no change in the error generation. The Makefile uses -mfloat-abi=hard but using this in platform.ini generates many VFP errors.