v3.0.0: Calling digitalWrite() inside ISR May Crash Due to Lack of IRAM_ATTR in _stopPWM() · Issue #8043 · esp8266/Arduino (original) (raw)

digitalWrite() calls _stopPWM(), which lacks the IRAM_ATTR attribute.

When digitalWrite() is called inside an ISR handler, it may have to wait for the content get fetched from the external flash, which'd block the ISR handler, which may cause the system to crash.

This bug can be easily reproduced if you read the flash filesystem while running digitalWrite() in ISR frequently. For the ease of implementation, the MCVE uses the ESP8266TimerInterrupt library.

This bug is new in v3.0.0 and couldn't be reproduced in v2.7.4.

#include <ESP8266TimerInterrupt.h> // https://github.com/khoih-prog/ESP8266TimerInterrupt #include <LittleFS.h> #define TEST_PIN (15) #define FILENAME "foobarbaz" #define FILE_CONTENT "foobarbaz" ESP8266Timer esp8266timer;

static IRAM_ATTR void timer_isr_handler() { static int state = LOW; digitalWrite(TEST_PIN, state); state = !state; }

void setup() { LittleFS.begin(); Serial.begin(115200); // Create a file in the LittleFS filesystem to be read in loop() File f = LittleFS.open(FILENAME, "w"); f.write(FILE_CONTENT, sizeof(FILE_CONTENT)); f.close();

// Initialization pinMode(TEST_PIN, OUTPUT); if (!esp8266timer.attachInterruptInterval(1 * 1000, timer_isr_handler)) { // Triggered once every millisecond Serial.println("Error: Failed to attach timer interrupt handler!"); delay(1000); ESP.restart(); }

delay(5000); // Rate limiting: Prevent the flash from wearing out from frequent f.write() calls. Serial.println("ready!"); }

void loop() { // Print the content from a file in the filesystem with Serial File f = LittleFS.open(FILENAME, "r"); if(f) { char buf[sizeof(FILE_CONTENT)]; f.read((uint8_t*)buf, sizeof(FILE_CONTENT)); Serial.print("File content read: "); Serial.println(buf); f.close(); } delay(100); }


Exception 0: Illegal instruction
PC: 0x40209884: _stopPWM(uint8_t) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_waveform_pwm.cpp line 264
EXCVADDR: 0x00000000

Decoding stack results
0x40100400: __digitalWrite(uint8_t, uint8_t) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_wiring_digital.cpp line 86
0x401001e0: timer1_isr_handler(void*, void*) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_timer.cpp line 37
0x4010011d: timer_isr_handler() at /home/username/Desktop/link to usb-7-segment/firmware/stoppwm_bug/stoppwm_bug.ino line 11
0x40100228: timer1_isr_handler(void*, void*) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_timer.cpp line 44
0x40100e86: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_phy.cpp line 309
0x40100e86: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_phy.cpp line 309
0x40209180: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/Esp.cpp line 954
0x40209207: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/Esp.cpp line 933
0x40100e86: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_phy.cpp line 309
0x40209180: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/Esp.cpp line 954
0x40209207: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/Esp.cpp line 933
0x40100e86: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_phy.cpp line 309
0x40209180: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/Esp.cpp line 954
0x40209207: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/Esp.cpp line 933
0x401001a8: ets_post(uint8, ETSSignal, ETSParam) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_main.cpp line 181
0x40100100: std::function ::operator()() const at /home/username/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.0-newlib4.0.0-gnu23-48f7b08/xtensa-lx106-elf/include/c++/10.2.0/bits/std_function.h line 617
0x402075fa: __yield() at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_main.cpp line 116
0x40208045: flash_hal_read(unsigned int, unsigned int, unsigned char*) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/flash_hal.cpp line 36
0x40205dba: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/LittleFS.cpp line 171
0x40201330: lfs_bd_read at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/../lib/littlefs/lfs.c line 101
0x402018a1: lfs_dir_fetchmatch at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/../lib/littlefs/lfs.c line 891
0x40205dba: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/LittleFS.cpp line 171
0x40201e94: lfs_dir_find at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/../lib/littlefs/lfs.c line 1238
0x402020f8: lfs_dir_find_match at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/../lib/littlefs/lfs.c line 1140
0x40204554: lfs_dir_commit_commit at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/../lib/littlefs/lfs.c line 1560
0x40204266: lfs_file_rawopencfg at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/../lib/littlefs/lfs.c line 2472
0x40204ced: lfs_file_open at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/libraries/LittleFS/src/../lib/littlefs/lfs.c line 5058
0x4020684f: littlefs_impl::LittleFSImpl::open(char const*, fs::OpenMode, fs::AccessMode) at /home/username/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.0-newlib4.0.0-gnu23-48f7b08/xtensa-lx106-elf/include/c++/10.2.0/bits/shared_ptr_base.h line 1324
0x401008a7: umm_free_core(umm_heap_context_t*, void*) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/umm_malloc/umm_malloc.cpp line 549
0x40206c33: fs::FS::open(char const*, char const*) at /home/username/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.0-newlib4.0.0-gnu23-48f7b08/xtensa-lx106-elf/include/c++/10.2.0/bits/shared_ptr_base.h line 1324
0x40206dd0: HardwareSerial::write(unsigned char const*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/HardwareSerial.h line 193
0x40206ddc: HardwareSerial::write(unsigned char const*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/HardwareSerial.h line 193
0x40206dd0: HardwareSerial::write(unsigned char const*, unsigned int) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/HardwareSerial.h line 193
0x40206f74: Print::write(char const*) at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/Print.h line 59
0x40206fc0: Print::println() at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/Print.h line 57
0x4020549f: loop() at /home/username/Desktop/link to usb-7-segment/firmware/stoppwm_bug/stoppwm_bug.ino line 31
0x402055b5: setup() at /home/username/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.0-newlib4.0.0-gnu23-48f7b08/xtensa-lx106-elf/include/c++/10.2.0/bits/shared_ptr_base.h line 1183
0x40205f48: fs::FS::_defaultTimeCB() at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/FS.h line 249
0x4020767c: loop_wrapper() at /home/username/.arduino15/packages/esp8266/hardware/esp8266/3.0.0/cores/esp8266/core_esp8266_main.cpp line 201