Add support for RP2040 dormant (using external RTC clock)

This commit is contained in:
William Vinnicombe 2025-08-22 14:59:27 +01:00
parent 83d1e65f1e
commit 9bf9fffd7c
4 changed files with 57 additions and 10 deletions

View file

@ -215,11 +215,7 @@ void low_power_sleep_until_pin_state(uint gpio_pin, bool edge, bool high,
// Clear the irq so we can go back to dormant mode again if we want
gpio_acknowledge_irq(gpio_pin, event);
// todo fix race in gpio_set_irq_enabled_with_callback
// gpio_set_irq_enabled_with_callback(gpio_pin, event, false, NULL);
gpio_set_irq_enabled(gpio_pin, event, false);
gpio_set_irq_callback(NULL);
gpio_set_irq_enabled_with_callback(gpio_pin, event, false, NULL);
post_clock_gating();
}
@ -374,7 +370,7 @@ void low_power_go_dormant(dormant_clock_source_t dormant_clock_source) {
int low_power_dormant_until_aon_timer(absolute_time_t until,
dormant_clock_source_t dormant_clock_source,
__unused uint src_hz, uint gpio_pin,
uint src_hz, uint gpio_pin,
const clock_dest_set_t *keep_enabled) {
low_power_setup_clocks_for_dormant(dormant_clock_source);
@ -388,6 +384,7 @@ int low_power_dormant_until_aon_timer(absolute_time_t until,
clock_dest_set_add(&local_keep_enabled, CLK_DEST_RTC_RTC);
#elif PICO_RP2350
// todo
((void)src_hz);
((void)gpio_pin);
if (dormant_clock_source == DORMANT_CLOCK_SOURCE_LPOSC)
powman_timer_set_1khz_tick_source_lposc();

View file

@ -7,6 +7,17 @@ target_link_libraries(hello_sleep pico_stdlib pico_low_power pico_status_led)
# create map/bin/hex file etc.
pico_add_extra_outputs(hello_sleep)
if (PICO_RP2040)
add_executable(rtc_clksrc
rtc_clksrc.c
)
target_link_libraries(rtc_clksrc pico_stdlib pico_status_led)
# create map/bin/hex file etc.
pico_add_extra_outputs(rtc_clksrc)
endif()
add_executable(hello_sleep_gpio
hello_sleep_gpio.c
)

View file

@ -14,6 +14,8 @@
#define SLEEP_TIME_S 2
#define SLEEP_TIME_MS SLEEP_TIME_S * 1000
#define RTC_GPIO 22 // must support clock input, see the GPIO function table in the datasheet.
bool repeater(repeating_timer_t *timer) {
if (aon_timer_is_running()) {
printf(" Repeating timer at %dms (aon: %dms)\n", to_ms_since_boot(get_absolute_time()), to_ms_since_boot(aon_timer_get_absolute_time()));
@ -86,7 +88,6 @@ int main() {
printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S);
busy_wait_ms(SLEEP_TIME_MS);
#if !PICO_RP2040
printf("Going DORMANT for %d seconds via AON TIMER\n", SLEEP_TIME_S);
// todo, ah; we should start the aon timer; still have to decide what to do about keeping them in sync
@ -95,9 +96,13 @@ int main() {
aon_timer_start(&ts);
wakeup_time = delayed_by_ms(start_time, SLEEP_TIME_MS);
low_power_dormant_until_aon_timer(wakeup_time, DORMANT_CLOCK_SOURCE_LPOSC, XOSC_KHZ * 1000,
0, // gpio pin (unused with powman)
NULL);
low_power_dormant_until_aon_timer(wakeup_time,
#if PICO_RP2040
DORMANT_CLOCK_SOURCE_XOSC, 46875,
#else
DORMANT_CLOCK_SOURCE_LPOSC, XOSC_HZ,
#endif
RTC_GPIO, NULL);
diff = absolute_time_diff_us(get_absolute_time(), wakeup_time);
// need to use the AON timer for checking time, since the other timer is unclocked
diff = absolute_time_diff_us(wakeup_time, get_absolute_time());
@ -113,6 +118,7 @@ int main() {
printf("Doing %d second pause to prove timer running\n", SLEEP_TIME_S);
busy_wait_ms(SLEEP_TIME_MS);
#if !PICO_RP2040
printf("Going to PSTATE for %d seconds\n", SLEEP_TIME_S);
start_time = aon_timer_get_absolute_time();

View file

@ -0,0 +1,33 @@
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/status_led.h"
#include "pico/sync.h"
#include "hardware/clocks.h"
#define RTC_GPIO 21
bool repeater(repeating_timer_t *timer) {
printf(" Repeating timer at %dms\n", to_ms_since_boot(get_absolute_time()));
status_led_set_state(!status_led_get_state());
return true;
}
int main() {
stdio_init_all();
status_led_init();
clock_gpio_init(RTC_GPIO, CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_VALUE_CLK_RTC, 1);
repeating_timer_t repeat;
add_repeating_timer_ms(500, repeater, NULL, &repeat);
while (true) __wfi();
return 0;
}