mirror of
https://github.com/meshtastic/firmware.git
synced 2026-11-08 07:15:22 -05:00
Latch the LoRa IRQ skip-sleep give-up until the line is seen low
doLightSleep() skips a light sleep when the LoRa IRQ line is already asserted, and bounds that to LORA_IRQ_SKIP_SLEEP_MAX consecutive skips so a line stuck high cannot stop the node sleeping for good. But the counter was reset on the sleep it finally allowed, so the bound never stuck: a genuinely stuck-high line produced five skips, one sleep, five skips, one sleep, for as long as it stayed high. Each of those skipped attempts is not free. It runs waitEnterSleep() and the full notifyLightSleep / notifyLightSleepEnd observer pass, which detaches, arms and restores every wake pin - the path #12100 and #12131's interrupt storm live on - so the loop costs far more than the sleep it is protecting. Reset the counter only when the line is actually read low, which is the condition that says the radio is clearing its IRQs again. Nothing changes for the transient case the skip exists for: the line goes low as soon as the main loop services the packet, and the next sleep clears the count. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTiifXrVc4YdonmLRCeWhw
This commit is contained in:
1 parent
aa405226c2
commit
c85cc0a5ed
1 file changed
+9
-2
+9
-2
@@ -579,7 +579,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
assert(res == ESP_OK);
|
||||
|
||||
console->flush();
|
||||
const bool loraIrqPending = loraWakeIrqAsserted() && loraIrqSkippedSleeps < LORA_IRQ_SKIP_SLEEP_MAX;
|
||||
const bool loraIrqAsserted = loraWakeIrqAsserted();
|
||||
const bool loraIrqPending = loraIrqAsserted && loraIrqSkippedSleeps < LORA_IRQ_SKIP_SLEEP_MAX;
|
||||
if (loraIrqPending) {
|
||||
// A LoRa IRQ is already pending (see loraWakeIrqAsserted). Don't sleep on top of it - return so
|
||||
// the main loop services the packet now instead of stranding it until the next wake.
|
||||
@@ -591,7 +592,13 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
} else {
|
||||
// Either nothing pending, or the line has stayed high past LORA_IRQ_SKIP_SLEEP_MAX and the main
|
||||
// loop is clearly not going to clear it. Never sleeping costs more than one stranded packet.
|
||||
loraIrqSkippedSleeps = 0;
|
||||
//
|
||||
// Only reset the count once the line is seen low again. Resetting on every sleep we allow made a
|
||||
// stuck-high line give LORA_IRQ_SKIP_SLEEP_MAX skips, one sleep, repeat, forever - and each
|
||||
// skipped attempt still runs waitEnterSleep() and the whole notifyLightSleep/End pass, which
|
||||
// detaches, arms and restores every wake pin. Once we have given up, stay given up.
|
||||
if (!loraIrqAsserted)
|
||||
loraIrqSkippedSleeps = 0;
|
||||
res = esp_light_sleep_start();
|
||||
}
|
||||
if (res != ESP_OK) {
|
||||
|
||||
Reference in new issue
Block a user