ATOMIC_SET_BIT() stopping code execution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-05-21 7:43 AM
A similar problem to this post but not quite the same:
I've got my own low-level LPUART transmission code, it works like this:
1) Initialize LPUART in FIFO mode with thresholds at 1/2 full
2) When a buffer needs to be sent, write bytes to TDR until all bytes sent or transmit FIFO is full
3) If transmit FIFO is full, enable USART_CR3_TXFTIE and let the ISR handle the rest.
4) When the ISR has written all the bytes to the FIFO, it disables USART_CR3_TXFTIE
What I see is this:
1) Send first packet. It's 10 bytes long, the first byte gets moved immediately to the TX shift register and 8 bytes fill up the FIFO so there's 1 byte left. The interrupt is enabled, the ISR fires, the last byte is written to the FIFO, the interrupt is disabled.
2) Send second packet. It's 7 bytes long so fits completely in the FIFO and the interrupt is left disabled
3) Send third packet. It's 71 bytes long, the first byte gets moved immediately to the TX shift register and 8 bytes fill up the FIFO so there are 62 bytes left. It calls
ATOMIC_SET_BIT(pUART->CR3, USART_CR3_TXFTIE)
to enable the interrupt, and the interrupt never comes. I finally noticed that when I hit the "Suspend" button in the debugger, it shows that the current code location is that call to ATOMIC_SET_BIT() so that call never completed.
If I replace that call with a simple
pUART->CR3 |= USART_CR3_TXFTIE;
everything works as it should.
In the post I linked at the top, the problem was that he had interrupts every few microseconds, I am running the ADC at top speed (in the ADC1_2_IRQHandler I'm reading the value and then immediately setting ADC_CR_ADSTART) so it's possible I also have that many interrupts (I haven't dug into it deeply enough to determine the exact timing) but the solution given for the previous post was "if an interrupt is called between these, the STREX fails and it has to go do the LDREX again" and that leaves some lingering questions.
1) I've got my ADC running the whole time, so why does ATOMIC_SET_BIT() work the first time through? Shouldn't this problem affect every call to ATOMIC_SET_BIT(), not just some?
2) Let's say my situation is similar to the previous post and the CPU is spending 66% of its time servicing the ADC interrupt. From the time the code calls ATOMIC_SET_BIT() until I press the "Suspend" button in the debugger is several seconds, which means the CPU has had literally millions of chances to do LDREX/STREX. It doesn't seem plausible that every single one of those LDREX/STREX pairs fails.
3) Is there any benefit, in this situation, to calling ATOMIC_SET_BIT() instead of just setting the bit directly? I'm assuming the reason to call ATOMIC_SET_BIT() is to prevent other processes from jumping in and modifying CR3 between my code loading it, modifying it, and storing it back, but in this case nobody else should be touching CR3.
Solved! Go to Solution.
- Labels:
-
Interrupt
-
LPUART
-
STM32G4 Series
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-05-21 10:51 AM - edited ‎2025-05-21 10:53 AM
FWIW, I think your problem is exactly the same as the linked thread.
If the chip is executing code but is stuck on ATOMIC_SET_BIT, there are only two possibilities:
- LDREX/STREX fails to complete due to interrupt storm.
- LDREX/STREX fail to even get ran due to interrupt storm.
This is further reinforced by the code succeeding when you replace it with a simple bit set. So actually only the first case is a possibility.
There are explanations for (1) and (2). I don't see those ruling out the above cases.
For (3) above, the benefit to ATOMIC_SET_BIT is only when CR3 is being modified by multiple threads. For UART, this can happen if TX and RX are handled separately.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-05-21 8:37 AM
Hello @cbcooper
Please refer to the post below:
Solved: ATOMIC_SET_BIT() stopping code execution - STMicroelectronics Community
Saket_Om
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-05-21 10:51 AM - edited ‎2025-05-21 10:53 AM
FWIW, I think your problem is exactly the same as the linked thread.
If the chip is executing code but is stuck on ATOMIC_SET_BIT, there are only two possibilities:
- LDREX/STREX fails to complete due to interrupt storm.
- LDREX/STREX fail to even get ran due to interrupt storm.
This is further reinforced by the code succeeding when you replace it with a simple bit set. So actually only the first case is a possibility.
There are explanations for (1) and (2). I don't see those ruling out the above cases.
For (3) above, the benefit to ATOMIC_SET_BIT is only when CR3 is being modified by multiple threads. For UART, this can happen if TX and RX are handled separately.
