From f74bd50af73dbd5b5fd89b277685a24552c41ee3 Mon Sep 17 00:00:00 2001 From: Peter Harper Date: Thu, 8 Aug 2024 14:01:32 +0100 Subject: [PATCH 1/2] Update pico_sleep examples Adds examples that sleep via an alarm or via an AON timer Adds dormant examples that wake on an AON timer or GPIO Fixed to work for RP2040 and RP2350 --- sleep/CMakeLists.txt | 4 +- sleep/hello_dormant/CMakeLists.txt | 20 ++++-- sleep/hello_dormant/hello_dormant.c | 36 ---------- sleep/hello_dormant/hello_dormant_aon.c | 84 ++++++++++++++++++++++++ sleep/hello_dormant/hello_dormant_gpio.c | 41 ++++++++++++ sleep/hello_sleep/CMakeLists.txt | 22 +++++-- sleep/hello_sleep/hello_sleep.c | 77 ---------------------- sleep/hello_sleep/hello_sleep_alarm.c | 58 ++++++++++++++++ sleep/hello_sleep/hello_sleep_aon.c | 70 ++++++++++++++++++++ 9 files changed, 285 insertions(+), 127 deletions(-) mode change 100644 => 100755 sleep/CMakeLists.txt mode change 100644 => 100755 sleep/hello_dormant/CMakeLists.txt delete mode 100644 sleep/hello_dormant/hello_dormant.c create mode 100644 sleep/hello_dormant/hello_dormant_aon.c create mode 100755 sleep/hello_dormant/hello_dormant_gpio.c mode change 100644 => 100755 sleep/hello_sleep/CMakeLists.txt delete mode 100644 sleep/hello_sleep/hello_sleep.c create mode 100755 sleep/hello_sleep/hello_sleep_alarm.c create mode 100644 sleep/hello_sleep/hello_sleep_aon.c diff --git a/sleep/CMakeLists.txt b/sleep/CMakeLists.txt old mode 100644 new mode 100755 index 30c19c4..a45f913 --- a/sleep/CMakeLists.txt +++ b/sleep/CMakeLists.txt @@ -1,4 +1,4 @@ if (NOT PICO_NO_HARDWARE) - add_subdirectory_exclude_platforms(hello_dormant "rp2350.*") - add_subdirectory_exclude_platforms(hello_sleep "rp2350.*") + add_subdirectory(hello_dormant) + add_subdirectory(hello_sleep) endif () diff --git a/sleep/hello_dormant/CMakeLists.txt b/sleep/hello_dormant/CMakeLists.txt old mode 100644 new mode 100755 index afd5a0d..1682b86 --- a/sleep/hello_dormant/CMakeLists.txt +++ b/sleep/hello_dormant/CMakeLists.txt @@ -1,8 +1,16 @@ -add_executable(hello_dormant - hello_dormant.c +add_executable(hello_dormant_gpio + hello_dormant_gpio.c ) +target_link_libraries(hello_dormant_gpio + pico_stdlib + hardware_sleep) +pico_add_extra_outputs(hello_dormant_gpio) -target_link_libraries(hello_dormant pico_stdlib hardware_sleep) - -# create map/bin/hex file etc. -pico_add_extra_outputs(hello_dormant) \ No newline at end of file +add_executable(hello_dormant_aon + hello_dormant_aon.c + ) +target_link_libraries(hello_dormant_aon + pico_stdlib + hardware_sleep + ) +pico_add_extra_outputs(hello_dormant_aon) diff --git a/sleep/hello_dormant/hello_dormant.c b/sleep/hello_dormant/hello_dormant.c deleted file mode 100644 index 4d33ff8..0000000 --- a/sleep/hello_dormant/hello_dormant.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include "pico/stdlib.h" -#include "pico/sleep.h" - -int main() { - stdio_init_all(); - printf("Hello Dormant!\n"); - - printf("Switching to XOSC\n"); - uart_default_tx_wait_blocking(); - - // UART will be reconfigured by sleep_run_from_xosc - sleep_run_from_xosc(); - - printf("Running from XOSC\n"); - uart_default_tx_wait_blocking(); - - printf("XOSC going dormant\n"); - uart_default_tx_wait_blocking(); - - // Go to sleep until we see a high edge on GPIO 10 - sleep_goto_dormant_until_edge_high(10); - - uint i = 0; - while (1) { - printf("XOSC awake %d\n", i++); - } - - return 0; -} \ No newline at end of file diff --git a/sleep/hello_dormant/hello_dormant_aon.c b/sleep/hello_dormant/hello_dormant_aon.c new file mode 100644 index 0000000..71ec056 --- /dev/null +++ b/sleep/hello_dormant/hello_dormant_aon.c @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/sleep.h" + +// For clock_configure_gpin +#ifdef PICO_RP2040 +#include "hardware/clocks.h" +#endif + +// For RP2040 this example needs an external clock fed into the GP20 +// Note: Only GP20 and GP22 can be used for clock input, See the GPIO function table in the datasheet. +// You can use another Pico to generate this. See the clocks/hello_gpout example for more details. +// rp2040: clock_gpio_init(21, CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_VALUE_CLK_RTC, 1); // 46875Hz can only export a clock on gpios 21,23,24,25 and only 21 is exposed by Pico +// RP2350 has an LPOSC it can use, so doesn't need this +#define EXTERNAL_CLOCK_INPUT_PIN 20 +#define RTC_FREQ_HZ 46875 + +static void sleep_callback(void) { + printf("AON timer woke us up\n"); +} + +static void aon_sleep(void) { + + // Get the time from the aon timer and set our alarm time + struct timespec ts; + aon_timer_get_time(&ts); + ts.tv_sec += 10; + + printf("Sleeping for 10 seconds\n"); + uart_default_tx_wait_blocking(); + +#if PICO_RP2040 + // The RTC must be run from an external source, since the dormant source will be inactive + clock_configure_gpin(clk_rtc, EXTERNAL_CLOCK_INPUT_PIN, RTC_FREQ_HZ, 46875); +#endif + + // Go to sleep for 10 seconds, with RTC running off GP20 + // The external clock is the RTC of another pico being fed to GP20 + sleep_goto_aon_dormant_until(&ts, &sleep_callback); +} + +int main() { + + stdio_init_all(); + printf("Hello Dormant AON Timer!\n"); + + struct timespec ts = { .tv_sec = 1723124088, .tv_nsec = 0 }; + aon_timer_start(&ts); + + while(true) { + printf("Awake for 10s\n"); + sleep_ms(10000); + + uart_default_tx_wait_blocking(); + + // Set the crystal oscillator as the dormant clock source, UART will be reconfigured from here + // This is necessary before sending the pico dormant +#if PICO_RP2040 + printf("Switching to XOSC\n"); + sleep_run_from_xosc(); +#else + printf("Switching to LPSC\n"); + sleep_run_from_lpsc(); +#endif + + uart_default_tx_wait_blocking(); + + printf("Going dormant\n"); + uart_default_tx_wait_blocking(); + + // Go to sleep until the RTC interrupt is generated after 10 seconds + aon_sleep(); + + // Re-enabling clock sources and generators. + sleep_power_up(); + } + return 0; +} diff --git a/sleep/hello_dormant/hello_dormant_gpio.c b/sleep/hello_dormant/hello_dormant_gpio.c new file mode 100755 index 0000000..fd111ae --- /dev/null +++ b/sleep/hello_dormant/hello_dormant_gpio.c @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/sleep.h" + +#define WAKE_GPIO 10 + +int main() { + stdio_init_all(); + printf("Hello Dormant GPIO!\n"); + + printf("Test starting in 10s\n"); + sleep_ms(10000); + + while(true) { + printf("Switching to XOSC\n"); + uart_default_tx_wait_blocking(); + + // Set the crystal oscillator as the dormant clock source, UART will be reconfigured from here + // This is necessary before sending the pico into dormancy + sleep_run_from_xosc(); + + printf("Going dormant until GPIO %d goes edge high\n", WAKE_GPIO); + uart_default_tx_wait_blocking(); + + // Go to sleep until we see a high edge on GPIO 10 + sleep_goto_dormant_until_edge_high(WAKE_GPIO); + + // Re-enabling clock sources and generators. + sleep_power_up(); + printf("Now awake for 10s\n"); + sleep_ms(1000 * 10); + } + + return 0; +} \ No newline at end of file diff --git a/sleep/hello_sleep/CMakeLists.txt b/sleep/hello_sleep/CMakeLists.txt old mode 100644 new mode 100755 index a45f6ac..dcc63c7 --- a/sleep/hello_sleep/CMakeLists.txt +++ b/sleep/hello_sleep/CMakeLists.txt @@ -1,8 +1,18 @@ -add_executable(hello_sleep - hello_sleep.c +add_executable(hello_sleep_alarm + hello_sleep_alarm.c ) +target_link_libraries(hello_sleep_alarm + pico_stdlib + hardware_sleep + ) +pico_add_extra_outputs(hello_sleep_alarm) -target_link_libraries(hello_sleep pico_stdlib hardware_sleep) - -# create map/bin/hex file etc. -pico_add_extra_outputs(hello_sleep) \ No newline at end of file +add_executable(hello_sleep_aon + hello_sleep_aon.c + ) +target_link_libraries(hello_sleep_aon + pico_stdlib + hardware_sleep + pico_aon_timer + ) +pico_add_extra_outputs(hello_sleep_aon) diff --git a/sleep/hello_sleep/hello_sleep.c b/sleep/hello_sleep/hello_sleep.c deleted file mode 100644 index 7a8a48e..0000000 --- a/sleep/hello_sleep/hello_sleep.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include "pico/stdlib.h" -#include "pico/sleep.h" - -#include "hardware/rtc.h" - -static bool awake; - -static void sleep_callback(void) { - printf("RTC woke us up\n"); - awake = true; -} - -static void rtc_sleep(void) { - // Start on Friday 5th of June 2020 15:45:00 - datetime_t t = { - .year = 2020, - .month = 06, - .day = 05, - .dotw = 5, // 0 is Sunday, so 5 is Friday - .hour = 15, - .min = 45, - .sec = 00 - }; - - // Alarm 10 seconds later - datetime_t t_alarm = { - .year = 2020, - .month = 06, - .day = 05, - .dotw = 5, // 0 is Sunday, so 5 is Friday - .hour = 15, - .min = 45, - .sec = 10 - }; - - // Start the RTC - rtc_init(); - rtc_set_datetime(&t); - - printf("Sleeping for 10 seconds\n"); - uart_default_tx_wait_blocking(); - - sleep_goto_sleep_until(&t_alarm, &sleep_callback); -} - -int main() { - stdio_init_all(); - printf("Hello Sleep!\n"); - - printf("Switching to XOSC\n"); - - // Wait for the fifo to be drained so we get reliable output - uart_default_tx_wait_blocking(); - - // UART will be reconfigured by sleep_run_from_xosc - sleep_run_from_xosc(); - - printf("Switched to XOSC\n"); - - awake = false; - - rtc_sleep(); - - // Make sure we don't wake - while (!awake) { - printf("Should be sleeping\n"); - } - - return 0; -} diff --git a/sleep/hello_sleep/hello_sleep_alarm.c b/sleep/hello_sleep/hello_sleep_alarm.c new file mode 100755 index 0000000..751c0db --- /dev/null +++ b/sleep/hello_sleep/hello_sleep_alarm.c @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/sleep.h" + +static bool awake; + +static void alarm_sleep_callback(uint alarm_id) { + printf("alarm woke us up\n"); + uart_default_tx_wait_blocking(); + awake = true; + hardware_alarm_set_callback(alarm_id, NULL); + hardware_alarm_unclaim(alarm_id); +} + +int main() { + + stdio_init_all(); + printf("Hello Alarm Sleep!\n"); + + do { + printf("Awake for 10 seconds\n"); + sleep_ms(1000 * 10); + + printf("Switching to XOSC\n"); + + // Wait for the fifo to be drained so we get reliable output + uart_default_tx_wait_blocking(); + + // Set the crystal oscillator as the dormant clock source, UART will be reconfigured from here + // This is only really necessary before sending the pico dormant but running from xosc while asleep saves power + sleep_run_from_xosc(); + awake = false; + + // Go to sleep until the alarm interrupt is generated after 10 seconds + printf("Sleeping for 10 seconds\n"); + uart_default_tx_wait_blocking(); + + int alarm_id = -1; + sleep_goto_sleep_for(10000, &alarm_sleep_callback, &alarm_id); + if (alarm_id >= 0) { + // Make sure we don't wake + while (!awake) { + printf("Should be sleeping\n"); + } + } + + // Re-enabling clock sources and generators. + sleep_power_up(); + } while(true); + + return 0; +} diff --git a/sleep/hello_sleep/hello_sleep_aon.c b/sleep/hello_sleep/hello_sleep_aon.c new file mode 100644 index 0000000..1749ca2 --- /dev/null +++ b/sleep/hello_sleep/hello_sleep_aon.c @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "pico/sleep.h" +#include "pico/aon_timer.h" + +static bool awake; + +static void sleep_callback(void) { + printf("AON Timer woke us up\n"); + uart_default_tx_wait_blocking(); + awake = true; +} + +static void aon_sleep(void) { + + // Get the time from the aon timer and set our alarm time + struct timespec ts; + aon_timer_get_time(&ts); + ts.tv_sec += 10; + + printf("Sleeping for 10 seconds\n"); + uart_default_tx_wait_blocking(); + + // Go to sleep + sleep_goto_aon_sleep_until(&ts, &sleep_callback); +} + +int main() { + + stdio_init_all(); + + printf("Hello AON timer Sleep!\n"); + + struct timespec ts = { .tv_sec = 1723124088, .tv_nsec = 0 }; + aon_timer_start(&ts); + + do { + printf("Awake for 10 seconds\n"); + sleep_ms(1000 * 10); + + printf("Switching to XOSC\n"); + + // Wait for the fifo to be drained so we get reliable output + uart_default_tx_wait_blocking(); + + // Set the crystal oscillator as the dormant clock source, UART will be reconfigured from here + // This is only really necessary before sending the pico into dormancy but running from xosc while asleep saves power + sleep_run_from_xosc(); + + // Go to sleep until an interrupt is generated after 10 seconds + awake = false; + aon_sleep(); + + // Make sure we don't wake + while (!awake) { + printf("Should be sleeping\n"); + } + + // Re-enabling clock sources and generators. + sleep_power_up(); + } while(true); + + return 0; +} From 54e741030728fcc03d84339abfdc4102c99a06a0 Mon Sep 17 00:00:00 2001 From: Peter Harper Date: Thu, 7 Nov 2024 19:20:06 +0000 Subject: [PATCH 2/2] Changes from code review --- sleep/hello_dormant/hello_dormant_aon.c | 4 ++-- sleep/hello_sleep/hello_sleep_alarm.c | 4 +--- sleep/hello_sleep/hello_sleep_aon.c | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/sleep/hello_dormant/hello_dormant_aon.c b/sleep/hello_dormant/hello_dormant_aon.c index 71ec056..481af1b 100644 --- a/sleep/hello_dormant/hello_dormant_aon.c +++ b/sleep/hello_dormant/hello_dormant_aon.c @@ -42,7 +42,7 @@ static void aon_sleep(void) { // Go to sleep for 10 seconds, with RTC running off GP20 // The external clock is the RTC of another pico being fed to GP20 - sleep_goto_aon_dormant_until(&ts, &sleep_callback); + sleep_goto_dormant_until(&ts, &sleep_callback); } int main() { @@ -66,7 +66,7 @@ int main() { sleep_run_from_xosc(); #else printf("Switching to LPSC\n"); - sleep_run_from_lpsc(); + sleep_run_from_lposc(); #endif uart_default_tx_wait_blocking(); diff --git a/sleep/hello_sleep/hello_sleep_alarm.c b/sleep/hello_sleep/hello_sleep_alarm.c index 751c0db..205bf35 100755 --- a/sleep/hello_sleep/hello_sleep_alarm.c +++ b/sleep/hello_sleep/hello_sleep_alarm.c @@ -41,9 +41,7 @@ int main() { printf("Sleeping for 10 seconds\n"); uart_default_tx_wait_blocking(); - int alarm_id = -1; - sleep_goto_sleep_for(10000, &alarm_sleep_callback, &alarm_id); - if (alarm_id >= 0) { + if (sleep_goto_sleep_for(10000, &alarm_sleep_callback)) { // Make sure we don't wake while (!awake) { printf("Should be sleeping\n"); diff --git a/sleep/hello_sleep/hello_sleep_aon.c b/sleep/hello_sleep/hello_sleep_aon.c index 1749ca2..256dc8e 100644 --- a/sleep/hello_sleep/hello_sleep_aon.c +++ b/sleep/hello_sleep/hello_sleep_aon.c @@ -28,7 +28,7 @@ static void aon_sleep(void) { uart_default_tx_wait_blocking(); // Go to sleep - sleep_goto_aon_sleep_until(&ts, &sleep_callback); + sleep_goto_sleep_until(&ts, &sleep_callback); } int main() {