8000 WIP: rp2: Use the soft timer hardware alarm to wake from lightsleep. · micropython/micropython@9a34859 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9a34859

Browse files
committed
WIP: rp2: Use the soft timer hardware alarm to wake from lightsleep.
Fixes issue where PICO-W build won't lightsleep() for more than 64ms. This is a regression introduced in 74fb42a when we switched away from the pico-sdk alarm pool for soft timers and accidentally made soft timer expiry a wakeup source. Before 74fb42a, both the pico-sdk alarm pool and the lightsleep wakeup timer uses alarm 3. The lightsleep wakeup would quietly clobber alarm 3's timeout, meaning softtimer wouldn't wake the chip from lightsleep. After 74fb42a, soft timer wakeup happens on timer alarm 2 so this interrupt wakes the chip from light sleep. On PICO-W builds this happens every lwIP tick (64ms). The change is to go back to using the same timer alarm for both lightsleep wakeup and soft timer, but now being explicit about lightsleep wakeup clobbering any soft timer wakeup. Also adds a "catch up" call to soft timer handler as it's currently possible to miss soft timer events after waking up. This also reverts the changes added in 19844b to enable the timer IRQ on CPU1. This should now be covered by the changes in 9db16cf which explicitly trigger a wakeup event from CPU0 to CPU1 any time the soft timer handler fires. TBC. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent ee8d8b3 commit 9a34859

File tree

1 file changed

+10
-16
lines changed

1 file changed

+10
-16
lines changed

ports/rp2/modmachine.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -196,17 +196,7 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
196196
#endif
197197
xosc_dormant();
198198
} else {
199-
bool timer3_enabled = irq_is_enabled(3);
200-
201-
const uint32_t alarm_num = 3;
202-
const uint32_t irq_num = TIMER_ALARM_IRQ_NUM(timer_hw, alarm_num);
203199
if (use_timer_alarm) {
204-
// Make sure ALARM3/IRQ3 is enabled on _this_ core
205-
if (!timer3_enabled) {
206-
irq_set_enabled(irq_num, true);
207-
}
208-
hw_set_bits(&timer_hw->inte, 1u << alarm_num);
209-
// Use timer alarm to wake.
210200
clocks_hw->sleep_en0 = 0x0;
211201
#if PICO_RP2040
212202
clocks_hw->sleep_en1 = CLOCKS_SLEEP_EN1_CLK_SYS_TIMER_BITS;
@@ -215,8 +205,12 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
215205
#else
216206
#error Unknown processor
217207
#endif
218-
timer_hw->intr = 1u << alarm_num; // clear any IRQ
219-
timer_hw->alarm[alarm_num] = timer_hw->timerawl + delay_ms * 1000;
208+
209+
// Clobber the soft timer hardware alarm (as soft timer doesn't wake lightsleep)
210+
// and repurpose it for the lightsleep wakeup
211+
//
212+
// The timer peripheral will already be configured via softtimer_init().
213+
hardware_alarm_set_target(MICROPY_HW_SOFT_TIMER_ALARM_NUM, delayed_by_ms(get_absolute_time(), delay_ms));
220214
} else {
221215
// TODO: Use RTC alarm to wake.
222216
clocks_hw->sleep_en0 = 0x0;
@@ -247,10 +241,6 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
247241

248242
// Go into low-power mode.
249243
__wfi();
250-
251-
if (!timer3_enabled) {
252-
irq_set_enabled(irq_num, false);
253-
}
254244
clocks_hw->sleep_en0 |= ~(0u);
255245
clocks_hw->sleep_en1 |= ~(0u);
256246
}
@@ -264,6 +254,10 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
264254

265255
// Re-sync mp_hal_time_ns() counter with aon timer.
266256
mp_hal_time_ns_set_from_rtc();
257+
258+
// we might have missed at least one soft timer expiry that hasn't been processed
259+
// depending on when we woke up, so re-trigger soft timer processing now
260+
hardware_alarm_force_irq(MICROPY_HW_SOFT_TIMER_ALARM_NUM);
267261
}
268262

269263
NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args) {

0 commit comments

Comments
 (0)
0