Skip to content

Commit c122d46

Browse files
committed
Raspberry Pico Sleep Demo
1 parent 0432f73 commit c122d46

File tree

11 files changed

+231
-4
lines changed

11 files changed

+231
-4
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,6 @@
5959
[submodule "lib/protobuf-c"]
6060
path = lib/protobuf-c
6161
url = https://github.com/protobuf-c/protobuf-c.git
62+
[submodule "lib/pico-extras"]
63+
path = lib/pico-extras
64+
url = https://github.com/raspberrypi/pico-extras.git

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,38 @@
11
[![Unix CI badge](https://github.com/micropython/micropython/actions/workflows/ports_unix.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![STM32 CI badge](https://github.com/micropython/micropython/actions/workflows/ports_stm32.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![Docs CI badge](https://github.com/micropython/micropython/actions/workflows/docs.yml/badge.svg)](https://docs.micropython.org/) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
22

3+
This is a fork of the MicroPython project to allow deep sleeping and waking
4+
from the internal real time clock of the Raspberry Pico.
5+
6+
This can be built with the following commands:
7+
8+
```bash
9+
git clone https://github.com/ghubcoder/micropython-pico-deepsleep.git
10+
cd micropython-pico-deepsleep/
11+
make -C mpy-cross/
12+
git submodule update --init -- lib/pico-sdk
13+
git submodule update --init -- lib/pico-extras
14+
git submodule update --init -- lib/tinyusb
15+
cd ports/rp2sleep
16+
make -j4
17+
```
18+
19+
This will create a `firmware.uf2` file which can then be loaded onto your
20+
Pico in the usual way using the BOOTSEL button.
21+
22+
A precompiled binary can be found [here](https://github.com/ghubcoder/micropython-pico-deepsleep/releases/tag/v1.1-pico-deepsleep).
23+
24+
Example usage:
25+
26+
```python
27+
import picosleep
28+
picosleep.seconds(60)
29+
```
30+
31+
Please see [this](https://ghubcoder.github.io/posts/deep-sleeping-the-pico-micropython/)
32+
post for more information.
33+
34+
Original readme follows:
35+
336
The MicroPython project
437
=======================
538
<p align="center">

lib/fsp

Submodule fsp updated 1930 files

lib/pico-extras

Submodule pico-extras added at 2309d56

lib/stm32lib

Submodule stm32lib updated 842 files

ports/rp2/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ else()
1414
set(PICO_SDK_PATH ../../lib/pico-sdk)
1515
endif()
1616

17+
if (PICO_EXTRAS_PATH_OVERRIDE)
18+
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH_OVERRIDE})
19+
else()
20+
set(PICO_EXTRAS_PATH ../../lib/pico-extras)
21+
endif()
22+
1723
# Use the local tinyusb instead of the one in pico-sdk
1824
set(PICO_TINYUSB_PATH ${MICROPY_DIR}/lib/tinyusb)
1925
# Use the local lwip instead of the one in pico-sdk
@@ -71,6 +77,7 @@ string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/tinyusb)
7177
include(${MICROPY_DIR}/py/py.cmake)
7278
include(${MICROPY_DIR}/extmod/extmod.cmake)
7379
include(${PICO_SDK_PATH}/pico_sdk_init.cmake)
80+
include(pico_extras_import.cmake)
7481

7582
# Define the top-level project
7683
project(${MICROPY_TARGET})
@@ -125,6 +132,7 @@ set(MICROPY_SOURCE_PORT
125132
machine_spi.c
126133
machine_timer.c
127134
main.c
135+
modpicosleep.c
128136
modrp2.c
129137
mphalport.c
130138
mpnetworkport.c
@@ -154,6 +162,7 @@ set(MICROPY_SOURCE_QSTR
154162
${MICROPY_PORT_DIR}/machine_timer.c
155163
${MICROPY_PORT_DIR}/machine_uart.c
156164
${MICROPY_PORT_DIR}/machine_wdt.c
165+
${MICROPY_PORT_DIR}/modpicosleep.c
157166
${MICROPY_PORT_DIR}/modrp2.c
158167
${MICROPY_PORT_DIR}/modos.c
159168
${MICROPY_PORT_DIR}/rp2_flash.c
@@ -177,6 +186,8 @@ set(PICO_SDK_COMPONENTS
177186
hardware_pwm
178187
hardware_regs
179188
hardware_rtc
189+
hardware_rosc
190+
hardware_sleep
180191
hardware_spi
181192
hardware_structs
182193
hardware_sync
@@ -189,6 +200,7 @@ set(PICO_SDK_COMPONENTS
189200
pico_bootrom
190201
pico_multicore
191202
pico_platform
203+
pico_runtime
192204
pico_stdio
193205
pico_stdlib
194206
pico_sync
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// Board and hardware specific configuration
2-
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico"
2+
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico (sleep)"
33
#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024)

ports/rp2/boards/RPI_PICO_W/mpconfigboard.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Board and hardware specific configuration
2-
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico W"
2+
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico W (sleep)"
33

44
// todo: We need something to check our binary size
55
#define MICROPY_HW_FLASH_STORAGE_BYTES (848 * 1024)

ports/rp2/modpicosleep.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
2+
#include "py/runtime.h"
3+
#include "pico/sleep.h"
4+
#include "pico/stdlib.h"
5+
#include <stdint.h>
6+
#include <string.h>
7+
#include <stdio.h>
8+
#include <time.h>
9+
#include <stdlib.h>
10+
#include "hardware/clocks.h"
11+
#include "hardware/rosc.h"
12+
#include "hardware/structs/scb.h"
13+
14+
static void sleep_callback(void)
15+
{
16+
return;
17+
}
18+
19+
static void rtc_sleep_seconds(uint32_t seconds_to_sleep)
20+
{
21+
22+
// Hangs if we attempt to sleep for 1 second....
23+
// Guard against this and perform a normal sleep
24+
if (seconds_to_sleep == 1)
25+
{
26+
sleep_ms(1000);
27+
return;
28+
}
29+
30+
int y = 2020, m = 6, d = 5, hour = 15, mins = 45, secs = 0;
31+
struct tm t = {.tm_year = y - 1900,
32+
.tm_mon = m - 1,
33+
.tm_mday = d,
34+
.tm_hour = hour,
35+
.tm_min = mins,
36+
.tm_sec = secs};
37+
38+
t.tm_sec += seconds_to_sleep;
39+
mktime(&t);
40+
41+
datetime_t t_alarm = {
42+
.year = t.tm_year + 1900,
43+
.month = t.tm_mon + 1,
44+
.day = t.tm_mday,
45+
.dotw = t.tm_wday, // 0 is Sunday, so 5 is Friday
46+
.hour = t.tm_hour,
47+
.min = t.tm_min,
48+
.sec = t.tm_sec};
49+
50+
sleep_goto_sleep_until(&t_alarm, &sleep_callback);
51+
}
52+
53+
void recover_from_sleep(uint scb_orig, uint clock0_orig, uint clock1_orig)
54+
{
55+
56+
// Re-enable ring Oscillator control
57+
rosc_write(&rosc_hw->ctrl, ROSC_CTRL_ENABLE_BITS);
58+
59+
// reset procs back to default
60+
scb_hw->scr = scb_orig;
61+
clocks_hw->sleep_en0 = clock0_orig;
62+
clocks_hw->sleep_en1 = clock1_orig;
63+
64+
// reset clocks
65+
clocks_init();
66+
stdio_init_all();
67+
68+
return;
69+
}
70+
71+
STATIC mp_obj_t picosleep_seconds(mp_obj_t seconds_obj)
72+
{
73+
mp_int_t seconds = mp_obj_get_int(seconds_obj);
74+
stdio_init_all();
75+
// save values for later
76+
uint scb_orig = scb_hw->scr;
77+
uint clock0_orig = clocks_hw->sleep_en0;
78+
uint clock1_orig = clocks_hw->sleep_en1;
79+
80+
// crudely reset the clock each time
81+
// to the value below
82+
datetime_t t = {
83+
.year = 2020,
84+
.month = 06,
85+
.day = 05,
86+
.dotw = 5, // 0 is Sunday, so 5 is Friday
87+
.hour = 15,
88+
.min = 45,
89+
.sec = 00};
90+
91+
// Start the Real time clock
92+
rtc_init();
93+
sleep_run_from_xosc();
94+
rtc_set_datetime(&t);
95+
rtc_sleep_seconds(seconds);
96+
recover_from_sleep(scb_orig, clock0_orig, clock1_orig);
97+
98+
return mp_const_none;
99+
}
100+
MP_DEFINE_CONST_FUN_OBJ_1(picosleep_seconds_obj, picosleep_seconds);
101+
102+
STATIC const mp_rom_map_elem_t picosleep_module_globals_table[] = {
103+
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picosleep)},
104+
{MP_ROM_QSTR(MP_QSTR_seconds), MP_ROM_PTR(&picosleep_seconds_obj)},
105+
};
106+
STATIC MP_DEFINE_CONST_DICT(picosleep_module_globals, picosleep_module_globals_table);
107+
108+
const mp_obj_module_t mp_module_picosleep = {
109+
.base = {&mp_type_module},
110+
.globals = (mp_obj_dict_t *)&picosleep_module_globals,
111+
};
112+
113+
MP_REGISTER_MODULE(MP_QSTR_picosleep, mp_module_picosleep);

ports/rp2/mpconfigport.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@
185185
#endif
186186
#endif
187187

188+
extern const struct _mp_obj_module_t mp_module_picosleep;
189+
188190
#if MICROPY_PY_NETWORK_CYW43
189191
extern const struct _mp_obj_type_t mp_network_cyw43_type;
190192
#define MICROPY_HW_NIC_CYW43 \

ports/rp2/pico_extras_import.cmake

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# This is a copy of <PICO_EXTRAS_PATH>/external/pico_extras_import.cmake
2+
3+
# This can be dropped into an external project to help locate pico-extras
4+
# It should be include()ed prior to project()
5+
6+
if (DEFINED ENV{PICO_EXTRAS_PATH} AND (NOT PICO_EXTRAS_PATH))
7+
set(PICO_EXTRAS_PATH $ENV{PICO_EXTRAS_PATH})
8+
message("Using PICO_EXTRAS_PATH from environment ('${PICO_EXTRAS_PATH}')")
9+
endif ()
10+
11+
if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT))
12+
set(PICO_EXTRAS_FETCH_FROM_GIT $ENV{PICO_EXTRAS_FETCH_FROM_GIT})
13+
message("Using PICO_EXTRAS_FETCH_FROM_GIT from environment ('${PICO_EXTRAS_FETCH_FROM_GIT}')")
14+
endif ()
15+
16+
if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT_PATH))
17+
set(PICO_EXTRAS_FETCH_FROM_GIT_PATH $ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH})
18+
message("Using PICO_EXTRAS_FETCH_FROM_GIT_PATH from environment ('${PICO_EXTRAS_FETCH_FROM_GIT_PATH}')")
19+
endif ()
20+
21+
if (NOT PICO_EXTRAS_PATH)
22+
if (PICO_EXTRAS_FETCH_FROM_GIT)
23+
include(FetchContent)
24+
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
25+
if (PICO_EXTRAS_FETCH_FROM_GIT_PATH)
26+
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
27+
endif ()
28+
FetchContent_Declare(
29+
pico_extras
30+
GIT_REPOSITORY https://github.com/raspberrypi/pico-extras
31+
GIT_TAG master
32+
)
33+
if (NOT pico_extras)
34+
message("Downloading Raspberry Pi Pico Extras")
35+
FetchContent_Populate(pico_extras)
36+
set(PICO_EXTRAS_PATH ${pico_extras_SOURCE_DIR})
37+
endif ()
38+
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
39+
else ()
40+
if (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../pico-extras")
41+
set(PICO_EXTRAS_PATH ${PICO_SDK_PATH}/../pico-extras)
42+
message("Defaulting PICO_EXTRAS_PATH as sibling of PICO_SDK_PATH: ${PICO_EXTRAS_PATH}")
43+
else()
44+
message(FATAL_ERROR
45+
"PICO EXTRAS location was not specified. Please set PICO_EXTRAS_PATH or set PICO_EXTRAS_FETCH_FROM_GIT to on to fetch from git."
46+
)
47+
endif()
48+
endif ()
49+
endif ()
50+
51+
set(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" CACHE PATH "Path to the PICO EXTRAS")
52+
set(PICO_EXTRAS_FETCH_FROM_GIT "${PICO_EXTRAS_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of PICO EXTRAS from git if not otherwise locatable")
53+
set(PICO_EXTRAS_FETCH_FROM_GIT_PATH "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download EXTRAS")
54+
55+
get_filename_component(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" REALPATH BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
56+
message("PICO_EXTRAS_PATH is ${CMAKE_CURRENT_LIST_DIR}")
57+
if (NOT EXISTS ${PICO_EXTRAS_PATH})
58+
message(FATAL_ERROR "Directory '${PICO_EXTRAS_PATH}' not found")
59+
endif ()
60+
61+
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH} CACHE PATH "Path to the PICO EXTRAS" FORCE)
62+
63+
add_subdirectory(${PICO_EXTRAS_PATH} pico_extras)

0 commit comments

Comments
 (0)