Nick's Interrupts>Critical Sections Question

Under

What if you are not sure interrupts are on or off?

There is a final "gotcha" here. What if interrupts might be off already? Then turning them back on afterwards is a Bad Idea.

In that case you need to save the processor status register like this:

unsigned int getCount ()
  {
  unsigned int c;
  byte oldSREG = SREG;   // remember if interrupts are on or off
 
  noInterrupts ();   // turn interrupts off
  c = count;         // access the shared variable
  SREG = oldSREG;    // turn interrupts back on, if they were off

  return c;          // return copy of shared variable
  }  // end of getCount

This "safe" code saves the current status of interrupts, turns them off (they may already be off), gets the shared variable into a temporary variable, turns interrupts back on if they were off, and then returns the copy of the shared variable.

Ok, I am really trying to understand this, and I don't.

As I read this section text and the code, I can't figure out why the saved SREG would turn the interrupts on if they were off when it was saved? It seems like if the register was saved when they were off, then restored, it would leave them off. What don't I understand? AND, if it is a "BAD IDEA" to turn them back on, why would we?

Maybe I just ran across an error, but it is really confusing me!

BTW Nick...I really like your stuff A LOT! On and off this forum. I just don't get this and I am trying to learn.

Thanks,
-fab

SREG is the "AVR Status Register." Bit 7 of SREG is the "Global Interrupt Enable" bit. When interrupts are enabled, the Global Interrupt Enable bit is set; when they're disabled, the bit is cleared.

Simply turning interrupts off, executing critical code, and then turning interrupts back on will lead to unexpected results if interrupts are already turned off when the critical sequence begins - the code will turn them back on. That's not what you want. You want interrupts to be in the same state when the program exits the the critical sequence they were in before it entered the sequnece.

Saving SREG saves the state of the Global Interrupt Enable bit. Restoring SREG restores the state of the Global Interrupt Enable bit, and puts interrupts back in the state they were in before the critical sequence started.

It seems like if the register was saved when they were off, then restored, it would leave them off.

That's right. If they were off, you want them off now as well.

Plus everything tmd3 said.

Ok, that's what I thought. But the code snipet would do that (leave interrupts off it they were off) right? Even though the text after the code says it turns it back on.

Ok, just a typo.

Thanks Both!
-fab

Ah I see. You spotted a typo. I fixed it. Thanks!

Yeah Nick, it threw me for a loop, that's why I asked. But WOW! THANK YOU for all the information you have on your site. It is really helping me to learn to program and use microcontrollers! Very generous of you to take the time and effort to compile and offer so much great information!

Best Regards,
-fab

You are most welcome. :slight_smile: