cancel
Showing results for 
Search instead for 
Did you mean: 

How to fix linker error with atomic compare_exchange_weak

Chris F
Associate II

I have an atomic variable and want to use compare_exchange_weak on it.

But I'm getting the following linker error when compiling with STM32CubeIDE v1.8.0 (arm-none-eabi 9.3.1:(

arm-none-eabi\bin\ld.exe: ./Core/Src/main.o: in function `std::__atomic_base<unsigned char>::compare_exchange_weak(unsigned char&, unsigned char, std::memory_order, std::memory_order)':
arm-none-eabi\include\c++\9.3.1\bits/atomic_base.h:457: undefined reference to `__atomic_compare_exchange_1'

Here is a minimal example to demonstrate the linker error:

/* main.cpp */
 
#include <cstdint>
#include <cstdio>
#include <atomic>
 
int main() {
	std::atomic<uint8_t> some_atomic_var { 0 };
 
	some_atomic_var.store(3U);                   // atomic store works fine
	printf("%u\n", some_atomic_var.load());   // atomic load works fine
 
	auto val = some_atomic_var.load();
 
	// set second bit
	while (!some_atomic_var.compare_exchange_weak(val, val | (1 << 2U)));  // gives linker error
	printf("%u\n", some_atomic_var.load()); 
 
	return 0;
}

 Update 6.12.2021:

Platform:Windows version of CubeIDE 1.8.0

STM32 target: STM32F030CC

1 ACCEPTED SOLUTION

Accepted Solutions

Internet wisdom says that you should link -latomic in that case, but I cannot find it in the STM32 release.

otoh, Cortex-M0 is so simple. Are you using multi tasking? If so, check the implementation in RIOT OS https://github.com/RIOT-OS/RIOT/blob/master/core/atomic_c11.c for adding the missing function. If not, you could further simplify it.

Did you write that code or is it meant to be super portable, e.g. for multi-core, out-of-order execution CPUs?

hth

KnarfB

View solution in original post

7 REPLIES 7
KnarfB
Principal III

Hmm. It links here without errors:

10:30:16 **** Incremental Build of configuration Debug for project atomic ****
make -j12 all 
arm-none-eabi-g++ "../Core/Src/main.cpp" -mcpu=cortex-m4 -std=gnu++14 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32L432xx -c -I../Core/Inc -I../Drivers/STM32L4xx_HAL_Driver/Inc -I../Drivers/STM32L4xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32L4xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -fno-use-cxa-atexit -Wall -fstack-usage -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -o "Core/Src/main.o"
arm-none-eabi-g++ -o "atomic.elf" @"objects.list"   -mcpu=cortex-m4 -T"STM32_workspace\atomic\STM32L432KCUX_FLASH.ld" --specs=nosys.specs -Wl,-Map="atomic.map" -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group
Finished building target: atomic.elf
 
arm-none-eabi-size   atomic.elf 
arm-none-eabi-objdump -h -S  atomic.elf  > "atomic.list"
arm-none-eabi-objcopy  -O binary  atomic.elf  "atomic.bin"
   text	   data	    bss	    dec	    hex	filename
   5848	    116	   1600	   7564	   1d8c	atomic.elf
Finished building: default.size.stdout
 
Finished building: atomic.bin
Finished building: atomic.list

Thanks a lot for trying it out!

Did you use STM32CubeIDE v1.8.0 (also tried it with 1.7.0) and are you using the Windows version of the CubeIDE?

Yes and yes.

gcc version 9.3.1 20200408 (release) (GNU Tools for STM32 9-2020-q2-update.20201001-1621)

Interestingly, it builds fine when using an STM32L432 as target MCU.

But I get the linker error when trying to build for an STM32F030CC MCU.

A wild guess without having investigated it further:

The Cortex M0 (used in STM32F030) does not have an atomic compare-exchange instruction in its set, unlike the Cortex M4 (used in STM32L432) and the arm-none-eabi toolchain doesn't handle this fact correctly.

Confirmed. F0 uses ARMv6 but L4 ARMv7 instruction set. Maybe some emulation is missing here.

Internet wisdom says that you should link -latomic in that case, but I cannot find it in the STM32 release.

otoh, Cortex-M0 is so simple. Are you using multi tasking? If so, check the implementation in RIOT OS https://github.com/RIOT-OS/RIOT/blob/master/core/atomic_c11.c for adding the missing function. If not, you could further simplify it.

Did you write that code or is it meant to be super portable, e.g. for multi-core, out-of-order execution CPUs?

hth

KnarfB

Thanks a lot for your effort and your input!

I'm writing a multithreaded application based on FreeRTOS and wanted to youse the nice and shiny modern cpp features, but yeah I will protect the critical sections with a mutex instead that is the shorter path 🙂

The only need in terms of portability is, that I'm able to build and run it on a Windows host system so that I'm independent of the hardware for the high level application logic. Which works fine so far. The atomic thing is the first issue I had so far (ok plus some issues with CMSIS-OS).

All the best!

Chris