Functional interrupt (#1728)
* Initial * Implementation * Add to CMakelist.txt * Add example * Add IRAM_ATTR
This commit is contained in:
		
							parent
							
								
									5be3078b76
								
							
						
					
					
						commit
						ea61563c69
					
				| @ -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 | ||||
|  | ||||
							
								
								
									
										44
									
								
								cores/esp32/FunctionalInterrupt.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								cores/esp32/FunctionalInterrupt.cpp
									
									
									
									
									
										Normal 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; | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										20
									
								
								cores/esp32/FunctionalInterrupt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								cores/esp32/FunctionalInterrupt.h
									
									
									
									
									
										Normal 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_ */ | ||||
| @ -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,}; | ||||
| 
 | ||||
| @ -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; | ||||
| @ -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); | ||||
|  | ||||
| @ -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(); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user