Go Down

Topic: noInterupts via "cli() + restore SREG" method (Read 1 time) previous topic - next topic

RIDDICK

hi!

i have a concern about this code (for example in 0012's millis()):
Quote

uint8_t oldSREG = SREG;
// XXX
cli();
SREG = oldSREG;


what if at XXX an interupt happens, that changes SREG?
or is that impossible?

shouldn't we try to atomically manipulate the interrupt enabled bit?
maybe like this:
SREG &= oldSREG | (0xff ^ InteruptEnabledBitMask);

we just want to make sure, that we dont re-enable interrupts early, right?

bye
-Arne

Don Kinzer

#1
Nov 25, 2008, 07:44 pm Last Edit: Nov 25, 2008, 07:46 pm by dkinzer Reason: 1
Quote
what if at XXX an interupt happens, that changes SREG?
Interrupt handlers are not supposed to change SREG bits.  Besides, C/C++ code generally doesn't care about most of the bits in SREG.  If you were writing assembly language code, you could use a macro like the one below to conditionally enable interrupts based on a saved SREG value.
Code: [Select]
.macro restInt _reg=r24
 sbrc \_reg, SREG_I
 sei
.endm

Don

ZBasic Microcontrollers
http://www.zbasic.net

RIDDICK

-Arne

dcb

#3
Nov 26, 2008, 01:22 pm Last Edit: Nov 26, 2008, 01:24 pm by dcb Reason: 1
I looked at the assembly dump of a "large" project and the only sreg reference was from delaymicroseconds (ver 0011).  So that corroborates  what you are saying Don.  

I think the only thing (generally speaking) we care about is the global interrupt flag in SREG, and being able to restore it to its previous value after ensuring interrupts are disabled for a critical operation.

I don't know if the general population needs to prepare for nested interrupts though.  

One other annoyance is the fact that the interrupt handlers use reti by default also complicates things in the reuse department.  If they pushed and popped sreg (you know what I mean :) ), that might be better from a reuse, nesting perspective.


Don Kinzer

Quote
One other annoyance is the fact that the interrupt handlers use reti by default also complicates things in the reuse department.
This is not an issue either.  Consider that in order for an interrupt handler to have executed (by normal means, that is), interrupts must have been enabled.  Consequently, the fact that RETI unconditionally enables interrupts is immaterial.

It might be a problem if your code disables interrupts and then performs a CALL to the ISR's starting address.  This would be an unusual programming technique, though.
Don

ZBasic Microcontrollers
http://www.zbasic.net

dcb

well from a reuse perspective, I cant use an interrupt handler function from "normal" code without poential SEI side effects.  minor annoyance :)

Don Kinzer

#6
Nov 27, 2008, 01:46 am Last Edit: Nov 27, 2008, 02:11 am by dkinzer Reason: 1
Quote
I cant use an interrupt handler function from "normal" code without poential SEI side effects.
True.  However, you could factor out the code into a separate routine that is called from the ISR and otherwise.  Of course, that adds a bit of overhead to the ISR that wouldn't be incurred otherwise.
Don

ZBasic Microcontrollers
http://www.zbasic.net

Go Up