1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

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.
This commit is contained in:
Makuna 2015-08-03 19:35:17 -07:00
parent 8e09520501
commit 57642c10b6
5 changed files with 58 additions and 18 deletions

View File

@ -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
//
#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)
// 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() )

View File

@ -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(){
@ -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);
}
}

View File

@ -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();
@ -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);

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

View File

@ -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)