Skip to content

Functional interrupt #1728

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ set(CORE_SRCS
cores/esp32/esp32-hal-touch.c
cores/esp32/esp32-hal-uart.c
cores/esp32/Esp.cpp
cores/esp32/FunctionalInterrupt.cpp
cores/esp32/HardwareSerial.cpp
cores/esp32/IPAddress.cpp
cores/esp32/IPv6Address.cpp
Expand Down
44 changes: 44 additions & 0 deletions cores/esp32/FunctionalInterrupt.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
}




20 changes: 20 additions & 0 deletions cores/esp32/FunctionalInterrupt.h
Original file line number Diff line number Diff line change
@@ -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_ */
28 changes: 25 additions & 3 deletions cores/esp32/esp32-hal-gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ typedef void (*voidFuncPtrArg)(void*);
typedef struct {
voidFuncPtr fn;
void* arg;
bool functional;
} InterruptHandle_t;
static InterruptHandle_t __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,};

Expand Down Expand Up @@ -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;

if(!interrupt_initialized) {
interrupt_initialized = true;
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].arg = arg;
__pinInterruptHandlers[pin].functional = functional;

esp_intr_disable(gpio_intr_handle);
if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
GPIO.pin[pin].int_ena = 1;
Expand All @@ -258,15 +269,26 @@ extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * ar
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) {
__attachInterruptArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type);
__attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type, false);
}

extern void __detachInterrupt(uint8_t pin)
{
esp_intr_disable(gpio_intr_handle);
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
{
cleanupFunctional(__pinInterruptHandlers[pin].arg);
}
__pinInterruptHandlers[pin].fn = NULL;
__pinInterruptHandlers[pin].arg = NULL;
__pinInterruptHandlers[pin].arg = false;

GPIO.pin[pin].int_ena = 0;
GPIO.pin[pin].int_type = 0;
esp_intr_enable(gpio_intr_handle);
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}