Skip to content

Interrupt cleanup #649

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 5, 2015
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Interrupt cleanup
Fixes issue of reentrant calls to nointerrupts()
exposed functional replacements to cli sei and SREG when dealing with
interrupts
InterruptLock class to auto stop and restore interrupt level
Fix user ISR calls to be like Arduino with interrupts disabled fully.
  • Loading branch information
Makuna committed Aug 4, 2015
commit af204f9567f71983c7fe7c3817f2ada212113b5f
49 changes: 41 additions & 8 deletions hardware/esp8266com/esp8266/cores/esp8266/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,50 @@ void timer0_detachInterrupt(void);
void ets_intr_lock();
void ets_intr_unlock();

// level (0-15),
// level 15 will disable ALL interrupts,
// level 0 will disable most software interrupts
#ifndef __STRINGIFY
#define __STRINGIFY(a) #a
#endif

// these low level routines provide a replacement for SREG interrupt save that AVR uses
// but are esp8266 specific. A normal use pattern is like
//
//{
// uint32_t savedPS = xt_rsil(1); // this routine will allow level 2 and above
// // do work here
// xt_wsr_ps(savedPS); // restore the state
//}
//
#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")
// level (0-15), interrupts of the given level and above will be active
// level 15 will disable ALL interrupts,
// level 0 will enable ALL interrupts,
//
#define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)); state;}))
#define xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")

#define interrupts() xt_rsil(0)
#define noInterrupts() xt_rsil(15)

extern uint32_t interruptsState;
// this auto class wraps up xt_rsil so your code can be simplier, but can only be
// used in an ino or cpp files. A normal use pattern is like
//
//{
// {
// InterruptLock(1); // this routine will allow level 2 and above
// // do work within interrupt lock here
// }
// do work outside of interrupt lock here outside its scope
//}
//
#define InterruptLock(intrLevel) \
class _AutoDisableIntr { \
public: \
_AutoDisableIntr() { _savedPS = xt_rsil(intrLevel); } \
~_AutoDisableIntr() { xt_wsr_ps(_savedPS); } \
private: \
uint32_t _savedPS; \
}; \
_AutoDisableIntr _autoDisableIntr

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

#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
Expand Down
12 changes: 11 additions & 1 deletion hardware/esp8266com/esp8266/cores/esp8266/core_esp8266_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ static volatile timercallback timer1_user_cb = NULL;
void timer1_isr_handler(void *para){
if ((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable
T1I = 0;
if (timer1_user_cb) timer1_user_cb();
if (timer1_user_cb) {
// to make ISR compatible to Arduino AVR model where interrupts are disabled
// we disable them before we call the client ISR
uint32_t savedPS = xt_rsil(15); // stop other interrupts
timer1_user_cb();
xt_wsr_ps(savedPS);
}
}

void timer1_isr_init(){
Expand Down Expand Up @@ -72,7 +78,11 @@ static volatile timercallback timer0_user_cb = NULL;

void timer0_isr_handler(void* para){
if (timer0_user_cb) {
// to make ISR compatible to Arduino AVR model where interrupts are disabled
// we disable them before we call the client ISR
uint32_t savedPS = xt_rsil(15); // stop other interrupts
timer0_user_cb();
xt_wsr_ps(savedPS);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ void interrupt_handler(void *arg) {
if (handler->fn &&
(handler->mode == CHANGE ||
(handler->mode & 1) == digitalRead(i))) {
// to make ISR compatible to Arduino AVR model where interrupts are disabled
// we disable them before we call the client ISR
uint32_t savedPS = xt_rsil(15); // stop other interrupts
handler->fn();
xt_wsr_ps(savedPS);
}
}
ETS_GPIO_INTR_ENABLE();
Expand Down Expand Up @@ -152,9 +156,6 @@ extern void __detachInterrupt(uint8_t pin) {
}
}

// stored state for the noInterrupts/interrupts methods
uint32_t interruptsState = 0;

void initPins() {
//Disable UART interrupts
system_set_os_print(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ static uint8_t s_servoCount = 0; // the total number of attached s_se
//------------------------------------------------------------------------------
template <class T> void Servo_Handler(T* timer)
{
noInterrupts();

uint8_t servoIndex;

// clear interrupt
Expand Down Expand Up @@ -101,8 +99,6 @@ template <class T> void Servo_Handler(T* timer)

timer->setEndOfCycle();
}

interrupts();
}

static void initISR(ServoTimerSequence timerId)
Expand Down
4 changes: 2 additions & 2 deletions hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ inline bool ETS_INTR_WITHINISR()
{
uint32_t ps;
__asm__ __volatile__("rsr %0,ps":"=a" (ps));
// PS.EXCM bit check
return ((ps & (1 << 4)) != 0);
// PS.INTLEVEL check
return ((ps & 0x0f) != 0);
}

inline uint32_t ETS_INTR_ENABLED(void)
Expand Down