Pages: [1] 2   Go Down
Author Topic: is a read/write from/to an uint8_t atomic?  (Read 2346 times)
0 Members and 1 Guest are viewing this topic.
Netherlands
Offline Offline
Full Member
***
Karma: 3
Posts: 118
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 634
Posts: 50243
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Netherlands
Offline Offline
Full Member
***
Karma: 3
Posts: 118
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I do enable the interrupts in my function though

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

I only provide help via the forum - please do not contact me for private consultancy.

Netherlands
Offline Offline
Full Member
***
Karma: 3
Posts: 118
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17301
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 54
Posts: 1857
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: February 17, 2013, 02:09:40 pm by MichaelMeissner » Logged

Global Moderator
Online Online
Brattain Member
*****
Karma: 498
Posts: 19060
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Also be cautious of stuff like this:

Code:
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.
Logged


United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

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.

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 70
Posts: 2738
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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
« Last Edit: February 17, 2013, 03:11:26 pm by bperrybap » Logged

Global Moderator
Online Online
Brattain Member
*****
Karma: 498
Posts: 19060
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 70
Posts: 2738
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Netherlands
Offline Offline
Full Member
***
Karma: 3
Posts: 118
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Global Moderator
Online Online
Brattain Member
*****
Karma: 498
Posts: 19060
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Fair enough, but enabling interrupts inside an ISR is a last resort, as far as I am concerned.
Logged


Pages: [1] 2   Go Up
Jump to: