Michael wrote:
In both of these cases, "volatile" is insufficient because it does
not
imply "atomic". In the first case, you need an atomic
read-modify-write, and in the second you need an atomic read of a
wide
value. In both cases you can achieve that by enclosing the the
variable
access in a cli-sei pair. For example, the latter case can be fixed
by
changing the routine to something like
main() // or "int main(void)", yada yada
{
uint32_t ms; // does not need to be volatile
do{ cli(); ms = Milliseconds; sei(); } while (ms < SOME_LIMIT);
}
No, you can not. You need the macros in util/atomic.h because cli /
sei
are not memory barriers and accesses to variables done inside a pair
like that can be moved out by the compiler.
Just search the archives for previous discussions and examples...
Could a pair disabling a specific interrupt (rather than global
interrupts) also be susceptible to the compiler re-ordering it outside
the pair?
For instance, in this example I read a structure modified by a timer
ISR:
ETIMSK &= ˜_BV(OCIE3A);
memcpy(&tryconnect,&rtc,sizeof(struct datetime));
ETIMSK |= _BV(OCIE3A);
That will be safe (assuming the memcpy call accesses volatile data, or
uses an external function call). The compiler will keep volatile
accesses in order with each other, but may re-order non-volatile
accesses or instructions around the volatile accesses. The sei() and
cli() macros expand to a single assembly instruction, which does not
involve a volatile memory access - therefore the compiler can re-order
around them. The atomic.h macros include a "__asm__ volatile ("" :::
"memory")" memory barrier, which generates no code but counts as a
volatile memory access, thus forcing an order on the accesses. Your
specific interrupt disable is also a volatile access, so the code should
be safe.
_______________________________________________
AVR-GCC-list mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list