Make device shutdown fail-safe - #281
Open
TobiasRoeddiger wants to merge 3 commits into
Open
TobiasRoeddiger wants to merge 3 commits into
TobiasRoeddiger wants to merge 3 commits into
Conversation
|
Build output available: |
TobiasRoeddiger
force-pushed
the
codex/shutdown-gpio-failure
branch
from
September 17, 2026 03:52
3347ab5 to
c4f0a61
Compare
|
Build output available: |
TobiasRoeddiger
force-pushed
the
codex/shutdown-gpio-failure
branch
from
September 17, 2026 04:11
c4f0a61 to
f4e3ddc
Compare
|
Build output available: |
|
Build output available: |
|
Build output available: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A button or automatic shutdown must either enter charging-only mode while USB is present or reach nRF System OFF on battery. On
main, several shutdown operations could fail, block forever, assert, or choose the wrong USB branch. Because the status LED was turned off early, any of those failures could leave the application and peripheral rails powered while the device appeared off.This PR makes that shutdown sequence fail-safe. Normal shutdown still tries to stop sensors, finish the SD log, stop the DAC, and turn off the LED cleanly. A retained shutdown marker and a 30-second guard prevent those optional cleanup steps from keeping the device powered indefinitely. If cleanup stalls or asserts, the rebooted firmware detects the marker, skips all optional teardown and I2C access, drives the switched rails low directly, and enters System OFF. With USB connected, the same marker selects charging-only operation until the user explicitly starts the application or unplugs USB.
Failure handling
PowerManager::power_down()insrc/Battery/PowerManager.cpp; marker insrc/Battery/BootState.hpower_on = true, so rebooting to escape a failed shutdown would start the application again.PowerManager::begin()andPowerManager::power_down()error_handler()insrc/utils/error_handler.cpower_down(). System OFF or the charging reset already terminates the radio and connections.PowerManager::power_down()stop_sensor_manager()call inPowerManager::power_down()-ENOSPC, release the ring-buffer claim, and return. Still close the file so already-written data and metadata can be synced before shutdown continues.SDLogger::flush()andSDLogger::end()insrc/SD_Card/SDLogger/SDLogger.cppPowerManager::power_down()LOG_PANIC()synchronously drains the logging backend and can wait indefinitely for UART output. Logs are not required for System OFF.LOG_PANIC()from the shutdown path.PowerManager::power_down()PowerManager::power_down()PowerManager::power_down()gpio_pin_get_dt()returns a negative error code on failure. Converting that value directly toboolreported USB as present and selected the charging-reset path indefinitely./PGreading as connected; log a read error and fail toward battery/System OFF.BQ25120a::power_connected()insrc/Battery/BQ25120a.cpppower_down()before rails were disabled and before System OFF./PGand/INTremain the intended button/USB wake sources.PowerManager::power_down()GPOUTwas enabled as a level wake source even though gauge events cannot perform useful work while the application is off. It could wake the nRF into an apparently-off application state.GPOUTbefore System OFF. Gauge interrupts remain active while the application runs; button and USB wake remain available through the charger.BQ27220::disable_wakeup_int()andPowerManager::power_down()set_load_switch(),generic_pm_control(), andopenearable_power_rails_off()inboards/teco/openearable_v2/board_init.c;PowerManager::power_down()power_onfalse, and zero-initialize the status state. A button press explicitly clears the request and starts the application.PowerManager::begin()andPowerManager::power_down()sys_poweroff(), butsys_poweroff()is declared non-returning, so that code was unreachable.sys_poweroff()andCODE_UNREACHABLE; recovery is handled before that point by the guard and retained marker.PowerManager::power_down()Why the fuel-gauge interrupt is disabled only while off
While the application runs, BQ27220 events are useful: the callback publishes charge state and starts orderly low-voltage shutdown. They are not useful after System OFF because no application remains to consume them and the nRF cannot charge the cell. With the retained gauge defaults,
GPOUTcan pulse for state-of-charge changes andBatteryStatus()[SYSDWN]; the firmware programs theSYSDWNset threshold to 3.25 V and clear threshold to 3.35 V. Disabling only the nRF GPIO interrupt before System OFF prevents those events from waking an intentionally off device. See the BQ27220 Technical Reference Manual, Table 4-6.If charger wake setup itself fails, the firmware still enters System OFF instead of leaving the application running. A long button press remains the hardware reset recovery path on v2.7 through the BQ25120A-to-nRF
RESETNconnection.Validation and scope
openearable_v2/nrf5340/cpuappsucceeds, including MCUboot, application core, network core, merged images, anddfu_application.zip.