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 all commits
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
28 changes: 20 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,29 @@ 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
//
#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")
//{
// uint32_t savedPS = xt_rsil(1); // this routine will allow level 2 and above
// // do work here
// xt_wsr_ps(savedPS); // restore the state
//}
//
// 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")

extern uint32_t interruptsState;
#define interrupts() xt_rsil(0)
#define noInterrupts() xt_rsil(15)

#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
38 changes: 33 additions & 5 deletions hardware/esp8266com/esp8266/cores/esp8266/interrupts.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,51 @@ extern "C" {
#include "ets_sys.h"
}


#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")
// these auto classes wrap up xt_rsil so your code can be simplier, but can only be
// used in an ino or cpp files.

// InterruptLock is used when you want to completely disable locks
//{
// {
// InterruptLock lock;
// // do work within interrupt lock here
// }
// do work outside of interrupt lock here outside its scope
//}
//

class InterruptLock {
public:
InterruptLock() {
xt_disable_interrupts(_state, 15);
_state = xt_rsil(15);
}

~InterruptLock() {
xt_enable_interrupts(_state);
xt_wsr_ps(_state);
}

protected:
uint32_t _state;
};

// AutoInterruptLock is when you need to set a specific level, A normal use pattern is like
//
//{
// {
// AutoInterruptLock(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 AutoInterruptLock(intrLevel) \
class _AutoDisableIntr { \
public: \
_AutoDisableIntr() { _savedPS = xt_rsil(intrLevel); } \
~_AutoDisableIntr() { xt_wsr_ps(_savedPS); } \
private: \
uint32_t _savedPS; \
}; \
_AutoDisableIntr _autoDisableIntr

#endif //INTERRUPTS_H
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