cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4: Purpose of the usage of ATOMIC_SET_BIT ATOMIC_CLEAR_BIT macros in the low level drivers related to UART peripheral

Vladislav Yurov
Associate III

Hello, I'm using LL driver in projects and I found these differences comparing the newest LL driver version (1.7.13) with my current why:

in file stm32f4xx_ll_usart.h/c (macro with prefix ATOMIC_ is now used in several functions)

  • LL_USART_EnableDirectionRx is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_DisableDirectionRx is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_EnableDirectionTx is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_DisableDirectionTx is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_SetTransferDirection is now using ATOMIC_MODIFY_REG macro instead of MODIFY_REG
  • LL_USART_EnableIT_IDLE is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_EnableIT_RXNE is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_EnableIT_TC is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_EnableIT_TXE is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_EnableIT_PE is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_EnableIT_ERROR is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_EnableIT_CTS is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_DisableIT_IDLE is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_DisableIT_RXNE is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_DisableIT_TC is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_DisableIT_TXE is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_DisableIT_PE is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_DisableIT_ERROR is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_DisableIT_CTS is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_EnableDMAReq_RX is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_DisableDMAReq_RX is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT
  • LL_USART_EnableDMAReq_TX is now using ATOMIC_SET_BIT macro instead of SET_BIT
  • LL_USART_DisableDMAReq_TX is now using ATOMIC_CLEAR_BIT macro instead of CLEAR_BIT

So the question is, for what reason the macro with ATOMIC_ prefix is now used? Why only for UART peripheral? What these changes may affect?

36 REPLIES 36
KnarfB
Principal III

> What these changes may affect?

setting a bit or clearing a bit requires two memory accesses on ARM (not talking about bit-banding here): read a word + modify it + write the modified word. Concurrent modifications, e.g. from main and an interrupt handler of the same word may result in unexpected results (race conditions). This is fixed by using the ARM exclusive load/store instructions ldrex and strex, see https://developer.arm.com/documentation/dht0008/a/ch01s02s01.

For the remaining questions, maybe someone from ST can answer.

hth

KnarfB

It doesn't answers to the question, why it was added only for UART peripheral...

He answered at least one of your questions.

As to why these appear only in the UART functions - I can only guess. Maybe there are known issues with interrupts and non-interrupt code possibly changing the UART's CR at the same time, and there are not *known* cases of that in the other modules. Or maybe they (ST) haven't propogated this change elsewhere. Interestingly this doesn't appear in the F7 1.26.2 release. So I would guess this is just starting to propogate through the HAL ecosystem. But again, that is just a guess.

What the changes may affect - looks like the intent is to make applications work as intended with no clobbering/corruption of the UART CRx bits. At least that is what it looks like to me.

Pavel A.
Evangelist III

Strange. Maybe this was introduced for use in multicore systems where M4 is one of cores, such as STM32H7?

The source itself does not offer any hints.

Maybe, but these changes were made for STM32F4xx MCU's, which are single-core. Unfortunately I didn't found any explanation, why such changes implemented now.

From the link above, there is mentioned, that ARMv7-M supports the byte and halfword but not the doubleword variants. In LL drivers the 32-bit (word) variant is used... This is really confusing me now.

In ARM parlance, a word has 32-bit. double word (DWORD) was (is?) used for 32-bit when Windows transitioned from 16 to 32 bit.

My mistake, in the file stm32f4xx.h, macros __STREXW and __LDREXW are used... This postfix misleaded me..

TDK
Guru

Do STREX/LDREX even work on direct peripheral addresses? Documentation from ARM indicates "memory" access.

Certainly the changes would allow code to be thread-safe. It's unclear (to me at least) if these would work correctly on multi-core systems. I would tend to doubt it, as there would need to be a synchronization method between the cores to even allow it.

Edit: STREX/LDREX does work on GPIO->ODR as expected. Tested on a STM32F405.

If you feel a post has answered your question, please click "Accept as Solution".