mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-25 20:02:37 +03:00
* Properly check for "functional" ISRs and expose C-style attachInterruptArg * Use RAII idiom (cherry picked from commit 15c0b5b356aad0c3032b96ed6db0ec70cbf719d3) # Conflicts: # cores/esp8266/core_esp8266_wiring_digital.cpp * Indentation * Easier reviewability * Refactored after review input. * Finish up insights from review comments.
This commit is contained in:
parent
3f35506684
commit
93a52f923b
@ -218,6 +218,7 @@ uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
|
|||||||
|
|
||||||
void attachInterrupt(uint8_t pin, void (*)(void), int mode);
|
void attachInterrupt(uint8_t pin, void (*)(void), int mode);
|
||||||
void detachInterrupt(uint8_t pin);
|
void detachInterrupt(uint8_t pin);
|
||||||
|
void attachInterruptArg(uint8_t pin, void (*)(void*), void* arg, int mode);
|
||||||
|
|
||||||
void preinit(void);
|
void preinit(void);
|
||||||
void setup(void);
|
void setup(void);
|
||||||
|
@ -7,7 +7,7 @@ typedef void (*voidFuncPtr)(void);
|
|||||||
typedef void (*voidFuncPtrArg)(void*);
|
typedef void (*voidFuncPtrArg)(void*);
|
||||||
|
|
||||||
// Helper functions for Functional interrupt routines
|
// Helper functions for Functional interrupt routines
|
||||||
extern "C" void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFunc, void*fp , int mode);
|
extern "C" void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtr userFunc, void*fp, int mode, bool functional);
|
||||||
|
|
||||||
|
|
||||||
void ICACHE_RAM_ATTR interruptFunctional(void* arg)
|
void ICACHE_RAM_ATTR interruptFunctional(void* arg)
|
||||||
@ -47,7 +47,7 @@ void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode
|
|||||||
as->interruptInfo = ii;
|
as->interruptInfo = ii;
|
||||||
as->functionInfo = fi;
|
as->functionInfo = fi;
|
||||||
|
|
||||||
__attachInterruptArg (pin, (voidFuncPtr)interruptFunctional, as, mode);
|
__attachInterruptFunctionalArg(pin, (voidFuncPtr)interruptFunctional, as, mode, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
|
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
|
||||||
@ -61,5 +61,5 @@ void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> sc
|
|||||||
as->interruptInfo = ii;
|
as->interruptInfo = ii;
|
||||||
as->functionInfo = fi;
|
as->functionInfo = fi;
|
||||||
|
|
||||||
__attachInterruptArg (pin, (voidFuncPtr)interruptFunctional, as, mode);
|
__attachInterruptFunctionalArg(pin, (voidFuncPtr)interruptFunctional, as, mode, true);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
#include "user_interface.h"
|
#include "user_interface.h"
|
||||||
#include "core_esp8266_waveform.h"
|
#include "core_esp8266_waveform.h"
|
||||||
|
#include "interrupts.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
@ -109,8 +110,9 @@ typedef void (*voidFuncPtrArg)(void*);
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
void (*fn)(void);
|
voidFuncPtr fn;
|
||||||
void * arg;
|
void * arg;
|
||||||
|
bool functional;
|
||||||
} interrupt_handler_t;
|
} interrupt_handler_t;
|
||||||
|
|
||||||
//duplicate from functionalInterrupt.h keep in sync
|
//duplicate from functionalInterrupt.h keep in sync
|
||||||
@ -125,11 +127,11 @@ typedef struct {
|
|||||||
void* functionInfo;
|
void* functionInfo;
|
||||||
} ArgStructure;
|
} ArgStructure;
|
||||||
|
|
||||||
static interrupt_handler_t interrupt_handlers[16];
|
static interrupt_handler_t interrupt_handlers[16] = { {0, 0, 0, 0}, };
|
||||||
static uint32_t interrupt_reg = 0;
|
static uint32_t interrupt_reg = 0;
|
||||||
|
|
||||||
void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
|
void ICACHE_RAM_ATTR interrupt_handler(void*)
|
||||||
(void) arg;
|
{
|
||||||
uint32_t status = GPIE;
|
uint32_t status = GPIE;
|
||||||
GPIEC = status;//clear them interrupts
|
GPIEC = status;//clear them interrupts
|
||||||
uint32_t levels = GPI;
|
uint32_t levels = GPI;
|
||||||
@ -146,7 +148,9 @@ void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
|
|||||||
(handler->mode & 1) == !!(levels & (1 << i)))) {
|
(handler->mode & 1) == !!(levels & (1 << i)))) {
|
||||||
// to make ISR compatible to Arduino AVR model where interrupts are disabled
|
// to make ISR compatible to Arduino AVR model where interrupts are disabled
|
||||||
// we disable them before we call the client ISR
|
// we disable them before we call the client ISR
|
||||||
uint32_t savedPS = xt_rsil(15); // stop other interrupts
|
esp8266::InterruptLock irqLock; // stop other interrupts
|
||||||
|
if (handler->functional)
|
||||||
|
{
|
||||||
ArgStructure* localArg = (ArgStructure*)handler->arg;
|
ArgStructure* localArg = (ArgStructure*)handler->arg;
|
||||||
if (localArg && localArg->interruptInfo)
|
if (localArg && localArg->interruptInfo)
|
||||||
{
|
{
|
||||||
@ -154,6 +158,7 @@ void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
|
|||||||
localArg->interruptInfo->value = __digitalRead(i);
|
localArg->interruptInfo->value = __digitalRead(i);
|
||||||
localArg->interruptInfo->micro = micros();
|
localArg->interruptInfo->micro = micros();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (handler->arg)
|
if (handler->arg)
|
||||||
{
|
{
|
||||||
((voidFuncPtrArg)handler->fn)(handler->arg);
|
((voidFuncPtrArg)handler->fn)(handler->arg);
|
||||||
@ -162,7 +167,6 @@ void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
|
|||||||
{
|
{
|
||||||
handler->fn();
|
handler->fn();
|
||||||
}
|
}
|
||||||
xt_wsr_ps(savedPS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ETS_GPIO_INTR_ENABLE();
|
ETS_GPIO_INTR_ENABLE();
|
||||||
@ -170,8 +174,21 @@ void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
|
|||||||
|
|
||||||
extern void cleanupFunctional(void* arg);
|
extern void cleanupFunctional(void* arg);
|
||||||
|
|
||||||
extern void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFunc, void *arg, int mode) {
|
static void set_interrupt_handlers(uint8_t pin, voidFuncPtr userFunc, void* arg, uint8_t mode, bool functional)
|
||||||
|
{
|
||||||
|
interrupt_handler_t* handler = &interrupt_handlers[pin];
|
||||||
|
handler->mode = mode;
|
||||||
|
handler->fn = userFunc;
|
||||||
|
if (handler->functional && handler->arg) // Clean when new attach without detach
|
||||||
|
{
|
||||||
|
cleanupFunctional(handler->arg);
|
||||||
|
}
|
||||||
|
handler->arg = arg;
|
||||||
|
handler->functional = functional;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void* arg, int mode, bool functional)
|
||||||
|
{
|
||||||
// #5780
|
// #5780
|
||||||
// https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map
|
// https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map
|
||||||
if ((uint32_t)userFunc >= 0x40200000)
|
if ((uint32_t)userFunc >= 0x40200000)
|
||||||
@ -183,14 +200,7 @@ extern void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFu
|
|||||||
|
|
||||||
if(pin < 16) {
|
if(pin < 16) {
|
||||||
ETS_GPIO_INTR_DISABLE();
|
ETS_GPIO_INTR_DISABLE();
|
||||||
interrupt_handler_t *handler = &interrupt_handlers[pin];
|
set_interrupt_handlers(pin, (voidFuncPtr)userFunc, arg, mode, functional);
|
||||||
handler->mode = mode;
|
|
||||||
handler->fn = userFunc;
|
|
||||||
if (handler->arg) // Clean when new attach without detach
|
|
||||||
{
|
|
||||||
cleanupFunctional(handler->arg);
|
|
||||||
}
|
|
||||||
handler->arg = arg;
|
|
||||||
interrupt_reg |= (1 << pin);
|
interrupt_reg |= (1 << pin);
|
||||||
GPC(pin) &= ~(0xF << GPCI);//INT mode disabled
|
GPC(pin) &= ~(0xF << GPCI);//INT mode disabled
|
||||||
GPIEC = (1 << pin); //Clear Interrupt for this pin
|
GPIEC = (1 << pin); //Clear Interrupt for this pin
|
||||||
@ -200,31 +210,32 @@ extern void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void ICACHE_RAM_ATTR __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int mode )
|
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void* arg, int mode)
|
||||||
{
|
{
|
||||||
__attachInterruptArg (pin, userFunc, 0, mode);
|
__attachInterruptFunctionalArg(pin, userFunc, arg, mode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void ICACHE_RAM_ATTR __detachInterrupt(uint8_t pin) {
|
extern void ICACHE_RAM_ATTR __detachInterrupt(uint8_t pin) {
|
||||||
if(pin < 16) {
|
if (pin < 16)
|
||||||
|
{
|
||||||
ETS_GPIO_INTR_DISABLE();
|
ETS_GPIO_INTR_DISABLE();
|
||||||
GPC(pin) &= ~(0xF << GPCI);//INT mode disabled
|
GPC(pin) &= ~(0xF << GPCI);//INT mode disabled
|
||||||
GPIEC = (1 << pin); //Clear Interrupt for this pin
|
GPIEC = (1 << pin); //Clear Interrupt for this pin
|
||||||
interrupt_reg &= ~(1 << pin);
|
interrupt_reg &= ~(1 << pin);
|
||||||
interrupt_handler_t *handler = &interrupt_handlers[pin];
|
set_interrupt_handlers(pin, nullptr, nullptr, 0, false);
|
||||||
handler->mode = 0;
|
|
||||||
handler->fn = 0;
|
|
||||||
if (handler->arg)
|
|
||||||
{
|
|
||||||
cleanupFunctional(handler->arg);
|
|
||||||
}
|
|
||||||
handler->arg = 0;
|
|
||||||
if (interrupt_reg)
|
if (interrupt_reg)
|
||||||
|
{
|
||||||
ETS_GPIO_INTR_ENABLE();
|
ETS_GPIO_INTR_ENABLE();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initPins() {
|
extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int mode)
|
||||||
|
{
|
||||||
|
__attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, 0, mode, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void initPins() {
|
||||||
//Disable UART interrupts
|
//Disable UART interrupts
|
||||||
system_set_os_print(0);
|
system_set_os_print(0);
|
||||||
U0IE = 0;
|
U0IE = 0;
|
||||||
@ -243,6 +254,7 @@ extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pi
|
|||||||
extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite")));
|
extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite")));
|
||||||
extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead")));
|
extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead")));
|
||||||
extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt")));
|
extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt")));
|
||||||
|
extern void attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void* arg, int mode) __attribute__((weak, alias("__attachInterruptArg")));
|
||||||
extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt")));
|
extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt")));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user