FelipeMdeO opened a new pull request, #20223:
URL: https://github.com/apache/nuttx/pull/20223

   ## Summary
   
   `up_idlepm()` (`arch/xtensa/src/esp32s3/esp32s3_idle.c`) put the domain
   back in PM_NORMAL with `pm_changestate()` but left its local `oldstate`
   holding whatever it was before sleeping, usually PM_STANDBY. The
   `pm_checkstate()` call right below then returned PM_STANDBY again, the
   `newstate != oldstate` test compared PM_STANDBY against a stale
   PM_STANDBY, and the whole block was skipped — including the
   `esp_pmstandby()` call that is the only thing here that ever sleeps.
   
   So after the very first wakeup the board reported PM_NORMAL essentially
   forever, and light-slept only when something else happened to perturb
   `oldstate` (e.g. an application taking and releasing a PM_IDLE wakelock).
   
   Fix: explicitly set `oldstate = PM_NORMAL` right after `pm_relax()`,
   recording that the domain really is in PM_NORMAL now. The dead
   `newstate = PM_NORMAL` assignment that used to sit here was presumably
   meant to be this — it is overwritten by `pm_checkstate()` a few lines
   below and never had any effect.
   
   Related NuttX Issue: none filed yet.
   
   ## Impact
   
   * Is new feature added? No — pure bug fix.
   * Is existing feature changed? No behavior change for configs that never
     hit the leaking branch (anything not combining `CONFIG_PM` +
     `CONFIG_SCHED_TICKLESS`). For configs that do, this restores the ability
     to reach light sleep after the very first wakeup event, instead of only
     once.
   * Impact on hardware? `arch/xtensa/src/esp32s3/esp32s3_idle.c` only —
     esp32s3 boards using `CONFIG_PM` + `CONFIG_SCHED_TICKLESS`.
   
   ## Testing
   
   I confirm that changes are verified on local setup and works as intended:
   
   * Build Host: Ubuntu 24.04, x86_64, `xtensa-esp-elf-gcc` (crosstool-NG
     esp-14.2.0_20241119, 14.2.0).
   * Target: Xtensa, Seeed XIAO ESP32-S3 (esp32s3-xiao), out-of-tree
     defconfig with `CONFIG_PM=y`, `CONFIG_SCHED_TICKLESS=y`,
     `CONFIG_ESPRESSIF_WIFI=y`, MQTT collar application.
   
   Before the fix: 4.1 s of actual light sleep in 2 h of near-total
   idleness — a 1780:1 awake-to-asleep ratio.
   
   After the fix, corroborated across a 12 h 25 continuous production run:
   93% of wall time in PM_STANDBY (light sleep), 1 s awake-within-standby
   over the whole run, zero faults.
   
   Caveat worth stating: that 93% figure requires `CONFIG_DEBUG_INFO` off.
   `up_idlepm()`'s own `_info()` print runs inside `spin_lock_irqsave()` on
   every state change, and with debug output on the same board measures
   11.8% asleep — the instrument dominates the measurement. A reviewer
   reproducing with debug logging enabled will not see the 93% number.
   
   Fixing this is what exposed two further, independent bugs that had been
   dormant behind a board that never actually slept — the systimer
   double-counting sleep time, and I2C transfers being cut in half by sleep.
   Both are proposed as separate PRs.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to