Skip to content

Commit a0172dd

Browse files
committed
Merge pull request #649 from Makuna/interrupts
Interrupt cleanup
2 parents a074a0b + a2673f2 commit a0172dd

File tree

6 files changed

+70
-23
lines changed

6 files changed

+70
-23
lines changed

cores/esp8266/Arduino.h

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,17 +137,29 @@ void timer0_detachInterrupt(void);
137137
void ets_intr_lock();
138138
void ets_intr_unlock();
139139

140-
// level (0-15),
141-
// level 15 will disable ALL interrupts,
142-
// level 0 will disable most software interrupts
140+
#ifndef __STRINGIFY
141+
#define __STRINGIFY(a) #a
142+
#endif
143+
144+
// these low level routines provide a replacement for SREG interrupt save that AVR uses
145+
// but are esp8266 specific. A normal use pattern is like
143146
//
144-
#define xt_disable_interrupts(state, level) __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state))
145-
#define xt_enable_interrupts(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
147+
//{
148+
// uint32_t savedPS = xt_rsil(1); // this routine will allow level 2 and above
149+
// // do work here
150+
// xt_wsr_ps(savedPS); // restore the state
151+
//}
152+
//
153+
// level (0-15), interrupts of the given level and above will be active
154+
// level 15 will disable ALL interrupts,
155+
// level 0 will enable ALL interrupts,
156+
//
157+
#define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)); state;}))
158+
#define xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
146159

147-
extern uint32_t interruptsState;
160+
#define interrupts() xt_rsil(0)
161+
#define noInterrupts() xt_rsil(15)
148162

149-
#define interrupts() xt_enable_interrupts(interruptsState)
150-
#define noInterrupts() __asm__ __volatile__("rsil %0,15" : "=a" (interruptsState))
151163

152164
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
153165
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )

cores/esp8266/core_esp8266_timer.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ static volatile timercallback timer1_user_cb = NULL;
3232
void timer1_isr_handler(void *para){
3333
if ((T1C & ((1 << TCAR) | (1 << TCIT))) == 0) TEIE &= ~TEIE1;//edge int disable
3434
T1I = 0;
35-
if (timer1_user_cb) timer1_user_cb();
35+
if (timer1_user_cb) {
36+
// to make ISR compatible to Arduino AVR model where interrupts are disabled
37+
// we disable them before we call the client ISR
38+
uint32_t savedPS = xt_rsil(15); // stop other interrupts
39+
timer1_user_cb();
40+
xt_wsr_ps(savedPS);
41+
}
3642
}
3743

3844
void timer1_isr_init(){
@@ -72,7 +78,11 @@ static volatile timercallback timer0_user_cb = NULL;
7278

7379
void timer0_isr_handler(void* para){
7480
if (timer0_user_cb) {
81+
// to make ISR compatible to Arduino AVR model where interrupts are disabled
82+
// we disable them before we call the client ISR
83+
uint32_t savedPS = xt_rsil(15); // stop other interrupts
7584
timer0_user_cb();
85+
xt_wsr_ps(savedPS);
7686
}
7787
}
7888

cores/esp8266/core_esp8266_wiring_digital.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ void interrupt_handler(void *arg) {
123123
if (handler->fn &&
124124
(handler->mode == CHANGE ||
125125
(handler->mode & 1) == digitalRead(i))) {
126+
// to make ISR compatible to Arduino AVR model where interrupts are disabled
127+
// we disable them before we call the client ISR
128+
uint32_t savedPS = xt_rsil(15); // stop other interrupts
126129
handler->fn();
130+
xt_wsr_ps(savedPS);
127131
}
128132
}
129133
ETS_GPIO_INTR_ENABLE();
@@ -152,9 +156,6 @@ extern void __detachInterrupt(uint8_t pin) {
152156
}
153157
}
154158

155-
// stored state for the noInterrupts/interrupts methods
156-
uint32_t interruptsState = 0;
157-
158159
void initPins() {
159160
//Disable UART interrupts
160161
system_set_os_print(0);

cores/esp8266/interrupts.h

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,51 @@ extern "C" {
88
#include "ets_sys.h"
99
}
1010

11-
12-
#define xt_disable_interrupts(state, level) __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state))
13-
#define xt_enable_interrupts(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
11+
// these auto classes wrap up xt_rsil so your code can be simplier, but can only be
12+
// used in an ino or cpp files.
13+
14+
// InterruptLock is used when you want to completely disable locks
15+
//{
16+
// {
17+
// InterruptLock lock;
18+
// // do work within interrupt lock here
19+
// }
20+
// do work outside of interrupt lock here outside its scope
21+
//}
22+
//
1423

1524
class InterruptLock {
1625
public:
1726
InterruptLock() {
18-
xt_disable_interrupts(_state, 15);
27+
_state = xt_rsil(15);
1928
}
2029

2130
~InterruptLock() {
22-
xt_enable_interrupts(_state);
31+
xt_wsr_ps(_state);
2332
}
2433

2534
protected:
2635
uint32_t _state;
2736
};
2837

38+
// AutoInterruptLock is when you need to set a specific level, A normal use pattern is like
39+
//
40+
//{
41+
// {
42+
// AutoInterruptLock(1); // this routine will allow level 2 and above
43+
// // do work within interrupt lock here
44+
// }
45+
// do work outside of interrupt lock here outside its scope
46+
//}
47+
//
48+
#define AutoInterruptLock(intrLevel) \
49+
class _AutoDisableIntr { \
50+
public: \
51+
_AutoDisableIntr() { _savedPS = xt_rsil(intrLevel); } \
52+
~_AutoDisableIntr() { xt_wsr_ps(_savedPS); } \
53+
private: \
54+
uint32_t _savedPS; \
55+
}; \
56+
_AutoDisableIntr _autoDisableIntr
2957

3058
#endif //INTERRUPTS_H

libraries/Servo/src/esp8266/Servo.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ static uint8_t s_servoCount = 0; // the total number of attached s_se
5959
//------------------------------------------------------------------------------
6060
template <class T> void Servo_Handler(T* timer)
6161
{
62-
noInterrupts();
63-
6462
uint8_t servoIndex;
6563

6664
// clear interrupt
@@ -101,8 +99,6 @@ template <class T> void Servo_Handler(T* timer)
10199

102100
timer->setEndOfCycle();
103101
}
104-
105-
interrupts();
106102
}
107103

108104
static void initISR(ServoTimerSequence timerId)

tools/sdk/include/ets_sys.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ inline bool ETS_INTR_WITHINISR()
6565
{
6666
uint32_t ps;
6767
__asm__ __volatile__("rsr %0,ps":"=a" (ps));
68-
// PS.EXCM bit check
69-
return ((ps & (1 << 4)) != 0);
68+
// PS.INTLEVEL check
69+
return ((ps & 0x0f) != 0);
7070
}
7171

7272
inline uint32_t ETS_INTR_ENABLED(void)

0 commit comments

Comments
 (0)