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:
parent
8e09520501
commit
57642c10b6
@ -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() )
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user