From 55f4744e543821300e20d436d68d7e0ee940f589 Mon Sep 17 00:00:00 2001 From: Chris Pepper Date: Wed, 4 Jul 2018 23:51:45 +0100 Subject: [PATCH] [LPC176x] Endstop Interrupts Feature (#11202) Enable the endstop interrupts feature for LPC176x boards. Although Smoothieboard chose to use non-interrupt capable pins for their endstops, and this has been copied by clones, so they can't use it. --- Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp | 105 +++++++----------- .../src/HAL/HAL_LPC1768/endstop_interrupts.h | 32 +++++- .../src/HAL/HAL_LPC1768/include/pinmapping.h | 3 +- 3 files changed, 69 insertions(+), 71 deletions(-) diff --git a/Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp b/Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp index 3bedb71e91..a92a61a8fd 100644 --- a/Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp +++ b/Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp @@ -19,29 +19,20 @@ #ifdef TARGET_LPC1768 #include "../../inc/MarlinConfig.h" -#include -#include -//#include "HAL_timers.h" -#include "fastio.h" #define GNUM 31 typedef void (*interruptCB)(void); -static interruptCB callbacksP0[GNUM]; -static interruptCB callbacksP2[GNUM]; +static interruptCB callbacksP0[GNUM] = {}; +static interruptCB callbacksP2[GNUM] = {}; extern "C" void GpioEnableInt(const uint32_t port, const uint32_t pin, const uint32_t mode); extern "C" void GpioDisableInt(const uint32_t port, const uint32_t pin); -//void deadloop(void) {} -/* Configure PIO interrupt sources */ static void __initialize() { - for (uint8_t i = 0; i < GNUM; i++) { - callbacksP0[i] = 0; - callbacksP2[i] = 0; - } + NVIC_SetPriority(EINT3_IRQn, NVIC_EncodePriority(0, 1, 0)); NVIC_EnableIRQ(EINT3_IRQn); } @@ -54,6 +45,7 @@ void attachInterrupt(const pin_t pin, void (*callback)(void), uint32_t mode) { __initialize(); ++enabled; } + uint8_t myport = LPC1768_PIN_PORT(pin), mypin = LPC1768_PIN_PIN(pin); @@ -130,60 +122,41 @@ extern "C" void GpioDisableInt(const uint32_t port, const uint32_t pin) { } } -constexpr bool isPowerOf2(const uint16_t n) { - return IS_POWER_OF_2(n); +extern "C" void EINT3_IRQHandler(void) { + // Read in all current interrupt registers. We do this once as the + // GPIO interrupt registers are on the APB bus, and this is slow. + uint32_t rise0 = LPC_GPIOINT->IO0IntStatR, + fall0 = LPC_GPIOINT->IO0IntStatF, + rise2 = LPC_GPIOINT->IO2IntStatR, + fall2 = LPC_GPIOINT->IO2IntStatF; + + // Clear the interrupts ASAP + LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO2IntClr = 0xFFFFFFFF; + NVIC_ClearPendingIRQ(EINT3_IRQn); + + while (rise0 > 0) { // If multiple pins changes happened continue as long as there are interrupts pending + const uint8_t bitloc = 31 - __CLZ(rise0); // CLZ returns number of leading zeros, 31 minus that is location of first pending interrupt + if (callbacksP0[bitloc] != NULL) callbacksP0[bitloc](); + rise0 -= _BV(bitloc); + } + + while (fall0 > 0) { + const uint8_t bitloc = 31 - __CLZ(fall0); + if (callbacksP0[bitloc] != NULL) callbacksP0[bitloc](); + fall0 -= _BV(bitloc); + } + + while(rise2 > 0) { + const uint8_t bitloc = 31 - __CLZ(rise2); + if (callbacksP2[bitloc] != NULL) callbacksP2[bitloc](); + rise2 -= _BV(bitloc); + } + + while (fall2 > 0) { + const uint8_t bitloc = 31 - __CLZ(fall2); + if (callbacksP2[bitloc] != NULL) callbacksP2[bitloc](); + fall2 -= _BV(bitloc); + } } -#if 0 - extern "C" void EINT3_IRQHandler () { - LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO2IntClr = 0xFFFFFFFF; - TOGGLE(13); - //NVIC_ClearPendingIRQ(EINT3_IRQn); - } -#else - - extern "C" void EINT3_IRQHandler(void) { - // Read in all current interrupt registers. We do this once as the - // GPIO interrupt registers are on the APB bus, and this is slow. - uint32_t rise0 = LPC_GPIOINT->IO0IntStatR, - fall0 = LPC_GPIOINT->IO0IntStatF, - rise2 = LPC_GPIOINT->IO2IntStatR, - fall2 = LPC_GPIOINT->IO2IntStatF; - // Clear the interrupts ASAP - LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO2IntClr = 0xFFFFFFFF; - NVIC_ClearPendingIRQ(EINT3_IRQn); - - /* multiple pins changes happened.*/ - if (rise0) while (rise0 > 0) { // Continue as long as there are interrupts pending - const uint8_t bitloc = 31 - __CLZ(rise0); //CLZ returns number of leading zeros, 31 minus that is location of first pending interrupt - if (callbacksP0[bitloc] != NULL) callbacksP0[bitloc](); - rise0 -= _BV(bitloc); - } - - if (fall0) while (fall0 > 0) { - const uint8_t bitloc = 31 - __CLZ(fall0); - if (callbacksP0[bitloc] != NULL) callbacksP0[bitloc](); - fall0 -= _BV(bitloc); - } - - if (rise2) while(rise2 > 0) { - const uint8_t bitloc = 31 - __CLZ(rise2); - if (callbacksP2[bitloc] != NULL) callbacksP2[bitloc](); - //LPC_GPIOINT->IO2IntClr = 1 << bitloc; - rise2 -= _BV(bitloc); - } - - if (fall2) while (fall2 > 0) { - const uint8_t bitloc = 31 - __CLZ(fall2); - if (callbacksP2[bitloc] != NULL) callbacksP2[bitloc](); - //LPC_GPIOINT->IO2IntClr = 1 << bitloc; - fall2 -= _BV(bitloc); - } - //NVIC_ClearPendingIRQ(EINT3_IRQn); - //LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO2IntClr = 0xFFFFFFFF; - //NVIC_ClearPendingIRQ(EINT3_IRQn); - } - -#endif - #endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/HAL_LPC1768/endstop_interrupts.h b/Marlin/src/HAL/HAL_LPC1768/endstop_interrupts.h index 9167361c6d..48312ccc07 100644 --- a/Marlin/src/HAL/HAL_LPC1768/endstop_interrupts.h +++ b/Marlin/src/HAL/HAL_LPC1768/endstop_interrupts.h @@ -37,9 +37,6 @@ #ifndef _ENDSTOP_INTERRUPTS_H_ #define _ENDSTOP_INTERRUPTS_H_ -//Currently this is untested and broken -#error "Please disable Endstop Interrupts LPC176x is currently an unsupported platform" - #include "../../module/endstops.h" // One ISR for all EXT-Interrupts @@ -47,30 +44,57 @@ void endstop_ISR(void) { endstops.update(); } void setup_endstop_interrupts(void) { #if HAS_X_MAX - attachInterrupt(digitalPinToInterrupt(X_MAX_PIN), endstop_ISR, CHANGE); // assign it + #if !LPC1768_PIN_INTERRUPT_M(X_MAX_PIN) + #error "X_MAX_PIN is not an INTERRUPT capable pin." + #endif + attachInterrupt(digitalPinToInterrupt(X_MAX_PIN), endstop_ISR, CHANGE); #endif #if HAS_X_MIN + #if !LPC1768_PIN_INTERRUPT_M(X_MIN_PIN) + #error "X_MIN_PIN is not an INTERRUPT capable pin." + #endif attachInterrupt(digitalPinToInterrupt(X_MIN_PIN), endstop_ISR, CHANGE); #endif #if HAS_Y_MAX + #if !LPC1768_PIN_INTERRUPT_M(Y_MAX_PIN) + #error "Y_MAX_PIN is not an INTERRUPT capable pin." + #endif attachInterrupt(digitalPinToInterrupt(Y_MAX_PIN), endstop_ISR, CHANGE); #endif #if HAS_Y_MIN + #if !LPC1768_PIN_INTERRUPT_M(Y_MIN_PIN) + #error "Y_MIN_PIN is not an INTERRUPT capable pin." + #endif attachInterrupt(digitalPinToInterrupt(Y_MIN_PIN), endstop_ISR, CHANGE); #endif #if HAS_Z_MAX + #if !LPC1768_PIN_INTERRUPT_M(Z_MAX_PIN) + #error "Z_MAX_PIN is not an INTERRUPT capable pin." + #endif attachInterrupt(digitalPinToInterrupt(Z_MAX_PIN), endstop_ISR, CHANGE); #endif #if HAS_Z_MIN + #if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PIN) + #error "Z_MIN_PIN is not an INTERRUPT capable pin." + #endif attachInterrupt(digitalPinToInterrupt(Z_MIN_PIN), endstop_ISR, CHANGE); #endif #if HAS_Z2_MAX + #if !LPC1768_PIN_INTERRUPT_M(Z2_MAX_PIN) + #error "Z2_MAX_PIN is not an INTERRUPT capable pin." + #endif attachInterrupt(digitalPinToInterrupt(Z2_MAX_PIN), endstop_ISR, CHANGE); #endif #if HAS_Z2_MIN + #if !LPC1768_PIN_INTERRUPT_M(Z2_MIN_PIN) + #error "Z2_MIN_PIN is not an INTERRUPT capable pin." + #endif attachInterrupt(digitalPinToInterrupt(Z2_MIN_PIN), endstop_ISR, CHANGE); #endif #if HAS_Z_MIN_PROBE_PIN + #if !LPC1768_PIN_INTERRUPT_M(Z_MIN_PROBE_PIN) + #error "Z_MIN_PROBE_PIN is not an INTERRUPT capable pin." + #endif attachInterrupt(digitalPinToInterrupt(Z_MIN_PROBE_PIN), endstop_ISR, CHANGE); #endif } diff --git a/Marlin/src/HAL/HAL_LPC1768/include/pinmapping.h b/Marlin/src/HAL/HAL_LPC1768/include/pinmapping.h index 11fdf5cc3a..de727b8bde 100644 --- a/Marlin/src/HAL/HAL_LPC1768/include/pinmapping.h +++ b/Marlin/src/HAL/HAL_LPC1768/include/pinmapping.h @@ -267,7 +267,7 @@ constexpr pin_t adc_pin_table[] = { // Get the digital pin for an analog index pin_t analogInputToDigitalPin(const int8_t p); - +#define digitalPinToInterrupt(pin) (pin) // Return the index of a pin number // The pin number given here is in the form ppp:nnnnn int16_t GET_PIN_MAP_INDEX(const pin_t pin); @@ -283,6 +283,7 @@ bool PWM_PIN(const pin_t p); // Test whether the pin is interruptable bool INTERRUPT_PIN(const pin_t p); +#define LPC1768_PIN_INTERRUPT_M(pin) (((pin >> 8) & 0b1) != 0) // Get the pin number at the given index pin_t GET_PIN_MAP_PIN(const int16_t ind);