Heltec ESP32 WiFi LoRa v2 freezes

Hello everyone,

I have a project based on the Heltec ESP32 WiFi LoRa v2, the goal is to acquire some commands from our remote server and sent commands to nodes via LoRa. Nodes are designed for being powered by a battery pack charged by a solar panel.
The nodes are giving us some trouble.

The big problem is that the nodes freeze, sometime after 10 hours, and sometimes after a week, it happens at random times.

Do you have any suggestions? External reset? I don’t know what to do next.

Thank you for your help

What do you mean by freezing? Is the program stuck?

Hi, @navi thanks for the response. ESP32 freezing means that nothing is in the serial monitor and nothing is on display and it starts working only after reset. I don’t think that its program is stuck because it’s happening not for all ESP32.

Use the internal watchdog to see if this will happen.

It is not freezing, it is sleeping for an long time - precisely the uptime subtracted from 2^16 seconds, and it is caused by the timer architecture involving two timers which don’t latch correctly. But there is a fix, and here it is.

  1. Always set the duty cycle to a multiple of 2 seconds. Any randomisation also a multiple of 2s.
  2. Wait for LoRaMacState != LORAMAC_IDLE before before LoRaWAN.sleep();

The bug is that Asr_Timer_Disable does not disarm the ISR. CySysTimerDisable stops the counters. CySysTimerDisableIsr would remove Timer1
from the interrupt controller’s active vector table — but it is not called.
Timer1’s ISR vector remains armed.

Because Timer1 has ClearOnMatch, when it reaches its match value it does not
stop — it resets its counter to zero and immediately begins counting toward the
next match.

The race condition that follows when g_timeout != 0:

  1. Timer1 reaches its match. Timer1IsrCallback fires.
  2. g_timeout != 0, so it calls Asr_SetTimeout(g_timeout).
  3. Stage 2 calls Asr_Timer_Disable() — Timer1 counters reset, ISR still armed.
  4. Stage 2 configures Timer0 for the short remainder and enables Timer0 only.
  5. Timer1, now reset and counting again with ISR still armed, reaches its
    match value a second time.
  6. Timer1IsrCallback fires again. This time g_timeout is 0. The callback sees zero and calls
    timerAlarmCallback() — before Timer0 has fired.
  7. The wakeup event is consumed and discarded. No new alarm is queued.

The device calls CySysPmDeepSleep() with no valid wakeup alarm armed.

I found out about this because there was a relationship between the deep sleep time and the elapsed time since the device was reset.

It’s ESP32, not ASR.

Plus the thread, being 3 years old, relates to a product barely available anymore.