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]