-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
ports/zephyr: Add machine lightsleep. #16864
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: master
Are you sure you want to change the base?
ports/zephyr: Add machine lightsleep. #16864
Conversation
09c18f1
to
9b0020b
Compare
Signed-off-by: Patrick Joy <[email protected]>
625c8bf
to
075fcdc
Compare
This looks like a very useful addition to the Zephyr port. Thanks! |
I think, instead of grabbing the console device and putting it to sleep, it should either rely on zephyr's power policy management or implement pm_policy_next_state, or provide a API to chose what devices to turn on and off. Otherwise this looks good. |
Thanks @VynDragon I think the uart/console has to be manually shutdown on the nrf chips regardless of PM policy. My understanding is that when CONFIG_SERIAL=y then serial logging is enabled for debugging which uses power, even in low power modes. We can't turn off CONFIG_SERIAL because it's needed for micropython repl. There is some info on it here. You can see also in the power management examples they shut down the console device manually before power off. I'm very new to zephyr so I could be wrong, what do you think? Also looking at the example if might be worthwhile also implementing deepsleep with sys_poweroff();? |
Signed-off-by: Patrick Joy <[email protected]>
I have added machine.deepsleep() to this PR which completely powers down the system using |
I am trying to write PM for the chips I want to support but I am nowhere near a expert on this subsystem, so take what I say with a grain of salt.
Dont take the NRF sdk docs as exclusive reference, there are a lot of other chips :)
That is indeed a example of manual control of the power saving, but not of managing power states via policies. See https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/subsys/pm/latency for the default latency policy. I am also not sure if poweroff should be deep sleep of if that should be PM_STATE_SOFT_OFF. I have implemented power off on my platform, and it conserves some ways to be powered back on, but in comparison to ESP32 deepsleep, it would match a higher power state with more ways to wake up. |
ports/zephyr/modmachine.c
Outdated
// Get the UART device | ||
const struct device *uart0 = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); | ||
// Set UART device to low power state | ||
pm_device_action_run(uart0, PM_DEVICE_ACTION_SUSPEND); |
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.
Will this work on boards that use USB CDC as the console? Maybe the code here will still be OK, but at least the variable should be renamed from uart0
to console
?
const struct device *uart0 = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); | ||
// Set UART device to low power state | ||
pm_device_action_run(uart0, PM_DEVICE_ACTION_SUSPEND); | ||
sys_poweroff(); |
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.
It looks like this is not always available, eg the CI is failing here.
Signed-off-by: Patrick Joy <[email protected]>
Summary
Machine lightsleep is currently not implemented in the zephyr port.
nrf socs have excellent low power capabilities however they do require some additional PM setup. In particular the uart module consumes ~1mA of power even when not being used. Powering down the uart modue can reduce sleep current to as low as 4uA (depending on hardware).
This PR adds support for lightsleep in the zephyr port. It disables the main uart and calls k_sleep() to put the micropython thread to sleep. This allows Zephyr power management to reduce power to minimum. The uart is made active when the thread is resumed.
lightsleep is included by default on all boards but can be disabled by setting:
Note: It is disabled on the beagleconnect_freedom as it does not seem to be supported.
Testing
Tested on nrf5340dk with power profile kit.
Current reduced from idle 1mA to 4uA during lightsleep.
Confirmed that ram is retained as this is lightsleep
Firmware has been built for all board variants in the mp repo. All boards were sucsefully built except for:
qemu_cortex_m3 - Failed due to unrelated issue
beagleconnect_freedom - Does not seem to support PM so it has been explicitly disabled in prj.conf
Trade-offs and Alternatives
I don't believe there are any negative impacts of this change although I am not sure how to measure the increase in firmware size.
machine.deepsleep, machine.get_freq, machine.set_freq and machine.unique_id return "not implemented".