noInterupts via "cli() + restore SREG" method

hi!

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

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

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.

.macro restInt _reg=r24
  sbrc \_reg, SREG_I
  sei
.endm

oh - ok...

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 :slight_smile: ), that might be better from a reuse, nesting perspective.

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.

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

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.