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

core 2.7.4 to 3.0.2 problem in interrupt and timer1 #8581

Closed
GitHubLionel opened this issue May 24, 2022 · 17 comments
Closed

core 2.7.4 to 3.0.2 problem in interrupt and timer1 #8581

GitHubLionel opened this issue May 24, 2022 · 17 comments

Comments

@GitHubLionel
Copy link

GitHubLionel commented May 24, 2022

Hi

So my project : ESP12E Wemos D1 mini, 4 Mo, core 2.7.4, Sloeber env. on Windows7

Problem : My code work perfectly with core 2.7.4 and crash with 3.0.2. The crash is always around the same place : in the interrupt of the timer1. In short, I made a dimer : when I have the zero cross interrupt, I start the timer1 to activate the SSR relay for a delay.

I really made hundred of try but always the same problem.

Any ideas are welcome :)

Regards,
Lionel

The relevant code is :

#define SSR_TURN_ON_us    50
uint8_t SSR_PIN;
int8_t LED_PIN = -1;
static bool Top_CS_ZC = false;
static volatile bool Tim_Interrupt_Enabled = false;
static volatile bool Is_SSR_enabled = false;
static volatile float SSR_COUNT = 0.0;

// Send SSR pulse after delay
void IRAM_ATTR onTimerSSR(void)
{
	if (Is_SSR_enabled)
	{
		if (Top_CS_ZC)
		{
			digitalWrite(SSR_PIN, HIGH);
			Top_CS_ZC = false;
			Timer_SSR.setInterval(SSR_TURN_ON_us);
			Timer_SSR.startTimer();
		}
		else
		{
			digitalWrite(SSR_PIN, LOW);
			if (LED_PIN != -1)
				digitalWrite(LED_PIN, HIGH);
		}
	}
}

// Zero cross was fired
void IRAM_ATTR onZC(void)
{
	Count_CS_ZC++;

	if (Is_SSR_enabled && Tim_Interrupt_Enabled)
	{
		if (LED_PIN != -1)
			digitalWrite(LED_PIN, LOW);

		Top_CS_ZC = true;
		 Timer_SSR.setInterval(SSR_COUNT);
		Timer_SSR.startTimer();     <------------------- here is the line 120
	}
}

void IRAM_ATTR startTimer(void)
{
	timer1_write(_timerCount);
	timer1_enable(TIM_DIV, TIM_EDGE, _loop);
}

The dump crash stack is :

0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x4010127c: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 37
0x401002af: onTimerSSR() at E:\Sloeber\Sloeber_library\SSR\SSR.cpp line 120
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x401012c4: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 44
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40100fd6: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402159c0: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x40215a47: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40100fd6: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402159c0: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x40215a47: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x40211997: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 171
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101638: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 167
0x40211988: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 169
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x402019db: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 975
0x402019c4: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 964
0x4021901a: __yield() at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_main.cpp line 116
0x4021a425: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.2\cores\esp8266\flash_hal.cpp line 36
0x402119a6: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 171
0x40201330: lfs_bd_read at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 101
0x402018a2: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 891
0x4021a425: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.2\cores\esp8266\flash_hal.cpp line 36
0x40201e90: lfs_dir_find at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1238
0x402020f4: lfs_dir_find_match at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1140
0x40204262: lfs_file_rawopencfg at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 2472
0x4010095b: umm_free_core(umm_heap_context_t*, void*) at ...\esp8266\3.0.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 549
0x40221370: _strdup_r at /workdir/repo/newlib/newlib/libc/string/strdup_r.c line 10
0x40204ce9: lfs_file_open at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 5058
0x4021228e: littlefs_impl::LittleFSImpl::open(char const*, fs::OpenMode, fs::AccessMode) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 85
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101638: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 167
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
@themindfactory
Copy link
Contributor

themindfactory commented May 24, 2022 via email

@themindfactory
Copy link
Contributor

themindfactory commented May 24, 2022 via email

@mcspr
Copy link
Collaborator

mcspr commented May 24, 2022

What's Timer_SSR? What's the exception code? Is this some 3rd party library or are you the author?

@earlephilhower
Copy link
Collaborator

You've not given us an MCVE, either, so there's not much other than guessing we can do now.

FWIW, you've placed your IRQ handler in IRAM, which is good. But, have you placed all of whatever class TimerSSR is in IRAM as well? You need to have everything, all IRQ handlers and all functions/class members they call in IRAM or else you could get random crashes when an IRQ happens during a flash operation.

Also, if you have lfs_* in the stack trace it means you definitely have LittleFS linked in your application because something called it. So you may want to check on your statement that LFS is never called.

@GitHubLionel
Copy link
Author

Hi

Many thanks for your reply and to format my post (I used the correct quote but ....).
Yes, it is part of the whole code. But I have tested the rest separately and "normally", it is OK.
LittleFS is present because I store regularly some data (and also for the web page).
Timer_SSR is the class that encapsulate the timer1 access. All is in IRAM . Here is the code below.
Restart reason: 2
Exception cause: 0
Sorry but what is : MCVE ?
I think I respond to all your questions (and sorry for my poor English !!)

Timer_SSR class code :

 * TimerInterrupt class
 * For ESP8266 boards
 * Inspired of ESP8266TimerInterrupt.h written by Khoi Hoang
 */

#pragma once

#include <Arduino.h>

#define MAX_ESP8266_NUM_TIMERS      1
#define MAX_ESP8266_COUNT           8388607

typedef void (*timer_interrupt_cb)();

#define TIM_DIV1_CLOCK		(80000000UL)	// 80000000 / 1   = 80.0  MHz (80 ticks/us - 104857.588 us max)
#define TIM_DIV16_CLOCK		(5000000UL)	// 80000000 / 16  = 5.0   MHz (5 ticks/us - 1677721.4 us max)
#define TIM_DIV256_CLOCK	(312500UL)	// 80000000 / 256 = 312.5 KHz (1 tick = 3.2us - 26843542.4 us max)

#define TIM_CLOCK_FREQ        TIM_DIV16_CLOCK
#define TIM_DIV               TIM_DIV16

#define MIN_FREQ	((float) TIM_CLOCK_FREQ / MAX_ESP8266_COUNT)

/**
 * Class Timer using timer1 with interrupt
 * Call startTimer() to run the timer
 * ALWAYS stop the timer before any change !
 * Set interval in us and set frequency in hertz
 */
class TimerInterrupt
{
	private:
		timer_interrupt_cb _callback;		// pointer to the callback function
		float _frequency;       				// Timer frequency
		uint32_t _timerCount;      			// count to activate timer
		uint8_t _loop;            			// timer loop

	public:

		TimerInterrupt()
		{
			if (this->NbTimer == 1)
				throw("Only one timer");

			_frequency = 0;
			_timerCount = 0;
			_callback = NULL;
			_loop = TIM_LOOP;
			this->NbTimer++;
		}

		~TimerInterrupt()
		{
			timer1_disable();
			timer1_detachInterrupt();
		}

		// frequency (in hertz)
		bool IRAM_ATTR setFrequency(const float frequency_Hz)
		{
			// ESP8266 only has one usable timer1, max count is only 8,388,607. So to get longer time, we use max available 256 divider
			// Will use later if very low frequency is needed.

			if (frequency_Hz < MIN_FREQ)
			{
				return false;
			}

			_frequency = frequency_Hz;
			_timerCount = (uint32_t) (TIM_CLOCK_FREQ / frequency_Hz);

			if (_timerCount > MAX_ESP8266_COUNT)
			{
				_timerCount = MAX_ESP8266_COUNT;
				return false;
			}

			return true;
		}

		// frequency (in hertz)
		bool IRAM_ATTR setFrequency(const float frequency_Hz, const timer_interrupt_cb &callback,
				bool loop = true)
		{
			if (setFrequency(frequency_Hz))
			{
				_callback = callback;
				_loop = (uint8_t) loop;
				timer1_disable();
				timer1_attachInterrupt(callback);
				return true;
			}
			else
				return false;
		}

		// interval (in microseconds)
		bool IRAM_ATTR setInterval(const float interval_us)
		{
			return setFrequency(1000000.0f / interval_us);
		}

		// interval (in microseconds)
		bool IRAM_ATTR setInterval(const float interval_us, const timer_interrupt_cb &callback,
				bool loop = true)
		{
			return setFrequency(1000000.0f / interval_us, callback, loop);
		}

		void IRAM_ATTR setCallback(const timer_interrupt_cb &callback)
		{
			_callback = callback;
			timer1_disable();
			timer1_attachInterrupt(callback);
		}

		// set timer loop
		void IRAM_ATTR setTimerLoop(bool loop)
		{
			_loop = (uint8_t) loop;
		}

		// start the timer
		void IRAM_ATTR startTimer(void)
		{
			timer1_write(_timerCount);
			timer1_enable(TIM_DIV, TIM_EDGE, _loop);
		}

		// stop the timer. Just stop clock source, clear the count
		void IRAM_ATTR stopTimer(void)
		{
			timer1_disable();
		}

		void IRAM_ATTR detachInterrupt()
		{
			timer1_detachInterrupt();
		}

		void IRAM_ATTR reattachInterrupt()
		{
			if (_callback != NULL)
				timer1_attachInterrupt(_callback);
		}

		static uint8_t NbTimer;
};

uint8_t TimerInterrupt::NbTimer = 0;
// class TimerInterrupt

@GitHubLionel
Copy link
Author

GitHubLionel commented May 25, 2022

Hi again ;)

You give me an idea : I make this test :

  • I stop the data storage
  • then when I start the SSR process, no crash
  • then I try to access the LittleFS (try to load a web page) and I crash
    So the problem is the mix of the interrupt and LittleFS access.
    Here is 3 dumps of the crash of my test :
Restart reason: 2
Exception cause: 0
epc1=0x40228258 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

PC: 0x40228258
EXCVADDR: 0x00000000

Decoding stack results
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x401015b2: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 144
0x40101640: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266/interrupts.h line 29
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x40215a54: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x4021a435: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.2\cores\esp8266\flash_hal.cpp line 36
0x40100fd6: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402159d0: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x40215a57: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101638: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 167
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x40100fd6: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402159d0: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x40215a57: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101638: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 167
0x40220892: _printf_i at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c line 181
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x4010127c: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 37
0x401002b4: onTimerSSR() at E:\Sloeber\Sloeber_library\SSR\SSR.cpp line 120
0x401012c4: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 44
0x402019a4: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 964
0x402019f3: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 962
0x402020a4: lfs_bd_cmp at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 130
0x4021a435: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.2\cores\esp8266\flash_hal.cpp line 36
0x402119b6: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 171
0x40201330: lfs_bd_read at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 101
0x402018a2: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 891
0x40201e90: lfs_dir_find at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1238
0x402020f4: lfs_dir_find_match at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1140
0x40204262: lfs_file_rawopencfg at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 2472
0x40221380: _strdup_r at /workdir/repo/newlib/newlib/libc/string/strdup_r.c line 10
0x40100b64: malloc(size_t) at ...\esp8266\3.0.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 821
0x40204ce9: lfs_file_open at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 5058
0x40212269: littlefs_impl::LittleFSImpl::open(char const*, fs::OpenMode, fs::AccessMode) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 77
0x40207d15: esp8266webserver::ESP8266WebServerTemplate ::_parseRequest(WiFiClient&) at ...\esp8266\3.0.2\cores\esp8266/WString.h line 79
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101638: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 167
0x40215dee: fs::FS::open(char const*, char const*) at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr_base.h line 1324
0x4021c47b: String::len() const at ...\esp8266\3.0.2\cores\esp8266/WString.h line 263
0x40218165: String::concat(char const*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\WString.cpp line 309
0x4021861c: String::equals(String const&) const at ...\esp8266\3.0.2\cores\esp8266\WString.cpp line 492
0x40218250: String::concat(char const*) at ...\esp8266\3.0.2\cores\esp8266\WString.cpp line 317
0x40215e69: fs::FS::open(String const&, char const*) at ...\esp8266\3.0.2\cores\esp8266/WString.h line 277
0x40205b36: print_debug(String, bool) at ..\ESP12E_CS5480_LCD_TI_302.ino line 579
0x40218564: operator+(char const*, String const&) at ...\esp8266\3.0.2\cores\esp8266/WString.h line 133
0x4020ba34: handleListFile() at ...\esp8266\3.0.2\cores\esp8266/WString.h line 79
0x4021a9b1: uart_read(uart_t*, char*, size_t) at ...\esp8266\3.0.2\cores\esp8266\uart.cpp line 320
0x4021b64e: std::_Function_handler ::_M_invoke(std::_Any_data const&) at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 289
0x401000e1: std::function ::operator()() const at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 617
0x40206351: esp8266webserver::FunctionRequestHandler ::handle(esp8266webserver::ESP8266WebServerTemplate &, HTTPMethod, String const&) at ...\esp8266\3.0.2\libraries\ESP8266WebServer\src/detail/RequestHandlersImpl.h line 42
0x40208e78: esp8266webserver::ESP8266WebServerTemplate ::_handleRequest() at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 498
0x40209632: esp8266webserver::ESP8266WebServerTemplate ::handleClient() at ...\esp8266\3.0.2\libraries\ESP8266WebServer\src/ESP8266WebServer-impl.h line 274
Crash # 1 at 1571414 ms
Restart reason: 2
Exception cause: 0
epc1=0x40228574 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

PC: 0x40228574
EXCVADDR: 0x00000000

Decoding stack results
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101638: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 167
0x4010127c: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 37
0x401002af: onTimerSSR() at E:\Sloeber\Sloeber_library\SSR\SSR.cpp line 120
0x401012c4: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 44
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x40100fd6: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402159d0: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x40215a57: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40100fd6: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x4022041c: _printf_common at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c line 72
0x402159d0: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x40220a09: _printf_i at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c line 243
0x40215a57: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x4022543c: __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 182
0x40101654: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101638: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 167
0x40101578: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x402011aa: lfs_bd_read at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 32
0x402019c4: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 964
0x4020193d: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 921
0x402020a4: lfs_bd_cmp at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 130
0x4021a435: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.2\cores\esp8266\flash_hal.cpp line 36
0x402119b6: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 171
0x40201330: lfs_bd_read at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 101
0x402018a2: lfs_dir_fetchmatch at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 891
0x4022fff4: etharp_output_to_arp_index at core/ipv4/etharp.c line 769
0x40201e90: lfs_dir_find at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1238
0x402020f4: lfs_dir_find_match at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1140
0x4021901f: __yield() at ...\esp8266\3.0.2\cores\esp8266/core_esp8266_features.h line 65
0x40204262: lfs_file_rawopencfg at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 2472
0x40221380: _strdup_r at /workdir/repo/newlib/newlib/libc/string/strdup_r.c line 10
0x40100b64: malloc(size_t) at ...\esp8266\3.0.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 821
0x40204ce9: lfs_file_open at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 5058
0x40212269: littlefs_impl::LittleFSImpl::open(char const*, fs::OpenMode, fs::AccessMode) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 77
0x40100b64: malloc(size_t) at ...\esp8266\3.0.2\cores\esp8266\umm_malloc\umm_malloc.cpp line 821
0x40215dee: fs::FS::open(char const*, char const*) at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr_base.h line 1324
0x40218165: String::concat(char const*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\WString.cpp line 309
0x40218250: String::concat(char const*) at ...\esp8266\3.0.2\cores\esp8266\WString.cpp line 317
0x40215e69: fs::FS::open(String const&, char const*) at ...\esp8266\3.0.2\cores\esp8266/WString.h line 277
0x40205b36: print_debug(String, bool) at ..\ESP12E_CS5480_LCD_TI_302.ino line 579
0x40218564: operator+(char const*, String const&) at ...\esp8266\3.0.2\cores\esp8266/WString.h line 133
0x4020c0e8: handleSetTime() at ...\esp8266\3.0.2\cores\esp8266/WString.h line 79
0x4021b64e: std::_Function_handler ::_M_invoke(std::_Any_data const&) at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 289
0x401000e1: std::function ::operator()() const at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 617
0x40206351: esp8266webserver::FunctionRequestHandler ::handle(esp8266webserver::ESP8266WebServerTemplate &, HTTPMethod, String const&) at ...\esp8266\3.0.2\libraries\ESP8266WebServer\src/detail/RequestHandlersImpl.h line 42
0x40208e78: esp8266webserver::ESP8266WebServerTemplate ::_handleRequest() at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 498
0x40209632: esp8266webserver::ESP8266WebServerTemplate ::handleClient() at ...\esp8266\3.0.2\libraries\ESP8266WebServer\src/ESP8266WebServer-impl.h line 274

Crash # 1 at 162922 ms
Restart reason: 2
Exception cause: 0
epc1=0x40227f2c epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

PC: 0x40227f2c
EXCVADDR: 0x00000000

Decoding stack results
0x40100219: onZC() at E:\Sloeber\Sloeber_library\SSR\SSR.cpp line 158
0x4010158e: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 144
0x4010161c: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266/interrupts.h line 29
0x40101554: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 138
0x402156b8: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 951
0x40215757: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40100faa: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402156d0: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x40100faa: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x4020211a: lfs_dir_find_match at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1150
0x402156d0: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x40215757: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40101630: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 175
0x40101614: interrupt_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 167
0x40101a74: _stopPWM(uint8_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_waveform_pwm.cpp line 264
0x401014b8: __digitalWrite(uint8_t, uint8_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 87
0x40101250: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 37
0x40100294: onTimerSSR() at E:\Sloeber\Sloeber_library\SSR\SSR.cpp line 120
0x40101298: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 44
0x40201688: lfs_dir_getslice at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 620
0x40201624: lfs_dir_getslice at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs_util.h line 187
0x4021a135: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.2\cores\esp8266\flash_hal.cpp line 36
0x402116b6: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 171
0x40201330: lfs_bd_read at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 101
0x4021a135: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.2\cores\esp8266\flash_hal.cpp line 36
0x402116b6: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 171
0x40201330: lfs_bd_read at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 101
0x40201619: lfs_dir_getslice at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 601
0x4020a7e0: getContentType(String const&) at E:\Sloeber\Sloeber_library\Server_utils\Server_utils.cpp line 774
0x40201718: lfs_dir_get at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 644
0x40201f24: lfs_dir_getinfo at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1119
0x40204be4: lfs_stat at ...\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 4992
0x402113e8: littlefs_impl::LittleFSImpl::exists(char const*) at ...\esp8266\3.0.2\libraries\LittleFS\src/LittleFS.h line 99
0x4021bd94: fs::FS::exists(char const*) at ...\esp8266\3.0.2\cores\esp8266\FS.cpp line 379
0x4021598a: fs::FS::exists(String const&) at ...\esp8266\3.0.2\cores\esp8266/WString.h line 277
0x4020b284: handleReadFile(String const&) at ...\esp8266\3.0.2\cores\esp8266/WString.h line 79
0x4021a6b1: uart_read(uart_t*, char*, size_t) at ...\esp8266\3.0.2\cores\esp8266\uart.cpp line 320
0x4021a622: uart_read(uart_t*, char*, size_t) at ...\esp8266\3.0.2\cores\esp8266\uart.cpp line 295
0x4020b84d: std::_Function_handler   >::_M_invoke(const std::_Any_data &) at ...\esp8266\3.0.2\libraries\ESP8266WebServer\src/ESP8266WebServer.h line 126
0x401000e1: std::function ::operator()() const at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 617
0x40208e75: esp8266webserver::ESP8266WebServerTemplate ::_handleRequest() at e:\logiciel\sloeber\arduinoplugin\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h line 498
0x4020961e: esp8266webserver::ESP8266WebServerTemplate ::handleClient() at ...\esp8266\3.0.2\libraries\ESP8266WebServer\src/ESP8266WebServer-impl.h line 274

@GitHubLionel
Copy link
Author

Hi again !!!

I have made a simple sketch that produce the crash.
All you need is the EspSaveCrash library and my TimerInterrupt class (see below post).

Just run the sketch on a Wemos and wait a little for the crash ! lol

The Interrupt_Crash.ino sketch and the dump :

#include "Arduino.h"
#include <LittleFS.h>

// For the dump crash
#define USE_SAVE_CRASH
// To store the crash in file
//#define LOG_DEBUG

#ifdef USE_SAVE_CRASH
#include "EspSaveCrash.h"
#endif

#include "Timer_utils.h"

#ifdef USE_SAVE_CRASH
EspSaveCrash SaveCrash(0x0010, 0x0800);
#endif

// ********************************************************************************
// SSR variables
// ********************************************************************************

// Le timer avec interruption qui pilote le SSR
TimerInterrupt Timer_SSR;
uint8_t SSR_PIN;
int8_t LED_PIN = -1;
bool Top_CS_ZC = false;
uint32_t Count_CS_ZC = 0;
volatile bool Tim_Interrupt_Enabled = false;
// Indique si le SSR est activé ou pas
volatile bool Is_SSR_enabled = false;

#define SSR_TURN_ON_us    50      // Temps nécessaire au SSR pour démarrer en us
volatile float SSR_COUNT = 5000.0;  // 50%

// ********************************************************************************
// Callback
// ********************************************************************************

//#define USE_DIRECT_PIN

#ifdef USE_DIRECT_PIN
#define SET_PIN_HIGH(pin)	GPOS = (1 << (pin))  // set pin HIGH
#define SET_PIN_LOW(pin)	GPOC = (1 << (pin))  // set pin LOW
#endif

// Send SSR pulse after delay
void IRAM_ATTR onTimerSSR(void)
{
	if (Is_SSR_enabled)
	{
		if (Top_CS_ZC)
		{
#ifdef USE_DIRECT_PIN
			SET_PIN_HIGH(SSR_PIN);
#else
			digitalWrite(SSR_PIN, HIGH);
#endif
			Top_CS_ZC = false;
//			Timer_SSR.stopTimer();
			Timer_SSR.setInterval(SSR_TURN_ON_us);
			Timer_SSR.startTimer();
		}
		else
		{
#ifdef USE_DIRECT_PIN
			SET_PIN_LOW(SSR_PIN);
#else
			digitalWrite(SSR_PIN, LOW);
#endif
			if (LED_PIN != -1)
#ifdef USE_DIRECT_PIN
				SET_PIN_HIGH(LED_PIN);
#else
				digitalWrite(LED_PIN, HIGH);
#endif
		}
	}
}

// Zero cross was fired
// Note : on est obligé de redéfinir l'interval à chaque fois car il est modifié
// à chaque fois même si New_Timer_Parameters est false
void IRAM_ATTR onZC(void)
{

	if (Is_SSR_enabled && Tim_Interrupt_Enabled)
	{
		if (LED_PIN != -1)
#ifdef USE_DIRECT_PIN
			SET_PIN_LOW(LED_PIN);
#else
			digitalWrite(LED_PIN, LOW);
#endif

		Top_CS_ZC = true;
//	Timer_SSR.stopTimer();
		Timer_SSR.setInterval(SSR_COUNT);
		Timer_SSR.startTimer();
	}
}

// ********************************************************************************
// SSR part
// ********************************************************************************

// Les pins
#define SSR_COM_PIN		D8
#define LED_SSR_PIN	D3
#define ZC_PIN	D6

void SSR_Init(uint8_t ZC_Pin, uint8_t SSR_Pin, int8_t LED_Pin)
{
	// This code is for real life with a real ZC pin
	/*
	// interruption zero-cross Cirrus
	// Zero cross pin INPUT_PULLUP
	pinMode(ZC_Pin, INPUT_PULLUP);
	// Pilotage du timer SSR
	attachInterrupt(digitalPinToInterrupt(ZC_Pin), onZC, RISING);
	*/

	// Initialisation timer SSR
	// Au top du zéro-cross, attend SSR_COUNT us pour lancer le pulse SSR
	SSR_PIN = SSR_Pin;
	digitalWrite(SSR_Pin, LOW);
	pinMode(SSR_Pin, OUTPUT);
	digitalWrite(SSR_Pin, LOW);
	Timer_SSR.setInterval((float) SSR_COUNT, onTimerSSR, false);
	Tim_Interrupt_Enabled = true;

	// Led associé au SSR
	LED_PIN = LED_Pin;
	if (LED_PIN != -1)
	{
		digitalWrite(LED_PIN, LOW);
		pinMode(LED_PIN, OUTPUT);
		digitalWrite(LED_PIN, LOW);
	}
}

void SSR_Enable(void)
{
	Is_SSR_enabled = true;
}

// ********************************************************************************
// Setup / Loop
// ********************************************************************************

#ifdef USE_SAVE_CRASH
void print_crash(void)
{
	SaveCrash.print();

#ifdef LOG_DEBUG
	File temp = LittleFS.open("Crash_dump.txt", "w");
	if (temp)
	{
		SaveCrash.print(temp);
		temp.close();
	}
#endif
	SaveCrash.clear();
}
#endif

// Just to access LittleFS
void LittleFS_Crash()
{
	File file = LittleFS.open("Crash.log", "w");
	if (file)
	{
		file.print("Blabla \r\n");
		file.close();
	}
}

bool First = true;
uint32_t Count_ZC = 0;
uint32_t Count_seconde = 0;

//The setup function is called once at startup of the sketch
void setup()
{
// Add your initialization code here

	// To have time to connect serial
	delay(5000);

	// **** 0- initialisation Serial ****
  Serial.begin(115200);
  delay(100);  // Pour stabiliser UART

	// **** 1- initialisation LittleFS ****
	// Start the SPI Flash Files System, abort if not success
	if (!LittleFS.begin())
	{
		// On abandonne l'initialisation
		return;
	}

#ifdef USE_SAVE_CRASH
	// Sauvegarde du log d'un éventuel crash
	print_crash();
#endif

	// **** 2- Initialisation SSR avec Zero-Cross ****
	SSR_Init(ZC_PIN, SSR_COM_PIN, LED_SSR_PIN);

	// ZC simulation
	Count_ZC = millis();

	// For write to file
	Count_seconde = millis();
}

// The loop function is called in an endless loop
void loop()
{
//Add your repeated code here

	// Start the SSR process
	if (First)
	{
		SSR_Enable();
		First = false;
	}

	// ZC simulation
	if (millis() - Count_ZC > 10)
	{
		Count_ZC = millis();
		onZC();
	}

	if (millis() - Count_seconde > 1000)
	{
		Count_seconde = millis();
		Serial.print("1 seconde more ... \r\n");
		LittleFS_Crash();
	}
}

PC: 0x402142a4
EXCVADDR: 0x00000000

Decoding stack results
0x40100cfc: __digitalWrite(uint8_t, uint8_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 87
0x40100aa4: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 37
0x401001df: onTimerSSR() at ..\Interrupt_Crash.ino line 69
0x40100aec: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 44
0x401009f8: ets_post(uint8, ETSSignal, ETSParam) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_main.cpp line 181
0x40100a5e: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402078a4: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x4020792b: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40100cfc: __digitalWrite(uint8_t, uint8_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_wiring_digital.cpp line 87
0x40100a5e: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x40100a5e: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402078a4: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x4020792b: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40100a5e: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402078a4: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x4020792b: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x40100a5e: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402078a4: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 954
0x4020792b: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266\Esp.cpp line 933
0x402020a4: lfs_bd_cmp at ...\esp8266\hardware\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 130
0x40209151: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.2\cores\esp8266\flash_hal.cpp line 36
0x40205f6e: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 171
0x40201330: lfs_bd_read at ...\esp8266\hardware\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 101
0x402019c4: lfs_dir_fetchmatch at ...\esp8266\hardware\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 964
0x40205f6e: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 171
0x40100aec: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 44
0x40201e90: lfs_dir_find at ...\esp8266\hardware\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1238
0x402020f4: lfs_dir_find_match at ...\esp8266\hardware\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 1140
0x40204262: lfs_file_rawopencfg at ...\esp8266\hardware\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 2472
0x40100aec: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_timer.cpp line 44
0x40204ce9: lfs_file_open at ...\esp8266\hardware\esp8266\3.0.2\libraries\littlefs\lib\littlefs/lfs.c line 5058
0x40206821: littlefs_impl::LittleFSImpl::open(char const*, fs::OpenMode, fs::AccessMode) at ...\esp8266\3.0.2\libraries\LittleFS\src\LittleFS.cpp line 77
0x40205620: loop() at ..\Interrupt_Crash.ino line 238
0x40205616: loop() at ..\Interrupt_Crash.ino line 238
0x40207b7a: fs::FS::open(char const*, char const*) at ...\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr_base.h line 1324
0x40100a5e: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_phy.cpp line 309
0x402098bc: uart_write(uart_t*, char const*, size_t) at ...\esp8266\3.0.2\cores\esp8266\uart.cpp line 546
0x4020558c: LittleFS_Crash() at ..\Interrupt_Crash.ino line 179
0x40207d34: HardwareSerial::write(unsigned char const*, unsigned int) at ...\esp8266\3.0.2\cores\esp8266/HardwareSerial.h line 193
0x40207ed8: Print::write(char const*) at ...\esp8266\3.0.2\cores\esp8266/Print.h line 59
0x40207efc: Print::write(char const*) at ...\esp8266\3.0.2\cores\esp8266/Print.h line 57
0x40207ff0: Print::print(char const*) at ...\esp8266\3.0.2\cores\esp8266\Print.cpp line 121
0x40205659: loop() at ..\Interrupt_Crash.ino line 248
0x4020872c: loop_wrapper() at ...\esp8266\3.0.2\cores\esp8266\core_esp8266_main.cpp line 201

@themindfactory
Copy link
Contributor

themindfactory commented May 25, 2022 via email

@GitHubLionel
Copy link
Author

The goal is not to use another library ! ;)
My code work nicely with core 2.7.4, the question is why it does not work with 3.0.2 ?
The small sketch I made show the crash.

@GitHubLionel
Copy link
Author

GitHubLionel commented May 26, 2022

Hi,

I also test with core 3.0.0 and I have the same crash. I also test with Arduino IDE (I have 1.8.13), same crash.
So, there are something important change between 2.7.4 and 3.0.0 that break the code. I tried to compare the two cores but there are too many changes.
Could you reproduce the problem with my sketch and class TimerInterrupt below ?

Core dump for 3.0.0 :


Exception 0: Illegal instruction
PC: 0x4020a38c
EXCVADDR: 0x00000000

Decoding stack results
0x40100cfc: __digitalWrite(uint8_t, uint8_t) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_wiring_digital.cpp line 86
0x40100aa8: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_timer.cpp line 37
0x401001ef: onTimerSSR() at ..\Interrupt_Crash.ino line 76
0x40100af0: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_timer.cpp line 44
0x40100a62: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_phy.cpp line 309
0x40207844: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.0\cores\esp8266\Esp.cpp line 954
0x402078cb: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.0\cores\esp8266\Esp.cpp line 933
0x40100a62: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_phy.cpp line 309
0x40207844: EspClass::flashRead(unsigned int, unsigned int*, unsigned int) at ...\esp8266\3.0.0\cores\esp8266\Esp.cpp line 954
0x402078cb: EspClass::flashRead(unsigned int, unsigned char*, unsigned int) at ...\esp8266\3.0.0\cores\esp8266\Esp.cpp line 933
0x40100d04: __digitalWrite(uint8_t, uint8_t) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_wiring_digital.cpp line 87
0x40100aa8: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_timer.cpp line 37
0x401001e8: onTimerSSR() at ..\Interrupt_Crash.ino line 67
0x40100af0: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_timer.cpp line 44
0x4020122e: lfs_bd_read at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 62
0x402019c4: lfs_dir_fetchmatch at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 964
0x40209119: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.0\cores\esp8266\flash_hal.cpp line 36
0x40205f26: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.0\libraries\LittleFS\src\LittleFS.cpp line 171
0x40201330: lfs_bd_read at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 101
0x40100a62: __wrap_spi_flash_read(uint32_t, uint32_t*, size_t) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_phy.cpp line 309
0x402020a4: lfs_bd_cmp at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 130
0x40209119: flash_hal_read(unsigned int, unsigned int, unsigned char*) at ...\esp8266\3.0.0\cores\esp8266\flash_hal.cpp line 36
0x40205f26: littlefs_impl::LittleFSImpl::lfs_flash_read(lfs_config const*, unsigned int, unsigned int, void*, unsigned int) at ...\esp8266\3.0.0\libraries\LittleFS\src\LittleFS.cpp line 171
0x40201330: lfs_bd_read at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 101
0x402018a2: lfs_dir_fetchmatch at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 891
0x40201e90: lfs_dir_find at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 1238
0x402020f4: lfs_dir_find_match at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 1140
0x40100aa8: timer1_isr_handler(void*, void*) at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_timer.cpp line 37
0x40204262: lfs_file_rawopencfg at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 2472
0x40204ce9: lfs_file_open at ...\esp8266\3.0.0\libraries\littlefs\lib\littlefs/lfs.c line 5058
0x402067c5: littlefs_impl::LittleFSImpl::open(char const*, fs::OpenMode, fs::AccessMode) at ...\esp8266\3.0.0\libraries\LittleFS\src\LittleFS.cpp line 77
0x40207b42: fs::FS::open(char const*, char const*) at e:\logiciel\sloeber\arduinoplugin\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
0x401004db: umm_free_core(umm_heap_context_t*, void*) at ...\esp8266\3.0.0\cores\esp8266\umm_malloc\umm_malloc.cpp line 549
0x40209884: uart_write(uart_t*, char const*, size_t) at ...\esp8266\3.0.0\cores\esp8266\uart.cpp line 546
0x40205649: LittleFS_Crash() at ..\Interrupt_Crash.ino line 177
0x40207cfc: HardwareSerial::write(unsigned char const*, unsigned int) at ...\esp8266\3.0.0\cores\esp8266/HardwareSerial.h line 193
0x40207ea0: Print::write(char const*) at ...\esp8266\3.0.0\cores\esp8266/Print.h line 59
0x40207ec4: Print::write(char const*) at ...\esp8266\3.0.0\cores\esp8266/Print.h line 57
0x40207fb8: Print::print(char const*) at ...\esp8266\3.0.0\cores\esp8266\Print.cpp line 121
0x40205725: loop() at ..\Interrupt_Crash.ino line 246
0x402086f4: loop_wrapper() at ...\esp8266\3.0.0\cores\esp8266\core_esp8266_main.cpp line 201

@mhightower83
Copy link
Contributor

It is interesting that the crash location for exception 0 is at the start of the __ltsf2 library function which executes from flash.
It looks like the interrupt handler logic flow does have a float test. This might work for a while until the interrupt handler bumps into busy flash hardware. Most likely LittleFS doing read/writes. Well, that is my best guess.

@GitHubLionel
Copy link
Author

Hi mhightower83,

Thanks for your attention of my problem :)
So, what is the solution to avoid this problem ? Shall I modify something in the LittleFS code ?
Best regards,
Lionel

@mhightower83
Copy link
Contributor

I would switch to using integers in the ISR code.
Avoid floats since their supporting libraries are very likely not in IRAM.
Since interrupts are disabled in an ISR. In an ISR handler, you want to avoid a long execution time. Float operations will add more execution time than integers.
I think this problem would arise with any code that is interrupted while doing FLASH read/writes. IMO, through this example, LittleFS was doing it more often allowing the issue to show.

@GitHubLionel
Copy link
Author

Hi,

Ok, I switch to uint32_t in place of float.
Result : I have crash with core 3.0.0 but no crash with core 3.0.2. After investigation, I found a correction in core 3.0.2 about _stopPWM that was not in IRAM in core 3.0.0.
I try with my real project and no crash :)
So problem is solved 👍
Stay the mystery : why my code worked with core 2.7.4 ....
Thanks again,
Lionel

@GitHubLionel
Copy link
Author

GitHubLionel commented May 31, 2022

I have another question : In the interrupt, I use some variables (SSR_PIN, LED_PIN, Top_CS_ZC, ...).
What is the best to declare them : static, volatile, "normal" ?
I guess "static" and "volatile" if we have a risk to access to the variable same time in different place.
Is it possible to use the directive IRAM_ATTR with variables ?

@mhightower83
Copy link
Contributor

If a variable is read-only by the ISR, there is no need for special treatment by the compiler.

For volatile, there are nuances that I may not capture in my description. If you do an Internet search on "volatile C++" I think you will get a deeper understanding. For variables written from an ISR and main code, I use volatile. This reduces the assumptions made by the compiler when accessing the storage element. Generally speaking, less caching of the data into registers and more rereading the value before use.

I don't see a requirement for static in an ISR other than to create long lived private storage.

Is it possible to use the directive IRAM_ATTR with variables ?"

Yes. However, IRAM is generally in short supply compared to DRAM and brings additional access restrictions the compiler will not handle. For data access, it will be a little slower than DRAM and access is restricted to aligned 32 bit words. I see it as an option when DRAM is running critically low, and you can sacrifice a little speed and IRAM from the cache for more storage. See https://arduino-esp8266.readthedocs.io/en/latest/mmu.html for more details on using IRAM for data storage.

@mcspr
Copy link
Collaborator

mcspr commented Jun 1, 2022

Note that floating point functions are in flash since 2.7.0
#7180
#7188 (can be moved back to IRAM with build flag)

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

No branches or pull requests

5 participants