From 5b0eaac30badd5225a944accb6491f8015534a46 Mon Sep 17 00:00:00 2001 From: Max Prokhorov Date: Mon, 29 Apr 2019 10:28:47 +0300 Subject: [PATCH] ESP8266 / ESP32: Place ISR in IRAM --- Encoder.cpp | 2 - Encoder.h | 553 ++++++++++++++++++++++++++-------------------------- 2 files changed, 281 insertions(+), 274 deletions(-) diff --git a/Encoder.cpp b/Encoder.cpp index 6911b4f..b2d33d6 100644 --- a/Encoder.cpp +++ b/Encoder.cpp @@ -5,6 +5,4 @@ // configure options with #define (before they include it), and // to facilitate some crafty optimizations! -Encoder_internal_state_t * Encoder::interruptArgs[]; - diff --git a/Encoder.h b/Encoder.h index 6e0a2c3..147f932 100644 --- a/Encoder.h +++ b/Encoder.h @@ -51,6 +51,14 @@ #define ENCODER_ARGLIST_SIZE 0 #endif +// We need to manually place interrupt handlers in RAM for these platforms +#if defined(ESP8266) || defined(ESP32) +#ifndef IRAM_ATTR +#define IRAM_ATTR ICACHE_RAM_ATTR +#endif +#else +#define IRAM_ATTR +#endif // All the data needed by interrupts is consolidated into this ugly struct @@ -66,92 +74,9 @@ typedef struct { int32_t position; } Encoder_internal_state_t; -class Encoder -{ -public: - Encoder(uint8_t pin1, uint8_t pin2) { - #ifdef INPUT_PULLUP - pinMode(pin1, INPUT_PULLUP); - pinMode(pin2, INPUT_PULLUP); - #else - pinMode(pin1, INPUT); - digitalWrite(pin1, HIGH); - pinMode(pin2, INPUT); - digitalWrite(pin2, HIGH); - #endif - encoder.pin1_register = PIN_TO_BASEREG(pin1); - encoder.pin1_bitmask = PIN_TO_BITMASK(pin1); - encoder.pin2_register = PIN_TO_BASEREG(pin2); - encoder.pin2_bitmask = PIN_TO_BITMASK(pin2); - encoder.position = 0; - // allow time for a passive R-C filter to charge - // through the pullup resistors, before reading - // the initial state - delayMicroseconds(2000); - uint8_t s = 0; - if (DIRECT_PIN_READ(encoder.pin1_register, encoder.pin1_bitmask)) s |= 1; - if (DIRECT_PIN_READ(encoder.pin2_register, encoder.pin2_bitmask)) s |= 2; - encoder.state = s; -#ifdef ENCODER_USE_INTERRUPTS - interrupts_in_use = attach_interrupt(pin1, &encoder); - interrupts_in_use += attach_interrupt(pin2, &encoder); -#endif - //update_finishup(); // to force linker to include the code (does not work) - } +static Encoder_internal_state_t * interruptArgs[ENCODER_ARGLIST_SIZE]; -#ifdef ENCODER_USE_INTERRUPTS - inline int32_t read() { - if (interrupts_in_use < 2) { - noInterrupts(); - update(&encoder); - } else { - noInterrupts(); - } - int32_t ret = encoder.position; - interrupts(); - return ret; - } - inline int32_t readAndReset() { - if (interrupts_in_use < 2) { - noInterrupts(); - update(&encoder); - } else { - noInterrupts(); - } - int32_t ret = encoder.position; - encoder.position = 0; - interrupts(); - return ret; - } - inline void write(int32_t p) { - noInterrupts(); - encoder.position = p; - interrupts(); - } -#else - inline int32_t read() { - update(&encoder); - return encoder.position; - } - inline int32_t readAndReset() { - update(&encoder); - int32_t ret = encoder.position; - encoder.position = 0; - return ret; - } - inline void write(int32_t p) { - encoder.position = p; - } -#endif -private: - Encoder_internal_state_t encoder; -#ifdef ENCODER_USE_INTERRUPTS - uint8_t interrupts_in_use; -#endif -public: - static Encoder_internal_state_t * interruptArgs[ENCODER_ARGLIST_SIZE]; - // _______ _______ // Pin1 ______| |_______| |______ Pin1 // negative <--- _______ _______ __ --> positive @@ -199,11 +124,10 @@ class Encoder } */ -public: - // update() is not meant to be called from outside Encoder, - // but it is public to allow static interrupt routines. - // DO NOT call update() directly from sketches. - static void update(Encoder_internal_state_t *arg) { +// update() is not meant to be called from outside Encoder, +// but it is public to allow static interrupt routines. +// DO NOT call update() directly from sketches. +static void IRAM_ATTR update(Encoder_internal_state_t *arg) { #if defined(__AVR__) // The compiler believes this is just 1 line of code, so // it will inline this function into each interrupt @@ -311,6 +235,274 @@ class Encoder } #endif } + +#if defined(ENCODER_USE_INTERRUPTS) && !defined(ENCODER_OPTIMIZE_INTERRUPTS) + #ifdef CORE_INT0_PIN + static void IRAM_ATTR isr0(void) { update(interruptArgs[0]); } + #endif + #ifdef CORE_INT1_PIN + static void IRAM_ATTR isr1(void) { update(interruptArgs[1]); } + #endif + #ifdef CORE_INT2_PIN + static void IRAM_ATTR isr2(void) { update(interruptArgs[2]); } + #endif + #ifdef CORE_INT3_PIN + static void IRAM_ATTR isr3(void) { update(interruptArgs[3]); } + #endif + #ifdef CORE_INT4_PIN + static void IRAM_ATTR isr4(void) { update(interruptArgs[4]); } + #endif + #ifdef CORE_INT5_PIN + static void IRAM_ATTR isr5(void) { update(interruptArgs[5]); } + #endif + #ifdef CORE_INT6_PIN + static void IRAM_ATTR isr6(void) { update(interruptArgs[6]); } + #endif + #ifdef CORE_INT7_PIN + static void IRAM_ATTR isr7(void) { update(interruptArgs[7]); } + #endif + #ifdef CORE_INT8_PIN + static void IRAM_ATTR isr8(void) { update(interruptArgs[8]); } + #endif + #ifdef CORE_INT9_PIN + static void IRAM_ATTR isr9(void) { update(interruptArgs[9]); } + #endif + #ifdef CORE_INT10_PIN + static void IRAM_ATTR isr10(void) { update(interruptArgs[10]); } + #endif + #ifdef CORE_INT11_PIN + static void IRAM_ATTR isr11(void) { update(interruptArgs[11]); } + #endif + #ifdef CORE_INT12_PIN + static void IRAM_ATTR isr12(void) { update(interruptArgs[12]); } + #endif + #ifdef CORE_INT13_PIN + static void IRAM_ATTR isr13(void) { update(interruptArgs[13]); } + #endif + #ifdef CORE_INT14_PIN + static void IRAM_ATTR isr14(void) { update(interruptArgs[14]); } + #endif + #ifdef CORE_INT15_PIN + static void IRAM_ATTR isr15(void) { update(interruptArgs[15]); } + #endif + #ifdef CORE_INT16_PIN + static void IRAM_ATTR isr16(void) { update(interruptArgs[16]); } + #endif + #ifdef CORE_INT17_PIN + static void IRAM_ATTR isr17(void) { update(interruptArgs[17]); } + #endif + #ifdef CORE_INT18_PIN + static void IRAM_ATTR isr18(void) { update(interruptArgs[18]); } + #endif + #ifdef CORE_INT19_PIN + static void IRAM_ATTR isr19(void) { update(interruptArgs[19]); } + #endif + #ifdef CORE_INT20_PIN + static void IRAM_ATTR isr20(void) { update(interruptArgs[20]); } + #endif + #ifdef CORE_INT21_PIN + static void IRAM_ATTR isr21(void) { update(interruptArgs[21]); } + #endif + #ifdef CORE_INT22_PIN + static void IRAM_ATTR isr22(void) { update(interruptArgs[22]); } + #endif + #ifdef CORE_INT23_PIN + static void IRAM_ATTR isr23(void) { update(interruptArgs[23]); } + #endif + #ifdef CORE_INT24_PIN + static void IRAM_ATTR isr24(void) { update(interruptArgs[24]); } + #endif + #ifdef CORE_INT25_PIN + static void IRAM_ATTR isr25(void) { update(interruptArgs[25]); } + #endif + #ifdef CORE_INT26_PIN + static void IRAM_ATTR isr26(void) { update(interruptArgs[26]); } + #endif + #ifdef CORE_INT27_PIN + static void IRAM_ATTR isr27(void) { update(interruptArgs[27]); } + #endif + #ifdef CORE_INT28_PIN + static void IRAM_ATTR isr28(void) { update(interruptArgs[28]); } + #endif + #ifdef CORE_INT29_PIN + static void IRAM_ATTR isr29(void) { update(interruptArgs[29]); } + #endif + #ifdef CORE_INT30_PIN + static void IRAM_ATTR isr30(void) { update(interruptArgs[30]); } + #endif + #ifdef CORE_INT31_PIN + static void IRAM_ATTR isr31(void) { update(interruptArgs[31]); } + #endif + #ifdef CORE_INT32_PIN + static void IRAM_ATTR isr32(void) { update(interruptArgs[32]); } + #endif + #ifdef CORE_INT33_PIN + static void IRAM_ATTR isr33(void) { update(interruptArgs[33]); } + #endif + #ifdef CORE_INT34_PIN + static void IRAM_ATTR isr34(void) { update(interruptArgs[34]); } + #endif + #ifdef CORE_INT35_PIN + static void IRAM_ATTR isr35(void) { update(interruptArgs[35]); } + #endif + #ifdef CORE_INT36_PIN + static void IRAM_ATTR isr36(void) { update(interruptArgs[36]); } + #endif + #ifdef CORE_INT37_PIN + static void IRAM_ATTR isr37(void) { update(interruptArgs[37]); } + #endif + #ifdef CORE_INT38_PIN + static void IRAM_ATTR isr38(void) { update(interruptArgs[38]); } + #endif + #ifdef CORE_INT39_PIN + static void IRAM_ATTR isr39(void) { update(interruptArgs[39]); } + #endif + #ifdef CORE_INT40_PIN + static void IRAM_ATTR isr40(void) { update(interruptArgs[40]); } + #endif + #ifdef CORE_INT41_PIN + static void IRAM_ATTR isr41(void) { update(interruptArgs[41]); } + #endif + #ifdef CORE_INT42_PIN + static void IRAM_ATTR isr42(void) { update(interruptArgs[42]); } + #endif + #ifdef CORE_INT43_PIN + static void IRAM_ATTR isr43(void) { update(interruptArgs[43]); } + #endif + #ifdef CORE_INT44_PIN + static void IRAM_ATTR isr44(void) { update(interruptArgs[44]); } + #endif + #ifdef CORE_INT45_PIN + static void IRAM_ATTR isr45(void) { update(interruptArgs[45]); } + #endif + #ifdef CORE_INT46_PIN + static void IRAM_ATTR isr46(void) { update(interruptArgs[46]); } + #endif + #ifdef CORE_INT47_PIN + static void IRAM_ATTR isr47(void) { update(interruptArgs[47]); } + #endif + #ifdef CORE_INT48_PIN + static void IRAM_ATTR isr48(void) { update(interruptArgs[48]); } + #endif + #ifdef CORE_INT49_PIN + static void IRAM_ATTR isr49(void) { update(interruptArgs[49]); } + #endif + #ifdef CORE_INT50_PIN + static void IRAM_ATTR isr50(void) { update(interruptArgs[50]); } + #endif + #ifdef CORE_INT51_PIN + static void IRAM_ATTR isr51(void) { update(interruptArgs[51]); } + #endif + #ifdef CORE_INT52_PIN + static void IRAM_ATTR isr52(void) { update(interruptArgs[52]); } + #endif + #ifdef CORE_INT53_PIN + static void IRAM_ATTR isr53(void) { update(interruptArgs[53]); } + #endif + #ifdef CORE_INT54_PIN + static void IRAM_ATTR isr54(void) { update(interruptArgs[54]); } + #endif + #ifdef CORE_INT55_PIN + static void IRAM_ATTR isr55(void) { update(interruptArgs[55]); } + #endif + #ifdef CORE_INT56_PIN + static void IRAM_ATTR isr56(void) { update(interruptArgs[56]); } + #endif + #ifdef CORE_INT57_PIN + static void IRAM_ATTR isr57(void) { update(interruptArgs[57]); } + #endif + #ifdef CORE_INT58_PIN + static void IRAM_ATTR isr58(void) { update(interruptArgs[58]); } + #endif + #ifdef CORE_INT59_PIN + static void IRAM_ATTR isr59(void) { update(interruptArgs[59]); } + #endif +#endif + +class Encoder +{ +public: + Encoder(uint8_t pin1, uint8_t pin2) { + #ifdef INPUT_PULLUP + pinMode(pin1, INPUT_PULLUP); + pinMode(pin2, INPUT_PULLUP); + #else + pinMode(pin1, INPUT); + digitalWrite(pin1, HIGH); + pinMode(pin2, INPUT); + digitalWrite(pin2, HIGH); + #endif + encoder.pin1_register = PIN_TO_BASEREG(pin1); + encoder.pin1_bitmask = PIN_TO_BITMASK(pin1); + encoder.pin2_register = PIN_TO_BASEREG(pin2); + encoder.pin2_bitmask = PIN_TO_BITMASK(pin2); + encoder.position = 0; + // allow time for a passive R-C filter to charge + // through the pullup resistors, before reading + // the initial state + delayMicroseconds(2000); + uint8_t s = 0; + if (DIRECT_PIN_READ(encoder.pin1_register, encoder.pin1_bitmask)) s |= 1; + if (DIRECT_PIN_READ(encoder.pin2_register, encoder.pin2_bitmask)) s |= 2; + encoder.state = s; +#ifdef ENCODER_USE_INTERRUPTS + interrupts_in_use = attach_interrupt(pin1, &encoder); + interrupts_in_use += attach_interrupt(pin2, &encoder); +#endif + //update_finishup(); // to force linker to include the code (does not work) + } + + +#ifdef ENCODER_USE_INTERRUPTS + inline int32_t read() { + if (interrupts_in_use < 2) { + noInterrupts(); + update(&encoder); + } else { + noInterrupts(); + } + int32_t ret = encoder.position; + interrupts(); + return ret; + } + inline int32_t readAndReset() { + if (interrupts_in_use < 2) { + noInterrupts(); + update(&encoder); + } else { + noInterrupts(); + } + int32_t ret = encoder.position; + encoder.position = 0; + interrupts(); + return ret; + } + inline void write(int32_t p) { + noInterrupts(); + encoder.position = p; + interrupts(); + } +#else + inline int32_t read() { + update(&encoder); + return encoder.position; + } + inline int32_t readAndReset() { + update(&encoder); + int32_t ret = encoder.position; + encoder.position = 0; + return ret; + } + inline void write(int32_t p) { + encoder.position = p; + } +#endif +private: + Encoder_internal_state_t encoder; +#ifdef ENCODER_USE_INTERRUPTS + uint8_t interrupts_in_use; +#endif + private: /* #if defined(__AVR__) @@ -746,189 +938,6 @@ class Encoder } #endif // ENCODER_USE_INTERRUPTS - -#if defined(ENCODER_USE_INTERRUPTS) && !defined(ENCODER_OPTIMIZE_INTERRUPTS) - #ifdef CORE_INT0_PIN - static void isr0(void) { update(interruptArgs[0]); } - #endif - #ifdef CORE_INT1_PIN - static void isr1(void) { update(interruptArgs[1]); } - #endif - #ifdef CORE_INT2_PIN - static void isr2(void) { update(interruptArgs[2]); } - #endif - #ifdef CORE_INT3_PIN - static void isr3(void) { update(interruptArgs[3]); } - #endif - #ifdef CORE_INT4_PIN - static void isr4(void) { update(interruptArgs[4]); } - #endif - #ifdef CORE_INT5_PIN - static void isr5(void) { update(interruptArgs[5]); } - #endif - #ifdef CORE_INT6_PIN - static void isr6(void) { update(interruptArgs[6]); } - #endif - #ifdef CORE_INT7_PIN - static void isr7(void) { update(interruptArgs[7]); } - #endif - #ifdef CORE_INT8_PIN - static void isr8(void) { update(interruptArgs[8]); } - #endif - #ifdef CORE_INT9_PIN - static void isr9(void) { update(interruptArgs[9]); } - #endif - #ifdef CORE_INT10_PIN - static void isr10(void) { update(interruptArgs[10]); } - #endif - #ifdef CORE_INT11_PIN - static void isr11(void) { update(interruptArgs[11]); } - #endif - #ifdef CORE_INT12_PIN - static void isr12(void) { update(interruptArgs[12]); } - #endif - #ifdef CORE_INT13_PIN - static void isr13(void) { update(interruptArgs[13]); } - #endif - #ifdef CORE_INT14_PIN - static void isr14(void) { update(interruptArgs[14]); } - #endif - #ifdef CORE_INT15_PIN - static void isr15(void) { update(interruptArgs[15]); } - #endif - #ifdef CORE_INT16_PIN - static void isr16(void) { update(interruptArgs[16]); } - #endif - #ifdef CORE_INT17_PIN - static void isr17(void) { update(interruptArgs[17]); } - #endif - #ifdef CORE_INT18_PIN - static void isr18(void) { update(interruptArgs[18]); } - #endif - #ifdef CORE_INT19_PIN - static void isr19(void) { update(interruptArgs[19]); } - #endif - #ifdef CORE_INT20_PIN - static void isr20(void) { update(interruptArgs[20]); } - #endif - #ifdef CORE_INT21_PIN - static void isr21(void) { update(interruptArgs[21]); } - #endif - #ifdef CORE_INT22_PIN - static void isr22(void) { update(interruptArgs[22]); } - #endif - #ifdef CORE_INT23_PIN - static void isr23(void) { update(interruptArgs[23]); } - #endif - #ifdef CORE_INT24_PIN - static void isr24(void) { update(interruptArgs[24]); } - #endif - #ifdef CORE_INT25_PIN - static void isr25(void) { update(interruptArgs[25]); } - #endif - #ifdef CORE_INT26_PIN - static void isr26(void) { update(interruptArgs[26]); } - #endif - #ifdef CORE_INT27_PIN - static void isr27(void) { update(interruptArgs[27]); } - #endif - #ifdef CORE_INT28_PIN - static void isr28(void) { update(interruptArgs[28]); } - #endif - #ifdef CORE_INT29_PIN - static void isr29(void) { update(interruptArgs[29]); } - #endif - #ifdef CORE_INT30_PIN - static void isr30(void) { update(interruptArgs[30]); } - #endif - #ifdef CORE_INT31_PIN - static void isr31(void) { update(interruptArgs[31]); } - #endif - #ifdef CORE_INT32_PIN - static void isr32(void) { update(interruptArgs[32]); } - #endif - #ifdef CORE_INT33_PIN - static void isr33(void) { update(interruptArgs[33]); } - #endif - #ifdef CORE_INT34_PIN - static void isr34(void) { update(interruptArgs[34]); } - #endif - #ifdef CORE_INT35_PIN - static void isr35(void) { update(interruptArgs[35]); } - #endif - #ifdef CORE_INT36_PIN - static void isr36(void) { update(interruptArgs[36]); } - #endif - #ifdef CORE_INT37_PIN - static void isr37(void) { update(interruptArgs[37]); } - #endif - #ifdef CORE_INT38_PIN - static void isr38(void) { update(interruptArgs[38]); } - #endif - #ifdef CORE_INT39_PIN - static void isr39(void) { update(interruptArgs[39]); } - #endif - #ifdef CORE_INT40_PIN - static void isr40(void) { update(interruptArgs[40]); } - #endif - #ifdef CORE_INT41_PIN - static void isr41(void) { update(interruptArgs[41]); } - #endif - #ifdef CORE_INT42_PIN - static void isr42(void) { update(interruptArgs[42]); } - #endif - #ifdef CORE_INT43_PIN - static void isr43(void) { update(interruptArgs[43]); } - #endif - #ifdef CORE_INT44_PIN - static void isr44(void) { update(interruptArgs[44]); } - #endif - #ifdef CORE_INT45_PIN - static void isr45(void) { update(interruptArgs[45]); } - #endif - #ifdef CORE_INT46_PIN - static void isr46(void) { update(interruptArgs[46]); } - #endif - #ifdef CORE_INT47_PIN - static void isr47(void) { update(interruptArgs[47]); } - #endif - #ifdef CORE_INT48_PIN - static void isr48(void) { update(interruptArgs[48]); } - #endif - #ifdef CORE_INT49_PIN - static void isr49(void) { update(interruptArgs[49]); } - #endif - #ifdef CORE_INT50_PIN - static void isr50(void) { update(interruptArgs[50]); } - #endif - #ifdef CORE_INT51_PIN - static void isr51(void) { update(interruptArgs[51]); } - #endif - #ifdef CORE_INT52_PIN - static void isr52(void) { update(interruptArgs[52]); } - #endif - #ifdef CORE_INT53_PIN - static void isr53(void) { update(interruptArgs[53]); } - #endif - #ifdef CORE_INT54_PIN - static void isr54(void) { update(interruptArgs[54]); } - #endif - #ifdef CORE_INT55_PIN - static void isr55(void) { update(interruptArgs[55]); } - #endif - #ifdef CORE_INT56_PIN - static void isr56(void) { update(interruptArgs[56]); } - #endif - #ifdef CORE_INT57_PIN - static void isr57(void) { update(interruptArgs[57]); } - #endif - #ifdef CORE_INT58_PIN - static void isr58(void) { update(interruptArgs[58]); } - #endif - #ifdef CORE_INT59_PIN - static void isr59(void) { update(interruptArgs[59]); } - #endif -#endif }; #if defined(ENCODER_USE_INTERRUPTS) && defined(ENCODER_OPTIMIZE_INTERRUPTS)