Skip to content

Commit d0177fb

Browse files
committed
rp2/modmachine: Implement lightsleep() with optional sleep period.
Signed-off-by: Damien George <damien@micropython.org>
1 parent 6e83bb4 commit d0177fb

File tree

2 files changed

+75
-4
lines changed

2 files changed

+75
-4
lines changed

ports/rp2/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ set(PICO_SDK_COMPONENTS
150150
hardware_i2c
151151
hardware_irq
152152
hardware_pio
153+
hardware_pll
153154
hardware_pwm
154155
hardware_regs
155156
hardware_rtc
@@ -159,6 +160,7 @@ set(PICO_SDK_COMPONENTS
159160
hardware_timer
160161
hardware_uart
161162
hardware_watchdog
163+
hardware_xosc
162164
pico_base_headers
163165
pico_binary_info
164166
pico_bootrom

ports/rp2/modmachine.c

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,12 @@
3838
#include "modmachine.h"
3939
#include "uart.h"
4040
#include "hardware/clocks.h"
41+
#include "hardware/pll.h"
42+
#include "hardware/structs/rosc.h"
43+
#include "hardware/structs/scb.h"
44+
#include "hardware/structs/syscfg.h"
4145
#include "hardware/watchdog.h"
46+
#include "hardware/xosc.h"
4247
#include "pico/bootrom.h"
4348
#include "pico/stdlib.h"
4449
#include "pico/unique_id.h"
@@ -83,6 +88,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
8388

8489
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
8590
MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
91+
rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB;
8692
reset_usb_boot(0, 0);
8793
for (;;) {
8894
}
@@ -113,13 +119,76 @@ STATIC mp_obj_t machine_idle(void) {
113119
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
114120

115121
STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) {
116-
if (n_args == 0) {
117-
for (;;) {
118-
MICROPY_EVENT_POLL_HOOK
122+
mp_int_t delay_ms = 0;
123+
bool use_timer_alarm = false;
124+
125+
if (n_args == 1) {
126+
delay_ms = mp_obj_get_int(args[0]);
127+
if (delay_ms <= 1) {
128+
// Sleep is too small, just return.
129+
return mp_const_none;
130+
}
131+
use_timer_alarm = delay_ms < (1ULL << 32) / 1000;
132+
if (use_timer_alarm) {
133+
// Use timer alarm to wake.
134+
} else {
135+
// TODO: Use RTC alarm to wake.
136+
mp_raise_ValueError(MP_ERROR_TEXT("sleep too long"));
119137
}
138+
}
139+
140+
const uint32_t xosc_hz = XOSC_MHZ * 1000000;
141+
142+
// Disable USB and ADC clocks.
143+
clock_stop(clk_usb);
144+
clock_stop(clk_adc);
145+
146+
// CLK_REF = XOSC
147+
clock_configure(clk_ref, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, 0, xosc_hz, xosc_hz);
148+
149+
// CLK_SYS = CLK_REF
150+
clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF, 0, xosc_hz, xosc_hz);
151+
152+
// CLK_RTC = XOSC / 256
153+
clock_configure(clk_rtc, 0, CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC, xosc_hz, xosc_hz / 256);
154+
155+
// CLK_PERI = CLK_SYS
156+
clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, xosc_hz, xosc_hz);
157+
158+
// Disable PLLs.
159+
pll_deinit(pll_sys);
160+
pll_deinit(pll_usb);
161+
162+
// Disable ROSC.
163+
rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_DISABLE << ROSC_CTRL_ENABLE_LSB;
164+
165+
if (n_args == 0) {
166+
xosc_dormant();
120167
} else {
121-
mp_hal_delay_ms(mp_obj_get_int(args[0]));
168+
uint32_t sleep_en0 = clocks_hw->sleep_en0;
169+
uint32_t sleep_en1 = clocks_hw->sleep_en1;
170+
clocks_hw->sleep_en0 = CLOCKS_SLEEP_EN0_CLK_RTC_RTC_BITS;
171+
if (use_timer_alarm) {
172+
// Use timer alarm to wake.
173+
clocks_hw->sleep_en1 = CLOCKS_SLEEP_EN1_CLK_SYS_TIMER_BITS;
174+
timer_hw->alarm[3] = timer_hw->timerawl + delay_ms * 1000;
175+
} else {
176+
// TODO: Use RTC alarm to wake.
177+
clocks_hw->sleep_en1 = 0;
178+
}
179+
scb_hw->scr |= M0PLUS_SCR_SLEEPDEEP_BITS;
180+
__wfi();
181+
scb_hw->scr &= ~M0PLUS_SCR_SLEEPDEEP_BITS;
182+
clocks_hw->sleep_en0 = sleep_en0;
183+
clocks_hw->sleep_en1 = sleep_en1;
122184
}
185+
186+
// Enable ROSC.
187+
rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB;
188+
189+
// Bring back all clocks.
190+
clocks_init();
191+
123192
return mp_const_none;
124193
}
125194
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy