Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ add_subdirectory(gpio)
add_subdirectory(hstx)
add_subdirectory(i2c)
add_subdirectory(interp)
add_subdirectory(low_power)
add_subdirectory(multicore)
add_subdirectory(otp)
add_subdirectory(picoboard)
Expand Down
5 changes: 5 additions & 0 deletions low_power/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
add_subdirectory(low_power_sleep)
add_subdirectory(low_power_dormant)
if (NOT PICO_RP2040)
add_subdirectory(low_power_pstate)
endif()
38 changes: 38 additions & 0 deletions low_power/low_power_dormant/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
add_executable(low_power_dormant_timer
low_power_dormant_timer.c
)
target_link_libraries(low_power_dormant_timer PRIVATE
pico_stdlib
pico_low_power
pico_status_led
)
pico_add_extra_outputs(low_power_dormant_timer)
example_auto_set_url(low_power_dormant_timer)
pico_enable_stdio_usb(low_power_dormant_timer 0)
pico_enable_stdio_uart(low_power_dormant_timer 1)

add_executable(low_power_dormant_gpio
low_power_dormant_gpio.c
)
target_link_libraries(low_power_dormant_gpio PRIVATE
pico_stdlib
pico_low_power
pico_status_led
)
pico_add_extra_outputs(low_power_dormant_gpio)
example_auto_set_url(low_power_dormant_gpio)
pico_enable_stdio_usb(low_power_dormant_gpio 0)
pico_enable_stdio_uart(low_power_dormant_gpio 1)

# firmware for generating a clock on gp21 for running the dormant test on rp2040
# connect the clock out from gp21 to gp20 (or gp22) on the rp2040 running the dormant test
add_executable(low_power_clksrc
low_power_clksrc.c
)
target_link_libraries(low_power_clksrc PRIVATE
pico_stdlib
pico_status_led
)
pico_add_extra_outputs(low_power_clksrc)
pico_enable_stdio_usb(low_power_clksrc 0)
pico_enable_stdio_uart(low_power_clksrc 1)
35 changes: 35 additions & 0 deletions low_power/low_power_dormant/low_power_clksrc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2026 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"

#ifndef RTC_CLOCK_SRC_GPIO_OUT
#define RTC_CLOCK_SRC_GPIO_OUT 21
#endif

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_CLOCK_SRC_GPIO_OUT, CLOCKS_CLK_GPOUT3_CTRL_AUXSRC_VALUE_CLK_USB, 1024); // 48kHz

repeating_timer_t repeat;
add_repeating_timer_ms(500, repeater, NULL, &repeat);

while (true) __wfi();

return 0;
}
58 changes: 58 additions & 0 deletions low_power/low_power_dormant/low_power_dormant_gpio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/low_power.h"
#include "pico/status_led.h"

// GPIO to wait to go high, connect the other end to 3V3 OUT
#ifndef LOW_POWER_WAKE_GPIO
#define LOW_POWER_WAKE_GPIO 15
#endif

#ifndef CLOCK_SOURCE
#if PICO_RP2040
#define CLOCK_SOURCE DORMANT_CLOCK_SOURCE_XOSC
#else
#define CLOCK_SOURCE DORMANT_CLOCK_SOURCE_LPOSC
#endif
#endif

// Got to sleep and wakeup when gpio goes high
int main() {

stdio_init_all();
hard_assert(status_led_init());
gpio_init(LOW_POWER_WAKE_GPIO);

uint32_t count = 1;
while(true) {
status_led_set_state(true);

printf("Wake up, test run: %u\n", count++);

// Wait for gpio to go low
if (gpio_get(LOW_POWER_WAKE_GPIO)) {
printf("Awake until gpio %u goes low\n", LOW_POWER_WAKE_GPIO);
while(gpio_get(LOW_POWER_WAKE_GPIO)) {
tight_loop_contents();
}
}

// go dormant
printf("Dormant until gpio %u goes high\n", LOW_POWER_WAKE_GPIO);
status_led_set_state(false);

int rc = low_power_dormant_until_gpio_pin_state(LOW_POWER_WAKE_GPIO, true, true, CLOCK_SOURCE, NULL);
status_led_set_state(true);
if (rc != PICO_OK) {
printf("low_power_dormant_until_aon_timer returned error %d\n", rc);
hard_assert(false);
}
}
return 0;
}
77 changes: 77 additions & 0 deletions low_power/low_power_dormant/low_power_dormant_timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/low_power.h"
#include "pico/aon_timer.h"
#include "pico/status_led.h"

#ifdef PICO_RP2350
#include "hardware/powman.h"
#endif

// How long to wait
#ifndef AWAKE_TIME_MS
#define AWAKE_TIME_MS 10000
#endif
#ifndef SLEEP_TIME_MS
#define SLEEP_TIME_MS 10000
#endif

#if PICO_RP2040
#ifndef RTC_CLOCK_SRC_GPIO_IN
#define RTC_CLOCK_SRC_GPIO_IN 20
#endif
#endif

#ifndef CLOCK_SOURCE
#if PICO_RP2040
#define CLOCK_SOURCE DORMANT_CLOCK_SOURCE_XOSC
#else
#define CLOCK_SOURCE DORMANT_CLOCK_SOURCE_LPOSC
#endif
#endif

// Got to sleep and wakeup after 5 seconds
// The example will repeatedly wait 10 seconds then switch off for 10 seconds
// The debugger will appear to be unresponsive while the device is off
int main() {
stdio_init_all();
// Must start aon timer
low_power_start_aon_timer_at_time_ms(1776858754000);
#if AWAKE_TIME_MS < 10000
// pause for at least 10s to allow the debugger to attach on power up to allow the device to be re-programmed
printf("Waiting a bit to allow debugger to attach\n");
sleep_ms(10000 - AWAKE_TIME_MS);
#endif
hard_assert(status_led_init());
uint32_t count = 1;
while(true) {
status_led_set_state(true);

printf("Wake up, test run: %u\n", count++);

// Stay awake for a few seconds
printf("Awake for %dms\n", AWAKE_TIME_MS);
sleep_ms(AWAKE_TIME_MS);

// go dormant
printf("Dormant for %dms\n", SLEEP_TIME_MS);
status_led_set_state(false);

#if PICO_RP2040
low_power_set_external_clock_source(RTC_CLOCK_FREQ_HZ, RTC_CLOCK_SRC_GPIO_IN);
#endif
int rc = low_power_dormant_for_ms(SLEEP_TIME_MS, CLOCK_SOURCE, NULL);
status_led_set_state(true);
if (rc != PICO_OK) {
printf("low_power_dormant_for_ms returned error %d\n", rc);
hard_assert(false);
}
}
return 0;
}
27 changes: 27 additions & 0 deletions low_power/low_power_pstate/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
add_executable(low_power_pstate_timer
low_power_pstate_timer.c
)
target_link_libraries(low_power_pstate_timer PRIVATE
pico_stdlib
pico_low_power
pico_status_led
)
pico_set_persistent_data_loc(low_power_pstate_timer 0x20040000) # SRAM1 power domain
pico_add_extra_outputs(low_power_pstate_timer)
example_auto_set_url(low_power_pstate_timer)
pico_enable_stdio_usb(low_power_pstate_timer 0)
pico_enable_stdio_uart(low_power_pstate_timer 1)

add_executable(low_power_pstate_gpio
low_power_pstate_gpio.c
)
target_link_libraries(low_power_pstate_gpio PRIVATE
pico_stdlib
pico_low_power
pico_status_led
)
pico_set_persistent_data_loc(low_power_pstate_gpio 0x20040000) # SRAM1 power domain
pico_add_extra_outputs(low_power_pstate_gpio)
example_auto_set_url(low_power_pstate_gpio)
pico_enable_stdio_usb(low_power_pstate_gpio 0)
pico_enable_stdio_uart(low_power_pstate_gpio 1)
47 changes: 47 additions & 0 deletions low_power/low_power_pstate/low_power_pstate_gpio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/low_power.h"
#include "pico/aon_timer.h"
#include "pico/status_led.h"

// GPIO to wait to go high, connect the other end to 3V3 OUT
#ifndef LOW_POWER_WAKE_GPIO
#define LOW_POWER_WAKE_GPIO 15
#endif

uint32_t __persistent_data(run_count);

// The example will repeatedly wait 10 seconds then switch off for 10 seconds
// The debugger will appear to be unresponsive while the device is off
int main() {
stdio_init_all();

hard_assert(status_led_init());
status_led_set_state(true);

// Scratch register survives power down
printf("Wake up, test run: %u\n", run_count++);

// Wait for gpio to go low
if (gpio_get(LOW_POWER_WAKE_GPIO)) {
printf("Awake until gpio %u goes low\n", LOW_POWER_WAKE_GPIO);
while(gpio_get(LOW_POWER_WAKE_GPIO)) {
tight_loop_contents();
}
}

// power off
printf("Low power until gpio %u goes high\n", LOW_POWER_WAKE_GPIO);
status_led_set_state(false);
int rc = low_power_pstate_until_gpio_pin_state(LOW_POWER_WAKE_GPIO, true, true, NULL, NULL);
status_led_set_state(true);
printf("low_power_pstate_until_aon_timer returned error %d\n", rc);
hard_assert(false); // should never get here!
return 0;
}
55 changes: 55 additions & 0 deletions low_power/low_power_pstate/low_power_pstate_timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/low_power.h"
#include "pico/aon_timer.h"
#include "pico/status_led.h"

// How long to wait
#ifndef AWAKE_TIME_MS
#define AWAKE_TIME_MS 10000
#endif
#ifndef SLEEP_TIME_MS
#define SLEEP_TIME_MS 10000
#endif

uint32_t __persistent_data(run_count);

// The example will repeatedly wait 10 seconds then switch off for 10 seconds
// The debugger will appear to be unresponsive while the device is off
int main() {
stdio_init_all();
// Must start the aon timer if needed
printf("Current time: %llu\n", aon_timer_get_absolute_time());
if (!aon_timer_is_running()) {
low_power_start_aon_timer_at_time_ms(1776858754000);
}
Comment on lines +29 to +31
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to use persistent data here, so that it always sets the time when run? Otherwise when you load this repeatedly using picotool, the time will keep going up and never be reset to the start time

I think this would work

Suggested change
if (!aon_timer_is_running()) {
low_power_start_aon_timer_at_time_ms(1776858754000);
}
static bool __persistent_data(aon_timer_started);
if (!aon_timer_started) {
low_power_start_aon_timer_at_time_ms(1776858754000);
aon_timer_started = true;
}

#if AWAKE_TIME_MS < 10000
// pause for at least 10s to allow the debugger to attach on power up to allow the device to be re-programmed
printf("Waiting a bit to allow debugger to attach\n");
sleep_ms(10000 - AWAKE_TIME_MS);
#endif
hard_assert(status_led_init());
status_led_set_state(true);

// Scratch register survives power down
printf("Wake up, test run: %u\n", run_count++);

// Stay awake for a few seconds
printf("Awake for %dms\n", AWAKE_TIME_MS);
sleep_ms(AWAKE_TIME_MS);

// power off
printf("Low power for %dms\n", SLEEP_TIME_MS);
status_led_set_state(false);
int rc = low_power_pstate_for_ms(SLEEP_TIME_MS, NULL, NULL);
status_led_set_state(true);
printf("low_power_pstate_for_ms returned error %d\n", rc);
hard_assert(false); // should never get here!
return 0;
}
25 changes: 25 additions & 0 deletions low_power/low_power_sleep/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
add_executable(low_power_sleep_timer
low_power_sleep_timer.c
)
target_link_libraries(low_power_sleep_timer PRIVATE
pico_stdlib
pico_low_power
pico_status_led
)
pico_add_extra_outputs(low_power_sleep_timer)
example_auto_set_url(low_power_sleep_timer)
pico_enable_stdio_usb(low_power_sleep_timer 0)
pico_enable_stdio_uart(low_power_sleep_timer 1)

add_executable(low_power_sleep_gpio
low_power_sleep_gpio.c
)
target_link_libraries(low_power_sleep_gpio PRIVATE
pico_stdlib
pico_low_power
pico_status_led
)
pico_add_extra_outputs(low_power_sleep_gpio)
example_auto_set_url(low_power_sleep_gpio)
pico_enable_stdio_usb(low_power_sleep_gpio 0)
pico_enable_stdio_uart(low_power_sleep_gpio 1)
Loading
Loading