mirror of
				https://github.com/esp8266/Arduino.git
				synced 2025-11-03 14:33:37 +03:00 
			
		
		
		
	Scheduled Interrupt (#4609)
* Scheduled Interrupt * use capital letter for Schedule.h * Prevent memory leak when attach is called multiple times without detach * Add improved schedule_function * WIP : Integrate FunctionalInterrupt & ScheduledInterrupt * Fix travis error
This commit is contained in:
		@@ -1,24 +1,70 @@
 | 
				
			|||||||
#include <FunctionalInterrupt.h>
 | 
					#include <FunctionalInterrupt.h>
 | 
				
			||||||
 | 
					#include <Schedule.h>
 | 
				
			||||||
 | 
					#include "Arduino.h"
 | 
				
			||||||
 | 
					#include <ScheduledFunctions.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Duplicate typedefs from core_esp8266_wiring_digital_c
 | 
					// Duplicate typedefs from core_esp8266_wiring_digital_c
 | 
				
			||||||
typedef void (*voidFuncPtr)(void);
 | 
					typedef void (*voidFuncPtr)(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 ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFunc, void*fp , int mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Structure for communication
 | 
					 | 
				
			||||||
struct ArgStructure {
 | 
					 | 
				
			||||||
	std::function<void(void)> reqFunction;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void interruptFunctional(void* arg)
 | 
					void interruptFunctional(void* arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	((ArgStructure*)arg)->reqFunction();
 | 
					    ArgStructure* localArg = (ArgStructure*)arg;
 | 
				
			||||||
 | 
						if (localArg->functionInfo->reqScheduledFunction)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					      scheduledInterrupts->scheduleFunctionReg(std::bind(localArg->functionInfo->reqScheduledFunction,InterruptInfo(*(localArg->interruptInfo))), false, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (localArg->functionInfo->reqFunction)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  localArg->functionInfo->reqFunction();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C"
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					   void cleanupFunctional(void* arg)
 | 
				
			||||||
 | 
					   {
 | 
				
			||||||
 | 
						 ArgStructure* localArg = (ArgStructure*)arg;
 | 
				
			||||||
 | 
						 delete (FunctionInfo*)localArg->functionInfo;
 | 
				
			||||||
 | 
					     delete (InterruptInfo*)localArg->interruptInfo;
 | 
				
			||||||
 | 
						 delete localArg;
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
 | 
					void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// use the local interrupt routine which takes the ArgStructure as argument
 | 
						// use the local interrupt routine which takes the ArgStructure as argument
 | 
				
			||||||
	__attachInterruptArg (pin, (voidFuncPtr)interruptFunctional, new ArgStructure{intRoutine}, mode);
 | 
					
 | 
				
			||||||
 | 
						InterruptInfo* ii = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FunctionInfo* fi = new FunctionInfo;
 | 
				
			||||||
 | 
						fi->reqFunction = intRoutine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ArgStructure* as = new ArgStructure;
 | 
				
			||||||
 | 
						as->interruptInfo = ii;
 | 
				
			||||||
 | 
						as->functionInfo = fi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__attachInterruptArg (pin, (voidFuncPtr)interruptFunctional, as, mode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!scheduledInterrupts)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							scheduledInterrupts = new ScheduledFunctions(32);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						InterruptInfo* ii = new InterruptInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FunctionInfo* fi = new FunctionInfo;
 | 
				
			||||||
 | 
						fi->reqScheduledFunction = scheduledIntRoutine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ArgStructure* as = new ArgStructure;
 | 
				
			||||||
 | 
						as->interruptInfo = ii;
 | 
				
			||||||
 | 
						as->functionInfo = fi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__attachInterruptArg (pin, (voidFuncPtr)interruptFunctional, as, mode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,12 +4,34 @@
 | 
				
			|||||||
#include <stddef.h>
 | 
					#include <stddef.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <ScheduledFunctions.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#include "c_types.h"
 | 
					#include "c_types.h"
 | 
				
			||||||
#include "ets_sys.h"
 | 
					#include "ets_sys.h"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Structures for communication
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct InterruptInfo {
 | 
				
			||||||
 | 
						uint8_t pin = 0;
 | 
				
			||||||
 | 
						uint8_t value = 0;
 | 
				
			||||||
 | 
						uint32_t micro = 0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FunctionInfo {
 | 
				
			||||||
 | 
					    std::function<void(void)> reqFunction = nullptr;
 | 
				
			||||||
 | 
						std::function<void(InterruptInfo)> reqScheduledFunction = nullptr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ArgStructure {
 | 
				
			||||||
 | 
						InterruptInfo* interruptInfo = nullptr;
 | 
				
			||||||
 | 
						FunctionInfo* functionInfo = nullptr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ScheduledFunctions* scheduledInterrupts;
 | 
				
			||||||
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
 | 
					void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
 | 
				
			||||||
 | 
					void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //INTERRUPTS_H
 | 
					#endif //INTERRUPTS_H
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										117
									
								
								cores/esp8266/ScheduledFunctions.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								cores/esp8266/ScheduledFunctions.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ScheduledFunctions.cpp
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Created on: 27 apr. 2018
 | 
				
			||||||
 | 
					 *      Author: Herman
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include "ScheduledFunctions.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::list<ScheduledFunctions::ScheduledElement> ScheduledFunctions::scheduledFunctions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ScheduledFunctions::ScheduledFunctions()
 | 
				
			||||||
 | 
					:ScheduledFunctions(UINT_MAX)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ScheduledFunctions::ScheduledFunctions(unsigned int reqMax)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						maxElements = reqMax;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ScheduledFunctions::~ScheduledFunctions() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ScheduledRegistration ScheduledFunctions::insertElement(ScheduledElement se, bool front)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (countElements >= maxElements)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							countElements++;
 | 
				
			||||||
 | 
							if (front)
 | 
				
			||||||
 | 
							 {
 | 
				
			||||||
 | 
								scheduledFunctions.push_front(se);
 | 
				
			||||||
 | 
								return scheduledFunctions.begin()->registration;
 | 
				
			||||||
 | 
							 }
 | 
				
			||||||
 | 
							 else
 | 
				
			||||||
 | 
							 {
 | 
				
			||||||
 | 
								 scheduledFunctions.push_back(se);
 | 
				
			||||||
 | 
								 return scheduledFunctions.rbegin()->registration;
 | 
				
			||||||
 | 
							 }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::list<ScheduledFunctions::ScheduledElement>::iterator ScheduledFunctions::eraseElement(std::list<ScheduledFunctions::ScheduledElement>::iterator it)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						countElements--;
 | 
				
			||||||
 | 
						return scheduledFunctions.erase(it);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ScheduledFunctions::scheduleFunction(ScheduledFunction sf, bool continuous, bool front)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (insertElement({this,continuous,nullptr,sf}, front) == nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ScheduledFunctions::scheduleFunction(ScheduledFunction sf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return scheduleFunction(sf, false, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ScheduledRegistration ScheduledFunctions::scheduleFunctionReg (ScheduledFunction sf, bool continuous, bool front)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return insertElement({this,continuous,std::make_shared<int>(1),sf},front);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ScheduledFunctions::runScheduledFunctions()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto lastElement = scheduledFunctions.end(); // do not execute elements added during runScheduledFunctions
 | 
				
			||||||
 | 
						auto it = scheduledFunctions.begin();
 | 
				
			||||||
 | 
						while (it != lastElement)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							bool erase = false;
 | 
				
			||||||
 | 
							if (it->registration == nullptr)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								it->function();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (it->registration.use_count() > 1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									it->function();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									erase = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ((!it->continuous) || (erase))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								it = it->_this->eraseElement(it);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								it++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ScheduledFunctions::removeFunction(ScheduledRegistration sr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto it = scheduledFunctions.begin();
 | 
				
			||||||
 | 
						bool removed = false;
 | 
				
			||||||
 | 
						while ((!removed) && (it != scheduledFunctions.end()))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (it->registration == sr)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								it = eraseElement(it);
 | 
				
			||||||
 | 
								removed = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								it++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										51
									
								
								cores/esp8266/ScheduledFunctions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								cores/esp8266/ScheduledFunctions.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ScheduledFunctions.h
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Created on: 27 apr. 2018
 | 
				
			||||||
 | 
					 *      Author: Herman
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include "Arduino.h"
 | 
				
			||||||
 | 
					#include "Schedule.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <climits>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SCHEDULEDFUNCTIONS_H_
 | 
				
			||||||
 | 
					#define SCHEDULEDFUNCTIONS_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef std::function<void(void)> ScheduledFunction;
 | 
				
			||||||
 | 
					typedef std::shared_ptr<void> ScheduledRegistration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ScheduledFunctions {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						ScheduledFunctions();
 | 
				
			||||||
 | 
						ScheduledFunctions(unsigned int reqMax);
 | 
				
			||||||
 | 
						virtual ~ScheduledFunctions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ScheduledElement
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ScheduledFunctions* _this;
 | 
				
			||||||
 | 
							bool continuous;
 | 
				
			||||||
 | 
							ScheduledRegistration registration;
 | 
				
			||||||
 | 
							ScheduledFunction function;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ScheduledRegistration insertElement(ScheduledElement se, bool front);
 | 
				
			||||||
 | 
						std::list<ScheduledElement>::iterator eraseElement(std::list<ScheduledElement>::iterator);
 | 
				
			||||||
 | 
						bool scheduleFunction(ScheduledFunction sf, bool continuous, bool front);
 | 
				
			||||||
 | 
						bool scheduleFunction(ScheduledFunction sf);
 | 
				
			||||||
 | 
						ScheduledRegistration scheduleFunctionReg (ScheduledFunction sf, bool continuous, bool front);
 | 
				
			||||||
 | 
						static void runScheduledFunctions();
 | 
				
			||||||
 | 
						void removeFunction(ScheduledRegistration sr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static std::list<ScheduledElement> scheduledFunctions;
 | 
				
			||||||
 | 
						unsigned int maxElements;
 | 
				
			||||||
 | 
						unsigned int countElements = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* SCHEDULEDFUNCTIONS_H_ */
 | 
				
			||||||
@@ -112,6 +112,17 @@ typedef struct {
 | 
				
			|||||||
  void * arg;
 | 
					  void * arg;
 | 
				
			||||||
} interrupt_handler_t;
 | 
					} interrupt_handler_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//duplicate from functionalInterrupt.h keep in sync
 | 
				
			||||||
 | 
					typedef struct InterruptInfo {
 | 
				
			||||||
 | 
						uint8_t pin;
 | 
				
			||||||
 | 
						uint8_t value;
 | 
				
			||||||
 | 
						uint32_t micro;
 | 
				
			||||||
 | 
					} InterruptInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						InterruptInfo* interruptInfo;
 | 
				
			||||||
 | 
						void* functionInfo;
 | 
				
			||||||
 | 
					} ArgStructure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static interrupt_handler_t interrupt_handlers[16];
 | 
					static interrupt_handler_t interrupt_handlers[16];
 | 
				
			||||||
static uint32_t interrupt_reg = 0;
 | 
					static uint32_t interrupt_reg = 0;
 | 
				
			||||||
@@ -134,7 +145,14 @@ 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 
 | 
					      uint32_t savedPS = xt_rsil(15); // stop other interrupts
 | 
				
			||||||
 | 
					      ArgStructure* localArg = (ArgStructure*)handler->arg;
 | 
				
			||||||
 | 
					      if (localArg->interruptInfo)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					         localArg->interruptInfo->pin = i;
 | 
				
			||||||
 | 
					         localArg->interruptInfo->value = __digitalRead(i);
 | 
				
			||||||
 | 
					         localArg->interruptInfo->micro = micros();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      if (handler->arg)
 | 
					      if (handler->arg)
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
    	  ((voidFuncPtrArg)handler->fn)(handler->arg);
 | 
					    	  ((voidFuncPtrArg)handler->fn)(handler->arg);
 | 
				
			||||||
@@ -149,12 +167,18 @@ void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
 | 
				
			|||||||
  ETS_GPIO_INTR_ENABLE();
 | 
					  ETS_GPIO_INTR_ENABLE();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void cleanupFunctional(void* arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFunc, void *arg, int mode) {
 | 
					extern void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFunc, void *arg, int mode) {
 | 
				
			||||||
  if(pin < 16) {
 | 
					  if(pin < 16) {
 | 
				
			||||||
    ETS_GPIO_INTR_DISABLE();
 | 
					    ETS_GPIO_INTR_DISABLE();
 | 
				
			||||||
    interrupt_handler_t *handler = &interrupt_handlers[pin];
 | 
					    interrupt_handler_t *handler = &interrupt_handlers[pin];
 | 
				
			||||||
    handler->mode = mode;
 | 
					    handler->mode = mode;
 | 
				
			||||||
    handler->fn = userFunc;
 | 
					    handler->fn = userFunc;
 | 
				
			||||||
 | 
					    if (handler->arg)  // Clean when new attach without detach
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						  cleanupFunctional(handler->arg);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
    handler->arg = 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
 | 
				
			||||||
@@ -179,6 +203,10 @@ extern void ICACHE_RAM_ATTR __detachInterrupt(uint8_t pin) {
 | 
				
			|||||||
    interrupt_handler_t *handler = &interrupt_handlers[pin];
 | 
					    interrupt_handler_t *handler = &interrupt_handlers[pin];
 | 
				
			||||||
    handler->mode = 0;
 | 
					    handler->mode = 0;
 | 
				
			||||||
    handler->fn = 0;
 | 
					    handler->fn = 0;
 | 
				
			||||||
 | 
					    if (handler->arg)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							  cleanupFunctional(handler->arg);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
    handler->arg = 0;
 | 
					    handler->arg = 0;
 | 
				
			||||||
    if (interrupt_reg)
 | 
					    if (interrupt_reg)
 | 
				
			||||||
      ETS_GPIO_INTR_ENABLE();
 | 
					      ETS_GPIO_INTR_ENABLE();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user