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
Harvey White
Senior III

I looked a bit at the "thread safe" implementations, which are options in the CubeMX setups. Some of the higher level routines (fprint for instance), need to be surrounded by an RTOS semaphore when using RTOS.

That kind of behavior ought to be a default (it is in some cases) with an RTOS. Not quite sure that it is.

What the current implementation of "atomic" happens to be, I don't know, nor do I know why it was in there.

In an 8 bit processor, accessing a 16 bit I/O address is a two cycle operation, which can possibly be interrupted. With an RTOS (or even an IRQ), you don't want this. Hence ATOMIC inserted as user code. Whether or not a 32 bit processor does the same in successive 16 bit writes (or 8 bit writes) which can happen depending on how external memory is mapped) no idea.

S.Ma
Principal

When a peripheral can be shared with multiple async codes, the smart hardware should provide assist like gpio BSRR, or EXTI channel byte access, or RP2040 4 memory zones for direct, set, reset on registers. Otherwise, atomic penalty comes into play. Now most coders are single core and already interrupt disable comes with implementation dilemma, except in the cortex M0 where only one way exists...

KnarfB
Principal III

Right, smart hardware is always appreciated for SW development, as the additional complexity is then moved into the hardware.

But, SW supporting synchronisation primitives are also inevitable when firmware reaches some complexity (not talking about bit/register level access only).

The overhead of ATOMIC_SET_BIT compared to SET_BIT is 2 instruction cycles (cmp, bne) for the good case (branch/loop not taken).

hth

KnarfB

Nikita91
Lead II

There is a beginning of an answer in the release note of the HAL. But that does not indicate precisely which case is being treated.:

"Handling of UART concurrent register access in case of race condition between Tx and Rx transfers (HAL UART and LL LPUART)"

That makes the most sense. You could be setting up an RX transfer just as a TX interrupt hits and modifies the same registers.

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

To be continued.... Now they've introduced the same in the STM32H7 library, in update 1.10.1 (or 1.9.1)

RTOS task switch actually has same effect as interrupt: a task can be preempted between two instructions. So well, their point is valid. (by the way, when RTOSes do task switch they execute CLREX specially to abort any active ldrex ).

So far the ST answer is that ldrex/strex has been tested on UART registers and appears working TDK confirmed earlier that ldrex/strex works on GPIO BSRR. Well...