1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-07 16:23:38 +03:00

Merge pull request #649 from Makuna/interrupts

Interrupt cleanup
This commit is contained in:
Ivan Grokhotkov 2015-08-05 08:04:00 -04:00
commit a0172dd93a
6 changed files with 69 additions and 22 deletions

View File

@ -137,17 +137,29 @@ void timer0_detachInterrupt(void);
void ets_intr_lock(); void ets_intr_lock();
void ets_intr_unlock(); void ets_intr_unlock();
// level (0-15), #ifndef __STRINGIFY
// level 15 will disable ALL interrupts, #define __STRINGIFY(a) #a
// level 0 will disable most software interrupts #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 clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )

View File

@ -32,7 +32,13 @@ static volatile timercallback timer1_user_cb = NULL;
void timer1_isr_handler(void *para){ void timer1_isr_handler(void *para){
if ((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable if ((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable
T1I = 0; 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(){ void timer1_isr_init(){
@ -72,7 +78,11 @@ static volatile timercallback timer0_user_cb = NULL;
void timer0_isr_handler(void* para){ void timer0_isr_handler(void* para){
if (timer0_user_cb) { 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(); timer0_user_cb();
xt_wsr_ps(savedPS);
} }
} }

View File

@ -123,7 +123,11 @@ void interrupt_handler(void *arg) {
if (handler->fn && if (handler->fn &&
(handler->mode == CHANGE || (handler->mode == CHANGE ||
(handler->mode & 1) == digitalRead(i))) { (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(); handler->fn();
xt_wsr_ps(savedPS);
} }
} }
ETS_GPIO_INTR_ENABLE(); ETS_GPIO_INTR_ENABLE();
@ -152,9 +156,6 @@ extern void __detachInterrupt(uint8_t pin) {
} }
} }
// stored state for the noInterrupts/interrupts methods
uint32_t interruptsState = 0;
void initPins() { void initPins() {
//Disable UART interrupts //Disable UART interrupts
system_set_os_print(0); system_set_os_print(0);

View File

@ -8,23 +8,51 @@ extern "C" {
#include "ets_sys.h" #include "ets_sys.h"
} }
// these auto classes wrap up xt_rsil so your code can be simplier, but can only be
// used in an ino or cpp files.
#define xt_disable_interrupts(state, level) __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)) // InterruptLock is used when you want to completely disable locks
#define xt_enable_interrupts(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory") //{
// {
// InterruptLock lock;
// // do work within interrupt lock here
// }
// do work outside of interrupt lock here outside its scope
//}
//
class InterruptLock { class InterruptLock {
public: public:
InterruptLock() { InterruptLock() {
xt_disable_interrupts(_state, 15); _state = xt_rsil(15);
} }
~InterruptLock() { ~InterruptLock() {
xt_enable_interrupts(_state); xt_wsr_ps(_state);
} }
protected: protected:
uint32_t _state; 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 #endif //INTERRUPTS_H

View File

@ -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) template <class T> void Servo_Handler(T* timer)
{ {
noInterrupts();
uint8_t servoIndex; uint8_t servoIndex;
// clear interrupt // clear interrupt
@ -101,8 +99,6 @@ template <class T> void Servo_Handler(T* timer)
timer->setEndOfCycle(); timer->setEndOfCycle();
} }
interrupts();
} }
static void initISR(ServoTimerSequence timerId) static void initISR(ServoTimerSequence timerId)

View File

@ -65,8 +65,8 @@ inline bool ETS_INTR_WITHINISR()
{ {
uint32_t ps; uint32_t ps;
__asm__ __volatile__("rsr %0,ps":"=a" (ps)); __asm__ __volatile__("rsr %0,ps":"=a" (ps));
// PS.EXCM bit check // PS.INTLEVEL check
return ((ps & (1 << 4)) != 0); return ((ps & 0x0f) != 0);
} }
inline uint32_t ETS_INTR_ENABLED(void) inline uint32_t ETS_INTR_ENABLED(void)