1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-06 05:21:22 +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_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() )

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

@ -8,23 +8,51 @@ extern "C" {
#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))
#define xt_enable_interrupts(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
// 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

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)