|
From: | E. Weddington |
Subject: | Re: [avr-gcc-list] "Volatile" |
Date: | Fri, 15 Apr 2005 15:15:19 -0600 |
User-agent: | Mozilla Thunderbird 1.0.2 (Windows/20050317) |
Keith Gudger wrote:
Those of us on this list all know the "volatile" drill - it's FAQ #1. This is sort of the same issue, and I'm wondering if the code that "got me" is as obvious as the other volatile stuff. I have a volatile variable, "Flags", that is set and cleared in many routines, including an interrupt. Here is the disassembly for the Flags_Clear function: 00000f3e <Flags_Clear>:f3e: 98 2f mov r25, r24 f40: 90 95 com r25f42: 80 91 a4 00 lds r24, 0x00A4 f46: 89 23 and r24, r25 ; <- interrupt here f48: 80 93 a4 00 sts 0x00A4, r24 f4c: 08 95 ret The interrupt occured right before f46, and set the flag. The interrupt pushed and popped r24 & r25's values, so when the interrupt returned to f46, the flags were restored to their *previous* state (the flag unset! Ack! I'm screwed!) Two questions: 1) Is this something I should have learned in Embedded 101? If so, I"ll slink quitely away...
Well it's probably embedded 201....
See theory on "critical sections". Essentially, any operation that you want to have happen "atomically" you place in a critical section. The critical section is a section where nothing should disturb or otherwise interrupt it. So, for the AVR you disable global interrupts before and enable global interrupts after the section. This is really important when you have a single C statement that compiles to multiple assembly instructions. You get the false security of thinking that the operation is atomic because there is only one C statement. In reality, you can get an interrupt in the middle of the operation because the compiler generates multiple assembly instructions. The interrupt finishes, it goes back to your operation with corrupted values.and if not.. 2) How would the experts on this list have prevented this?
HTH Eric
[Prev in Thread] | Current Thread | [Next in Thread] |