Go Down

Topic: is a read/write from/to an uint8_t atomic? (Read 2762 times) previous topic - next topic

JosAH

Greetings,

the title says it all; an interrupt function decodes an IR remote signal and delivers a uint8_t value; the main control flow periodically reads this value and decides what to do; I don't mind reading an older value as long as the value isn't 'corrupted' by my interrupt handler; it can never be corrupt if the reading/writing of this variable is atomic. Is this so?

thanks in advance and kind regards,

Jos

PaulS

A change to a 8 bit variable is atomic. Changes to larger values are not. However, interrupts are disabled during an interrupt service routine, so corruption of a multibyte variable will not occur in the ISR.

The value in a multi-byte variable may change in the middle of a read/write operation outside of the ISR. That needs to protected by disabling interrupts during the read/write and then re-enabling them.

JosAH


A change to a 8 bit variable is atomic. Changes to larger values are not. However, interrupts are disabled during an interrupt service routine, so corruption of a multibyte variable will not occur in the ISR.


Thanks; that's what I wanted to know; I do enable the interrupts in my function though (reading from an IR takes several milli seconds and I want timers etc. to go on). But as long as that single byte is changed atomically, all is fine.

Thanks again for your reply and kind regards,

Jos

PeterH


I do enable the interrupts in my function though


You are enabling interrupts within an interrupt handler? That is a big red flag.
I only provide help via the forum - please do not contact me for private consultancy.

JosAH



I do enable the interrupts in my function though


You are enabling interrupts within an interrupt handler? That is a big red flag.


No it isn't, I know what I'm doing (<--- famous last words ;-) My interrupt function is triggered by a falling edge and then it starts decoding an IR signal from a digital pin; that can takes several milli seconds (I simply poll that pin in the interrupt function) and I want the millis() etc. interrupts to go on. At the start of my function I've detached it from the particular interrupt because I don't want it to be called recursively by another falling edge on that pin. b.t.w. I only enable interrupts after I've detached my function from that falling edge interrupt.

kind regards,

Jos

PeterH


I know what I'm doing


You "know what you're doing" but don't know that eight-bit writes are atomic? This is not very reassuring.
I only provide help via the forum - please do not contact me for private consultancy.

retrolefty



I do enable the interrupts in my function though


You are enabling interrupts within an interrupt handler? That is a big red flag.


Not really a 'red flag', just not recommended by those that don't understand the effect of using nested interrupts. But one certainly can re-enable interrupts within a ISR if required and understand all the effects of doing that.

Lefty


MichaelMeissner

#7
Feb 17, 2013, 08:06 pm Last Edit: Feb 17, 2013, 08:09 pm by MichaelMeissner Reason: 1


I know what I'm doing


You "know what you're doing" but don't know that eight-bit writes are atomic? This is not very reassuring.

I dunno, if the OP has experience on other platforms, he/she may have known what was the atomic types there, but was asking about the AVR in particular.  On the 20-30 different machines I have worked on, it has varied from byte to 16-bit, to 32-bit to 64-bit types that are suitably aligned depending on the underlying memory architecture of the machine.  If you are dealing with systems that have multiple processors accessing the same memory pool, it can get even more complex and you need to line things up on a cache line and use special instructions to get a lock.  Given the AVR is an 8-bit machine, and generates multiple instructions to handle 16 and 32-bit types, 8-bit chars are the right answer, while on the ARM, int is listed as sig_atomic_t.

Nick Gammon

Arithmetic is probably not atomic (eg. foo++);

Also be cautious of stuff like this:

Code: [Select]
if (foo > 100)
  foo = 0;


However a simple read would be OK.

Quote
I want the millis() etc. interrupts to go on.


If the whole things takes multiple milliseconds, can't you decode outside the ISR? Or do it another way? The IRremote library, for example, uses a timer interrupt to check (at a fixed interval) whether the incoming pulse is high or low.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

dc42



You are enabling interrupts within an interrupt handler? That is a big red flag.


No it isn't, I know what I'm doing (<--- famous last words ;-) My interrupt function is triggered by a falling edge and then it starts decoding an IR signal from a digital pin; that can takes several milli seconds (I simply poll that pin in the interrupt function) and I want the millis() etc. interrupts to go on. At the start of my function I've detached it from the particular interrupt because I don't want it to be called recursively by another falling edge on that pin. b.t.w. I only enable interrupts after I've detached my function from that falling edge interrupt.


Instead of polling the IR receiver in the ISR, why don't you leave the interrupt attached, and at each interrupt:

- call micros() to get the current time
- calculate the time since the previous edge, so that you can decode the next bit
- store the time you got from micros(), ready for the next interrupt
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

bperrybap

#10
Feb 17, 2013, 09:08 pm Last Edit: Feb 17, 2013, 09:11 pm by bperrybap Reason: 1

A change to a 8 bit variable is atomic.

A change to an eight bit variable is not necessarily atomic depending on what "change" means.
It will not be atomic if "change" means to modify part of the 8 bit variable
because of the AVR being RISC


For example, on some processors, operations like:

Code: [Select]
foo |= mask;
foo &= ~mask;


can be atomic because they compile down to a non interruptible instruction.
On the AVR these operations are not atomic because they compile down to multiple
instructions which can be interrupted.

When using an 8 bit variable on the AVR, a read is atomic and a write is atomic
an update/change to an 8 bit variable that involves reading/modifying/writing back the variable
to preserve a portion of it's previous contents is not atomic.

However, there are some specific AVR bit set/clear instructions that can be used on certain hardware
registers that can provide atomicity of setting or clearing an individual bit (not multiple bits).

--- bill

Nick Gammon

I agree with Bill. Setting/clearing one bit (where the bit is known at compile time) the compiler usually generates a single atomic instruction. However doing multiple bits, or arithmetic, is unlikely to be atomic.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

bperrybap


I agree with Bill. Setting/clearing one bit (where the bit is known at compile time) the compiler usually generates a single atomic instruction. However doing multiple bits, or arithmetic, is unlikely to be atomic.


Also, even if it is a single bit and the bit is known at compile time, SBI/CBI instructions can only be done
on an i/o registers vs a ram based 8 bit variable.

JosAH



I know what I'm doing


You "know what you're doing" but don't know that eight-bit writes are atomic? This is not very reassuring.


I don't know much about the Atmega internal memory model, that's why I asked here; if it had an internal four bit bus so that nibbles were written and read the read/writes could've been non-atomic; but they are so I'm happy again ;-)

kind regards,

Jos

Nick Gammon

Fair enough, but enabling interrupts inside an ISR is a last resort, as far as I am concerned.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up