cancel
Showing results for 
Search instead for 
Did you mean: 

Is uint16_t and uint32_t interrupt safe in Cortex M architecture?

SSudh.12
Associate

I am working on some embedded stuff and I had multiple interrupts possibly working on same data and so I was wondering if uint16_t and uint32_t data types are interrupt safe.

If interrupt is working a uint16/32_t data and is halfway interrupted by another interrupt that is trying to read this data, it will see corrupted data. Is this a possible scenario?

Thanks

7 REPLIES 7

Aligned 32-bit writes to SRAM are atomic.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

And unaligned 32- and 16-bit writes are not allowed in Cortex-M0/M0+ (they result in faults), and in Cortex-M3/4/7 they are atomic, althought they take longer (write takes 2 or 3 AHB bus cycles but the bus is locked during write, not allowing other master to interrupt).

So, in effect, yes, both uint16 and uint32 data are interrupt safe.

JW

Bob S
Principal

But... if the 2nd interrupt updates the variable, the 1st interrupt routine won't know about it, and if the 1st interrupt also updates the variable, the update from tne 2nd interrupt will be lost. For example:

normal code

ISR #1

read variable (atomic)

ISR #2

read variable (atomic)

do stuff

update variable (atomic)

EXIT ISR #2

update variable (atomic, but overwrites update from ISR #2)

EXIT ISR #1

resume normal code

To prevent this you need to use the "load exclusive/store exclusive/clear exclusive" assembly instructions (or __LDREX(), __STREX() and __CLREX() in "C"). And these can be tricky to use, so read the docs closely (look in the STM32 Cortex Programming Manual for your processor family (M0, M4, etc.).

S.Ma
Principal

This is probably not the real problem. Declare your variable as "volatile" and the compiler will deal with the details.

What you should think more is how you manipulate these data.

If you want to move data around, implement a one way SW FIFO.

Usually, I use a global variable which can be written on one side only, or a flag set by one side and cleared by the other.

Too complex will cause too much debugging time in the end.

Hi KIC8462852 EPIC204278916,

I agree declaring a variable as volatile removes one possible failure mode (that you might not see any change in the variable). But I don't think you are right. I don't think declaring a variable as Volatile is sufficient to ensure correct operation.

Volatile will force the current (possibly only) thread not to store the data in a processor variable but to read it from memory each and every time it wants the value.

But if the variable is so big (or potentially so aligned) that the cpu uses several instructions to read it from memory, it is possible that an interrupt will occur between the first of those reads. And the operation will be done on a "chimera" of the pre-interrupt value and the post-interrupt value.

As Clive wrote, correctly-aligned uint16_t and uint32_t will both be read in a single cycle. But if you put them in a struct that has the packed attribute (i.e. allowing it to be byte-aligned rather than word-aligned), Cortex M0 will have to use several byte accesses to guarantee correct reading whatever the alignment. And then it would not be interrupt-safe, even though it is declared volatile.

Regards,

Danish

T B
Associate II

why not using stdatomic.h ?

Then for example also increment (idx += 1) and bool operators ( x |= a) are interrupt safe.

> But if you put them in a struct that has the packed attribute (i.e. allowing it to be byte-aligned rather than word-aligned), Cortex M0 will have to use several byte accesses to guarantee correct reading whatever the alignment.

Cortex-M0 as a processor does not support unaligned accesses. So, it may be only the compiler which converts such access to a series of aligned accesses of smaller portions. I doubt gcc doing this; OTOH, I know of gcc-compiled Cube failures resulting from unaligned accesses on M0/M0+.

Do you know for sure there *is* any compiler doing this? And, if there is, can't this be suppressed in the given compiler's settings?

JW