From ccd2c7b426179ad50e4e2c0d3f132954fc6aa72c Mon Sep 17 00:00:00 2001 From: Mark Kriegsman <1334634+kriegsman@users.noreply.github.com> Date: Mon, 1 Nov 2021 22:15:35 -0400 Subject: Fix for ESP8266 interrupt handling mistakes, which were showing up once switching to the ESP8266 3.0.x core. --- src/platforms/esp/32/led_sysdefs_esp32.h | 2 -- src/platforms/esp/8266/clockless_esp8266.h | 44 +++++++++++++++++----------- src/platforms/esp/8266/led_sysdefs_esp8266.h | 2 -- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/platforms/esp/32/led_sysdefs_esp32.h b/src/platforms/esp/32/led_sysdefs_esp32.h index 5cd374e2..73df21bb 100644 --- a/src/platforms/esp/32/led_sysdefs_esp32.h +++ b/src/platforms/esp/32/led_sysdefs_esp32.h @@ -29,5 +29,3 @@ typedef unsigned long prog_uint32_t; // These can be overridden # define FASTLED_ESP32_RAW_PIN_ORDER -// #define cli() os_intr_lock(); -// #define sei() os_intr_lock(); diff --git a/src/platforms/esp/8266/clockless_esp8266.h b/src/platforms/esp/8266/clockless_esp8266.h index cf6690c6..ca2a6067 100644 --- a/src/platforms/esp/8266/clockless_esp8266.h +++ b/src/platforms/esp/8266/clockless_esp8266.h @@ -42,9 +42,7 @@ protected: #ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES ++_retry_cnt; #endif - os_intr_unlock(); delayMicroseconds(WAIT_TIME); - os_intr_lock(); } mWait.mark(); } @@ -78,23 +76,35 @@ protected: return false; } - // This method is made static to force making register Y available to use for data on AVR - if the method is non-static, then - // gcc will use register Y for the this pointer. + static uint32_t ICACHE_RAM_ATTR showRGBInternal(PixelController pixels) { // Setup the pixel controller and load/scale the first byte pixels.preStepFirstByteDithering(); register uint32_t b = pixels.loadAndScale0(); - pixels.preStepFirstByteDithering(); + pixels.preStepFirstByteDithering(); uint32_t start; - { - struct Lock { - Lock() { - os_intr_lock(); - } - ~Lock() { - os_intr_unlock(); - } - }; + + // This function has multiple exits, so we'll use an object + // with a destructor that releases the interrupt lock, regardless + // of how we exit the function. It also has methods for manually + // unlocking and relocking interrupts temporarily. + struct InterruptLock { + InterruptLock() { + os_intr_lock(); + } + ~InterruptLock() { + os_intr_unlock(); + } + void Unlock() { + os_intr_unlock(); + } + void Lock() { + os_intr_lock(); + } + }; + + { // Start of interrupt-locked block + InterruptLock intlock; start = __clock_cycles(); uint32_t last_mark = start; @@ -117,14 +127,14 @@ protected: } #if (FASTLED_ALLOW_INTERRUPTS == 1) - os_intr_unlock(); + intlock.Unlock(); #endif b = pixels.advanceAndLoadAndScale0(); pixels.stepDithering(); #if (FASTLED_ALLOW_INTERRUPTS == 1) - os_intr_lock(); + intlock.Lock(); // if interrupts took longer than 45µs, punt on the current frame if((int32_t)(__clock_cycles()-last_mark) > 0) { if((int32_t)(__clock_cycles()-last_mark) > (T1+T2+T3+((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US))) { @@ -133,7 +143,7 @@ protected: } #endif }; - } + } // End of interrupt-locked block #ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES ++_frame_cnt; diff --git a/src/platforms/esp/8266/led_sysdefs_esp8266.h b/src/platforms/esp/8266/led_sysdefs_esp8266.h index 26dffdcf..668a006b 100644 --- a/src/platforms/esp/8266/led_sysdefs_esp8266.h +++ b/src/platforms/esp/8266/led_sysdefs_esp8266.h @@ -35,5 +35,3 @@ typedef uint32_t prog_uint32_t; # endif #endif -// #define cli() os_intr_lock(); -// #define sei() os_intr_lock(); -- cgit v1.2.3