Skip to content
Open
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 @@ -78,6 +78,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
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,19 @@ App|Description
---|---
[hello_interp](interp/hello_interp) | A bundle of small examples, showing how to access the core-local interpolator hardware, and use most of its features.

### Low Power

These examples demonstrate how to use the pico_low_power library.

App|Description
---|---
[low_power_domant_timer](low_power/low_power_dormant) | Go dormant (disable clocks) and wakeup on a timer. Requires an external clock for when testing with RP2040. See [low_power_clksrc](low_power/low_power_dormant).
[low_power_dormant_gpio](low_power/low_power_dormant) | Go dormant (disable clocks) and wakeup on a GPIO.
[low_power_pstate_timer](low_power/low_power_pstate) | Go to a lower power state (RP2350 only) and restart on an AON timer.
[low_power_pstate_gpio](low_power/low_power_pstate) | Go to a lower power state (RP2350 only) and restart on a GPIO.
[low_power_sleep_timer](low_power/low_power_sleep) | Go to sleep and wakeup on a timer.
[low_power_sleep_gpio](low_power/low_power_sleep) | Go to sleep and wakeup on a GPIO.

### Multicore

App|Description
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;
}
59 changes: 59 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,59 @@
/**
* Copyright (c) 2026 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);
printf("State of gpio %u is %u\n", LOW_POWER_WAKE_GPIO, gpio_get(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) 2026 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)
50 changes: 50 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,50 @@
/**
* Copyright (c) 2026 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

static 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++);

gpio_init(LOW_POWER_WAKE_GPIO);
printf("State of gpio %u is %u\n", LOW_POWER_WAKE_GPIO, gpio_get(LOW_POWER_WAKE_GPIO));

// 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;
}
57 changes: 57 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,57 @@
/**
* Copyright (c) 2026 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

static uint32_t __persistent_data(run_count);
static bool __persistent_data(aon_timer_started);

// 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_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;
}
Loading
Loading