views:

132

answers:

6

I'm using 32-bit microcontroller (STR91x). I'm concurrently accessing (from ISR and main loop) struct member of type enum. Access is limited to writing to that enum field in the ISR and checking in the main loop. Enum's underlying type is not larger than integer (32-bit). I would like to make sure that I'm not missing anything and I can safely do it.

A: 

Well, it depends entirely on your hardware but I'd be surprised if an ISR could be interrupted by the main thread.

So probably the only thing you have to watch out for is if the main thread could be interrupted halfway through a read (so it may get part of the old value and part of the new).

It should be a simple matter of consulting the specs to ensure that interrupts are only processed between instructions (this is likely since the alternative would be very complex) and that your 32-bit load is a single instruction.

paxdiablo
+2  A: 

Provided that 32 bit reads and writes are atomic, which is almost certainly the case (you might want to make sure that your enum's word-aligned) then that which you've described will be just fine.

David Knell
If I don't have any explicit calls to gcc's "packed" or "aligned", it should be by default word-aligned? Or it's not obvious?
Renee
Essentially everything about alignment is "implementation defined" according to the standard. You will need to inspect your struct layout (gdb will do that for you) to verify that the fields are aligned by default. But they should be. You need to check the appropriate ARM family documentation to find out whether 32-bit reads are atomic, and verify that GCC did access the struct member appropriately. Then if the struct or at least that member is also volatile, you should be able to prove you are safe.
RBerteig
+2  A: 

As paxdiablo & David Knell said, generally speaking this is fine. Even if your bus is < 32 bits, chances are the instruction's multiple bus cycles won't be interrupted, and you'll always read valid data.

What you stated, and what we all know, but it bears repeating, is that this is fine for a single-writer, N-reader situation. If you had more than one writer, all bets are off unless you have a construct to protect the data.

Dan
The bus is 32-bits wide. The aligning issue bothers me a bit, because I'd prefer situation where corrupted read (due to problems with concurrency) is impossible rather than unlikely.
Renee
+2  A: 

If you want to make sure, find the compiler switch that generates an assembly listing and examine the assembly for the write in the ISR and the read in the main loop. Even if you are not familiar with ARM assembly, I'm sure you could quickly and easily be able to discern whether or not the reads and writes are atomic.

semaj
A: 

An aligned 32 bit access will generally be atomic (unless it were a particularly ludicrous compiler!).

However the rock-solid solution (and one generally applicable to non-32 bit targets too) is to simply disable the interrupt temporarily while accessing the data outside of the interrupt. The most robust way to do this is through an access function to statically scoped data rather than making the data global where you then have no single point of access and therefore no way of enforcing an atomic access mechanism when needed.

Clifford
+1  A: 

ARM supports 32-bit aligned reads that are atomic as far as interrupts are concerned. However, make sure your compiler doesn't try to cache the value in a register! Either mark it as a volatile, or use an explicit memory barrier - on GCC this can be done like so:

int tmp = yourvariable;
__sync_synchronize(yourvariable);

Note, however, that current versions of GCC person a full memory barrier for __sync_synchronize, rather than just for the one variable, so volatile is probably better for your needs.

Further, note that your variable will be aligned automatically unless you are doing something Weird (ie, explicitly specifying the location of the struct in memory, or requesting a packed struct). Unaligned variables on ARM cannot be read atomically, so make sure it's aligned, or disable interrupts while reading.

bdonlan