Functional interrupt (#1728)

* Initial

* Implementation

* Add to CMakelist.txt

* Add example

* Add IRAM_ATTR
This commit is contained in:
hreintke 2018-09-17 23:13:58 +02:00 committed by Me No Dev
parent 5be3078b76
commit ea61563c69
6 changed files with 137 additions and 3 deletions

View File

@ -17,6 +17,7 @@ set(CORE_SRCS
cores/esp32/esp32-hal-touch.c cores/esp32/esp32-hal-touch.c
cores/esp32/esp32-hal-uart.c cores/esp32/esp32-hal-uart.c
cores/esp32/Esp.cpp cores/esp32/Esp.cpp
cores/esp32/FunctionalInterrupt.cpp
cores/esp32/HardwareSerial.cpp cores/esp32/HardwareSerial.cpp
cores/esp32/IPAddress.cpp cores/esp32/IPAddress.cpp
cores/esp32/IPv6Address.cpp cores/esp32/IPv6Address.cpp

View File

@ -0,0 +1,44 @@
/*
* FunctionalInterrupt.cpp
*
* Created on: 8 jul. 2018
* Author: Herman
*/
#include "FunctionalInterrupt.h"
#include "Arduino.h"
typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrArg)(void*);
extern "C"
{
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional);
}
void IRAM_ATTR interruptFunctional(void* arg)
{
InterruptArgStructure* localArg = (InterruptArgStructure*)arg;
if (localArg->interruptFunction)
{
localArg->interruptFunction();
}
}
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
{
// use the local interrupt routine which takes the ArgStructure as argument
__attachInterruptFunctionalArg (pin, (voidFuncPtrArg)interruptFunctional, new InterruptArgStructure{intRoutine}, mode, true);
}
extern "C"
{
void cleanupFunctional(void* arg)
{
delete (InterruptArgStructure*)arg;
}
}

View File

@ -0,0 +1,20 @@
/*
* FunctionalInterrupt.h
*
* Created on: 8 jul. 2018
* Author: Herman
*/
#ifndef CORE_CORE_FUNCTIONALINTERRUPT_H_
#define CORE_CORE_FUNCTIONALINTERRUPT_H_
#include <functional>
struct InterruptArgStructure {
std::function<void(void)> interruptFunction;
};
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
#endif /* CORE_CORE_FUNCTIONALINTERRUPT_H_ */

View File

@ -74,6 +74,7 @@ typedef void (*voidFuncPtrArg)(void*);
typedef struct { typedef struct {
voidFuncPtr fn; voidFuncPtr fn;
void* arg; void* arg;
bool functional;
} InterruptHandle_t; } InterruptHandle_t;
static InterruptHandle_t __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,}; static InterruptHandle_t __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,};
@ -238,16 +239,26 @@ static void IRAM_ATTR __onPinInterrupt()
} }
} }
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type) extern void cleanupFunctional(void* arg);
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional)
{ {
static bool interrupt_initialized = false; static bool interrupt_initialized = false;
if(!interrupt_initialized) { if(!interrupt_initialized) {
interrupt_initialized = true; interrupt_initialized = true;
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __onPinInterrupt, NULL, &gpio_intr_handle); esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __onPinInterrupt, NULL, &gpio_intr_handle);
} }
// if new attach without detach remove old info
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
{
cleanupFunctional(__pinInterruptHandlers[pin].arg);
}
__pinInterruptHandlers[pin].fn = (voidFuncPtr)userFunc; __pinInterruptHandlers[pin].fn = (voidFuncPtr)userFunc;
__pinInterruptHandlers[pin].arg = arg; __pinInterruptHandlers[pin].arg = arg;
__pinInterruptHandlers[pin].functional = functional;
esp_intr_disable(gpio_intr_handle); esp_intr_disable(gpio_intr_handle);
if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
GPIO.pin[pin].int_ena = 1; GPIO.pin[pin].int_ena = 1;
@ -258,15 +269,26 @@ extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * ar
esp_intr_enable(gpio_intr_handle); esp_intr_enable(gpio_intr_handle);
} }
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type)
{
__attachInterruptFunctionalArg(pin, userFunc, arg, intr_type, false);
}
extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type) { extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type) {
__attachInterruptArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type); __attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type, false);
} }
extern void __detachInterrupt(uint8_t pin) extern void __detachInterrupt(uint8_t pin)
{ {
esp_intr_disable(gpio_intr_handle); esp_intr_disable(gpio_intr_handle);
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
{
cleanupFunctional(__pinInterruptHandlers[pin].arg);
}
__pinInterruptHandlers[pin].fn = NULL; __pinInterruptHandlers[pin].fn = NULL;
__pinInterruptHandlers[pin].arg = NULL; __pinInterruptHandlers[pin].arg = NULL;
__pinInterruptHandlers[pin].arg = false;
GPIO.pin[pin].int_ena = 0; GPIO.pin[pin].int_ena = 0;
GPIO.pin[pin].int_type = 0; GPIO.pin[pin].int_type = 0;
esp_intr_enable(gpio_intr_handle); esp_intr_enable(gpio_intr_handle);

View File

@ -0,0 +1,47 @@
#include <Arduino.h>
#include <FunctionalInterrupt.h>
#define BUTTON1 16
#define BUTTON2 17
class Button
{
public:
Button(uint8_t reqPin) : PIN(reqPin){
pinMode(PIN, INPUT_PULLUP);
attachInterrupt(PIN, std::bind(&Button::isr,this), FALLING);
};
~Button() {
detachInterrupt(PIN);
}
void IRAM_ATTR isr() {
numberKeyPresses += 1;
pressed = true;
}
void checkPressed() {
if (pressed) {
Serial.printf("Button on pin %u has been pressed %u times\n", PIN, numberKeyPresses);
pressed = false;
}
}
private:
const uint8_t PIN;
volatile uint32_t numberKeyPresses;
volatile bool pressed;
};
Button button1(BUTTON1);
Button button2(BUTTON2);
void setup() {
Serial.begin(115200);
}
void loop() {
button1.checkPressed();
button2.checkPressed();
}