32F417 / ARM32: which variables are atomic? - Page 1
Forum section: electronics / general

author: peter-h
author_rank: Super Contributor
timestamp: March 27, 2023, 02:48:58 pm
content: Fairly obviously it must beboolean (which GCC implements as an int, I think)8 bit ints16 bit ints32 bit intsNOT 64 bit variables (these will be accessed as at leasttwogoes).What about single floats?The more tricky case is that the 32F4 supportsunalignedvariables, transparently. AFAIK GCC does not assume this and aligns them. I don't usepackedstructs, but somebody working on this project one day might. I am 99% sure that an unaligned 32 bit variable access willnotallow interrupts (therefore RTOS switching) in between the two hardware accesses, but is this right? I would expect DMA can jump in though!

author: abyrvalg
author_rank: Frequent Contributor
timestamp: March 27, 2023, 03:10:52 pm
content: Technically, LDRD/STRD can access 64 bits uninterrupted, but there is no way (except asm of course) to force the compiler to use it.

author: peter-h
author_rank: Super Contributor
timestamp: March 28, 2023, 07:31:14 pm
content: I am surprised that all my guesses in post #1 were correctOn a slightly different tack, could one achieve an atomic write of say 20 bytes with memory-memory DMA?

author: gf
author_rank: Super Contributor
timestamp: March 28, 2023, 08:33:52 pm
content: Quote from: peter-h on March 27, 2023, 02:48:58 pmDoesn't option-munaligned-accessenable that?

author: peter-h
author_rank: Super Contributor
timestamp: March 30, 2023, 03:48:27 pm
content: How would that change whether a memory access is atomic or not, on a CPU whichsupportsunaligned access.On a slightly different tack, could one achieve an atomic write of say 20 bytes with memory-memory DMA?

author: wek
author_rank: Frequent Contributor
timestamp: March 30, 2023, 04:12:46 pm
content: QuoteDefine, very precisely, atomic.JW

author: peter-h
author_rank: Super Contributor
timestamp: March 30, 2023, 04:49:51 pm
content: Atomic from interrupts (which implicitly includes RTOS task switching, which uses SysTick).Does't have to be atomic from DMA (which I know historically, old days, could optionally use what they used to call cycle stealing).My question re DMA was in the opposite direction: can a 32F4 perform a DMA write or read, n words, which is atomic from interrupts? I have used DMAs which could do this.

author: wek
author_rank: Frequent Contributor
timestamp: March 30, 2023, 05:16:49 pm
content: No. And it wouldn't be atomic "from DMA" either, as individual streams are arbitrated round-robin, and even if you'd employ higher priority, the peripheral/memory sides alternate and have individual arbitration... this wold need to be drawn as timing diagram for detailed discussion.What *would* be atomic - regarding both interrupts and DMA - would be a 4-beat burst, i.e. max. 16 bytes (appropriately aligned), seeSingle and burst transferssubchapter of DMA chapter in RM0090 - bursts are unsplittable at the bus transfer level.JW

author: peter-h
author_rank: Super Contributor
timestamp: March 30, 2023, 06:36:50 pm
content: Well, that's good as it provides a means of atomically writing two double float, by copying them from elsewhere in RAM, and same for reading. That's useful and easy to do.

author: wek
author_rank: Frequent Contributor
timestamp: March 30, 2023, 07:19:29 pm
content: Quote from: peter-h on March 30, 2023, 06:36:50 pmYou may find that setting up the DMA and then waiting until it finished is not worth the hassle, and conventional disable-store-enable may be simpler, smaller and faster too.JW

author: peter-h
author_rank: Super Contributor
timestamp: March 31, 2023, 07:08:12 am
content: Yes of course; this is for unusual situations where interrupts must not be disabled for some reason.

author: bson
author_rank: Unknown
timestamp: April 05, 2023, 05:08:14 pm
content: Quote from: peter-h on March 30, 2023, 03:48:27 pmDepends on the DMA controller(s). Remember that some peripherals, like ethernet and USB often have their own DMA controllers. If the DMA controller you use for the m2m transfer can be set to the highest priority and you disable interrupts during the transfer, then the m2m transfer should be atomic. If you can't verify that it excludes the peripheral DMA controllers, then you can always stop those during the transfer if they can possibly ever overlap with your source/dest data.stm/ldm aren't atomic in that I'm fairly certain that DMA transfers can interleave with them. If interrupted they're restarted on return so in that sense they're atomic (last to finish wins), but from a system perspective they're not. Unaligned transfer I'd assume can be interleaved with DMA as well.

author: peter-h
author_rank: Super Contributor
timestamp: April 05, 2023, 07:19:07 pm
content: QuoteThatwould surprise me.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: April 06, 2023, 08:41:50 am
content: Why rely on atrickin the first place? Your project is RTOS-based IIRC, use it’s synchronization primitives instead of working around it. Tricks were the only option in 8-bit era, but nowadays most of thecommonproblems havecommonsolutions and looking for a trick on every occasion is a sign of something done wrong on upper design levels.

author: peter-h
author_rank: Super Contributor
timestamp: April 06, 2023, 09:04:24 am
content: Don't worry - I am not using any tricksI am just interested to know how this works.I use FreeRTOS mutexes etc extensively.But there are times when a boolean flag is just fine - or should be. What if one isn't using an RTOS and needs to flag "main loop" versus an ISR?Out of interest - is there a "test and set" instruction accessible from GCC C ? I used that extensively in the past. Far more efficient than a mutex (looking at FreeRTOS code).

author: gf
author_rank: Super Contributor
timestamp: April 06, 2023, 09:21:06 am
content: https://en.cppreference.com/w/c/atomic/atomic_flag_test_and_set(C11)

author: peter-h
author_rank: Super Contributor
timestamp: April 06, 2023, 10:12:19 am
content: Is that for C, not just C++?Interesting that you specify a "memory order" there.

author: Jeroen3
author_rank: Super Contributor
timestamp: April 06, 2023, 12:15:05 pm
content: Architecture reference manual says all <= 32 bit operands are atomic.Plus:Quote

author: gf
author_rank: Super Contributor
timestamp: April 06, 2023, 12:48:50 pm
content: Quote from: peter-h on April 06, 2023, 10:12:19 amYes, the link is for C.The corresponding functionality for C++ is std::atomic (https://en.cppreference.com/w/cpp/atomic/atomic)

author: peter-h
author_rank: Super Contributor
timestamp: April 06, 2023, 01:12:28 pm
content: QuoteJust as well then that accesses to the peripherals can't generate an exceptionThat memory ordering stuff is pretty complicated. I might have expected to see something like __DSB in there.

author: newbrain
author_rank: Super Contributor
timestamp: April 06, 2023, 02:59:45 pm
content: Quote from: Jeroen3 on April 06, 2023, 12:15:05 pmSingle-copy atomic access is guaranteed only for:Quote from: reference from Jeroen3 postSo I would qualify the ≤ 32 bit with "aligned", at least according to the reference.Quote from: peter-h on April 06, 2023, 09:04:24 amI beg to differ, but that's an old topic (busy loops in FreeRTOS tasks).

author: peter-h
author_rank: Super Contributor
timestamp: April 06, 2023, 07:28:05 pm
content: So unaligned 16 or 32 bit accesses are not atomic between say two RTOS tasks (i.e. not thread-safe).I am not doing loops inside RTOS tasks. That would just totally waste 1ms+ of the CPU time. I yield to the RTOS with say osDelay(100) if there is nothing to do. This surely is 100% fine "co-operative multitasking". It works extremely well, when I wrote all the tasks, and less well when I didn't (MbedTLS grabs the CPU for 3 seconds solid, so the only chance of another task running at all is if its priority is higher - or same or higher in my RTOS config).

author: thinkfat
author_rank: Unknown
timestamp: April 07, 2023, 12:29:13 pm
content: That depends very much on the definition of "atomic". If it's just about loading or storing a memory location uninterruptible, then any aligned access to <= 32bit data types will be fine.However:ARM as a load-store architecture doesn't have any atomically modifiable data types. ARM deemed this problematic enough to later introduce an "exclusive monitor" and the "LDREX/STREX" instructions. Prior to that the only way to implement "atomic" r/m/w was using SWP{B}. But both require implementing a protocol and asserting that all involved parties stick to it.LDREX/STREX only work on cached memory and the behavior if used on uncached memory is UNDEFINED, and some Cortex-A cores are known to just lock up hard, which is a real problem because LDREX/STREX are not privileged.

author: gf
author_rank: Super Contributor
timestamp: April 07, 2023, 02:58:06 pm
content: @peter-h, btw, in C it's unsafe anyway to assume that accessing any regular variable would be atomic. If may happen by chance, but the language specification does not guarantee that at all.Atomicity is only guaranteed for objects of _Atomic datatypes. Even large objects can be _Atomic, but not all _Atomic datatypes are necesssarily lock-free, and large atomic objects usually aren't. Non-lock-free _Atomic data types are still thread-safe (i.e. atomic wrt. different threads), but it is not safe to access them from a signal/interrupt handler. Only lock-free _Atomic objects can be safely accessed from a signal handler as well. See alsohttps://en.cppreference.com/w/c/language/atomicARM GCC obviously emits LDREXD, STREXD, DMB,... for particular operations on particular lock-free _Atomic data types.Arbitrary example:https://godbolt.org/z/YeMKevd7x

author: gf
author_rank: Super Contributor
timestamp: April 07, 2023, 05:13:49 pm
content: Quote from: gf on April 07, 2023, 02:58:06 pmI had missed that you are using a cortex-m4. For this processor, GCC does not generate inline code, but a call to e.g. __atomic_store_8() for "_Atomic long long" datatype. So it seems that 8 byte atomic operations are no longer lock-free in the code generated for this CPU.https://godbolt.org/z/TobaeYeoK

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 07, 2023, 08:25:37 pm
content: I would also suggest using stdatomic if your compiler supports C11 (which I'm sure it does.)