Skip to content

noInterrupts() and interrupts() potential problem #615

Closed
@bbx10

Description

@bbx10

I think there is a problem with disabling/restoring interrupts in some cases. Interrupts may be disabled permanently.

noInterrupts/interrupts saves and restores interrupt state to a global.

#define xt_disable_interrupts(state, level) __asm__ __volatile__("rsil %%0," __STRINGIFY(level) : "=a" (state))
#define xt_enable_interrupts(state)  __asm__ __volatile__("wsr %%0,ps; isync" :: "a" (state) : "memory")

extern uint32_t interruptsState;
#define interrupts() xt_enable_interrupts(interruptsState)
#define noInterrupts() __asm__ __volatile__("rsil %%0,15" : "=a" (interruptsState))

In the following, assuming interrupts are enabled before calling f2(), interrupts will be disabled after returning from f2().

void f1() {
  noInterrupts(); // (2) Save interruptsState (interrupts disabled on entry)
  ...
  interrupts();   // (3) Restore interrupts from interruptsState (disabled)
}

void f2() {
  noInterrupts(); // (1) Save interruptsState and disable interrupts
  ...
  f1();
  ...
  interrupts();   // (4) Restore interrupts from interrupstState (disabled)
}

I am not familiar with ESP8266 ASM so perhaps I am missing something. Or is there a requirement for functions that call noInterrupts to never call another function that calls noInterrupts?

AVR code saves SREG (status register), disables interrupts, then restores SREG. Each function has its own copy of SREG to ensure correct save/restore of the interrupt state.

Assuming interrupts are enabled when f2() is called, interrupts are enabled at the end of f2(), not f1(). This looks correct. ARM code does something similar.

void f1() {
  uint8_t sreg = SREG;
  noInterrupts();     // (2) Save SREG, interrupts disabled before entry
  ...
  SREG = sreg;        // (3) Restore SREG, interrupts still disabled
}

void f2() {
  uint8_t sreg = SREG;
  noInterrupts();       // (1) Save SREG, interrupts were enabled but
                        // now disabled.
  ...
  f1();
  ...
  SREG = sreg;          // (4) Restore SREG, enables interrupts.
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions