-
Notifications
You must be signed in to change notification settings - Fork 412
nRF52840 Power Management v2 Phase 1 - LPCOMP Wake and startup lockout #1413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
Added src/helpers/nrf52/Nrf52EarlyBoot.cpp: - Early register capture before SystemInit() Added src/helpers/nrf52/Nrf52PowerMgt.h: - Phase 1 API (PowerMgtConfig, PowerMgtState, initState, checkBootVoltage, configureLpcompWake, enterSystemOff) Added src/helpers/nrf52/Nrf52PowerMgt.cpp: - Initial Implementation Modified src/MeshCore.h: - Added power management virtual methods to MainBoard Added first supported board (Xiao nRF52840) for testing.
|
Leaving this in a draft state so it can be tested as this is a major refactor to centralise more of the code away from individual variants, and tidy up general sloppiness/hacky code from the v1 implementation. |
|
Would this work also e.g. with nfr52 based systems that do not have voltage divider resistors for the ADC port in place? (Thinking e.g. of ProMicro) |
Great question, likely not (at least in the current implementation). I've been trying to track down a concrete schematic for the promicro but because there are so many iterations of it, I can't get a reliable view of the board. If you happen to have one, that would go a long way to getting a more definitive answer. |
|
The ProMicro target is based on the "faketec" PCB (https://github.com/gargomoma/fakeTec_pcb). There are multiple variations of the PCB but mostly adding peripherals like FETs, power regulators, solar chargers etc. I was only able to find the schematic for V5 |
|
OK so short answer is yes it should work:
There are however a couple of caveats (citation needed from people who know this stuff better):
|
|
Sometimes we just need to send it and see. I'll add in code for the promicro variant if you're willing to test. |
|
I've found some duplication in the code so will undo the commits, fix that up and force push the branch back up to keep things tidy. I'll add the promicro support at the same time. |
If you can't measure battery voltage then it's not going to work. I personally haven't seen any promicro-based boards that don't implement a voltage divider for battery reading though |
The thing is that promicro based boards don't necessarily all use the same voltage dividers. Promicro repeaters do allow setting the adc.multiplier value via the CLI though 👍 |
src/helpers/nrf52/Nrf52PowerMgt.h
Outdated
| // Shutdown Reason Codes (stored in GPREGRET before SYSTEMOFF) | ||
| #define SHUTDOWN_REASON_NONE 0x00 | ||
| #define SHUTDOWN_REASON_LOW_VOLTAGE 0x4C // 'L' - Runtime low voltage threshold | ||
| #define SHUTDOWN_REASON_USER 0x55 // 'U' - User requested powerOff() | ||
| #define SHUTDOWN_REASON_BOOT_PROTECT 0x42 // 'B' - Boot voltage protection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to be careful here, as the bootloader uses GPREGRET as well, but I think these values will be OK.
#define DFU_MAGIC_OTA_APPJUM BOOTLOADER_DFU_START // 0xB1
#define DFU_MAGIC_OTA_RESET 0xA8
#define DFU_MAGIC_SERIAL_ONLY_RESET 0x4e
#define DFU_MAGIC_UF2_RESET 0x57
#define DFU_MAGIC_SKIP 0x6d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found this out while going over it again, there's apparently a GPREGRET2 we can use. Just looking into that.
- Simplified and brought power management code into NRF52Board - Switched to using GPREGRET2 instead of GPREGRET to avoid clashing with bootloader use of GPREGRET
ee73ddb to
94376f8
Compare
|
Cleaned up and simplfied the code (thanks to those who helped behind the scenes). Have switched GPREGRET over to GPREGRET2 and run a manual shutdown via the same route a boot lockout shutdown would take, and confirmed the LPCOMP wake works and so does the GPREGRET2 and RESETREAS value reads. Ready for a review I think. I've also added the promicro board support for others to test. |
|
BTW - once the reviews are done and the devs are happy, I'll clean up the commits into one. |
oltaco
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just a few comments/suggestions 👍
| #ifdef NRF52_POWER_MANAGEMENT | ||
| // Boot voltage protection check (may not return if voltage too low) | ||
| checkBootVoltage(&power_config); | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this happen before the power is supplied to the radio a few lines above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, I missed that. Fixed up on local and will be in the next commit.
| #ifdef NRF52_POWER_MANAGEMENT | ||
| bool isExternalPowered() override; | ||
| uint16_t getBootVoltage() override { return boot_voltage_mv; } | ||
| virtual uint32_t getResetReason() const override { return reset_reason; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as above can just use readResetReason()
| uint8_t g_nrf52_shutdown_reason = 0; // Shutdown reason | ||
|
|
||
| // Early constructor - runs before SystemInit() clears the registers | ||
| // Priority 101 ensures this runs before SystemInit (102) and before | ||
| // any C++ static constructors (default 65535) | ||
| static void __attribute__((constructor(101))) nrf52_early_reset_capture() { | ||
| g_nrf52_reset_reason = NRF_POWER->RESETREAS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reset reason can be accessed by readResetReason(), adafruit caches the value at early startup before it gets cleared.
GPREGRET2 shouldn't get cleared so you can access that at anytime, but if you use readResetReason() you probably don't need to force priority
| configureLpcompWake(power_config.lpcomp_ain_channel, power_config.lpcomp_ref_eighths); | ||
| enterSystemOff(SHUTDOWN_REASON_USER); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should LPCOMP wake be disabled when the user has explicitly requested shutdown via the UI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was in two minds about this when I added it and still am. What I'm trying to achieve is a means for the user to force a power management state change early or if they wish to test how it will respond with their setup.
I wanted to differentiate this without people getting arthritis in their thumbs from typing some long arduous command like "set pwrmgt.state shutdownandwake". I think there's probably merit in allowing both ways to exist; shutdown with and without LPCOMP wake.
What do you think?
This PR implements initial stages of power management functionality for nRF52840 nodes to prevent lockups and flash corruption associated with low voltage. This is designed to be modular and enabled per-variant.
Phase 1 (this PR) includes: