Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve hardware timer functions not in IRAM, crashes when called from ISR #4684

Merged
merged 1 commit into from
Jan 11, 2021
Merged

Conversation

taligentx
Copy link
Contributor

Hi folks,

As seen in crankyoldgit/IRremoteESP8266#1350 and taligentx/dscKeybusInterface#80, the Arduino/esp32 hardware timer functions are currently not in IRAM and cause crashes when called from an ISR:

Guru Meditation Error: Core  1 panic'ed (Cache disabled but cached memory region accessed)
Core 1 register dump:
PC      : 0x400d6838  PS      : 0x00060034  A0      : 0x80081aa8  A1      : 0x3ffbffa0  
A2      : 0x3ffc1be0  A3      : 0x20000000  A4      : 0x00000400  A5      : 0x00000000  
A6      : 0x3ffc7458  A7      : 0xffffffff  A8      : 0x800812ff  A9      : 0x00000001  
A10     : 0x3ffbdcb8  A11     : 0x00000000  A12     : 0x3ffba264  A13     : 0x0000abab  
A14     : 0x3ffc7058  A15     : 0x00000000  SAR     : 0x00000012  EXCCAUSE: 0x00000007  
EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000  
Core 1 was running in ISR context:
EPC1    : 0x400833f9  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x400d6838

ELF file SHA256: 0000000000000000

Backtrace: 0x400d6838:0x3ffbffa0 0x40081aa5:0x3ffbffc0 0x400848b5:0x3ffbffe0 0x400833f6:0x3ffba190 0x400858f3:0x3ffba1b0 0x40089d9e:0x3ffba1d0

Rebooting...

// Exception decoding: 

PC: 0x400d6838: timerStop at /Users/taligent/Library/Arduino15/packages/esp32/hardware/esp32/1.0.5-rc4/cores/esp32/esp32-hal-timer.c line 162
EXCVADDR: 0x00000000

Decoding stack results
0x400d6838: timerStop at /Users/taligent/Library/Arduino15/packages/esp32/hardware/esp32/1.0.5-rc4/cores/esp32/esp32-hal-timer.c line 162
0x40081aa5: __timerISR at /Users/taligent/Library/Arduino15/packages/esp32/hardware/esp32/1.0.5-rc4/cores/esp32/esp32-hal-timer.c line 88
0x400833f6: spi_flash_op_block_func at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/cache_utils.c line 82
0x400858f3: ipc_task at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/ipc.c line 62
0x40089d9e: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

I've run across this issue when using ESPAsyncWebServer and Blynk with my library (dscKeybusInterface). The library uses a GPIO pin change interrupt to catch a clock signal, and that ISR triggers a timer interrupt to read data from a different GPIO after 250us. This works fine with Arduino/AVR and esp8266, but calling timerStart() and timerStop() on Arduino/esp32 results in the above crash, and is resolved by placing these functions in IRAM.

For reference, Arduino/esp8266 places its hardware timer functions in IRAM: https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_timer.cpp

The current workaround in the IRremoteESP8266 library bypasses the Arduino esp32 core functions and redefines hw_timer_t and hw_timer_reg_t so its ISR can configure the timers directly: crankyoldgit/IRremoteESP8266#1351

It'd be great to be able to avoid these kinds of workarounds - thanks!

@crankyoldgit
Copy link

@crankyoldgit subscribing so I know when I can remove my ugly hack.

@me-no-dev
Copy link
Member

I am a bit divided between this and actually not running the ISR in IRAM at all (which will be the default approach in the upcoming 2.0.0). Placing more stuff in IRAM can cause issues with WiFi and BT code that is placed there (running out of IRAM space). Will merge this for now, but expect soon to run all interrupts out of IRAM.

@me-no-dev me-no-dev merged commit be77bd4 into espressif:master Jan 11, 2021
@crankyoldgit
Copy link

I am a bit divided between this and actually not running the ISR in IRAM at all (which will be the default approach in the upcoming 2.0.0).

@me-no-dev Can you please elaborate on this (or point to a discussion somewhere) please?
How are we supposed to handle ISRs if not-by-IRAM?

Also, so I know when I can remove my hack in IRremoteESP8266, what be the next release version of core that will include this merge?

@crankyoldgit
Copy link

How are we supposed to handle ISRs if not-by-IRAM?

I'll add to be clear, I can't make this timer call outside of an ISR. i.e. I'm familiar with setting a flag via an ISR, exiting, and then having non-IRAM code act accordingly later etc.

@taligentx
Copy link
Contributor Author

I am a bit divided between this and actually not running the ISR in IRAM at all (which will be the default approach in the upcoming 2.0.0)

Hi @me-no-dev - thanks for taking a look at this, and noted on my TODO list to look at the impacts of moving ISRs out of IRAM (at least for the ESP32 family). Arduino/esp8266 core requires ISRs to be in IRAM so I hadn't considered running outside of IRAM for ESP32.

In the case of dscKeybusInterface, the timer functions are getting called from a GPIO edge interrupt ISR every 500us (the external clock signal), which trigger a timer interrupt 250us later. If the timer interrupt is delayed by more than 250us, the data will be corrupt so I'll need to see what would happen in the case of a flash cache miss.

Some of the implementations of this library use ESPAsyncWebServer (thank you for this!) and SPIFFS - would a non-IRAM ISR be reliable in this scenario? xTaskNotifyFromISR() and such wouldn't help if the data itself isn't captured in time by the ISR.

@mathieucarbou
Copy link
Contributor

mathieucarbou commented Sep 27, 2024

FYI I found a way to have ISR function in IRAM for timers and at the same time run concurrent flash operations, by redefining some of the gtimer calls to be lined.

I am using that in the project: https://github.com/mathieucarbou/MycilaPulseAnalyzer which is a pulse analyser for ZCD circuits and ZC event trigger.

So it deals with ISR, gpio interrupts and timer interrupts, all in IRAM on Arduino.

There are 2 examples showing that, with also concurrent operations, which, of course crash if I use the Arduino API or ESP-IDF gtimer library directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants