From c122d46557a7ed94fe270f24c86916e1d9fa1213 Mon Sep 17 00:00:00 2001 From: ghubcoder Date: Mon, 25 Oct 2021 19:43:25 +0100 Subject: [PATCH] Raspberry Pico Sleep Demo --- .gitmodules | 3 + README.md | 33 ++++++ lib/fsp | 2 +- lib/pico-extras | 1 + lib/stm32lib | 2 +- ports/rp2/CMakeLists.txt | 12 +++ ports/rp2/boards/RPI_PICO/mpconfigboard.h | 2 +- ports/rp2/boards/RPI_PICO_W/mpconfigboard.h | 2 +- ports/rp2/modpicosleep.c | 113 ++++++++++++++++++++ ports/rp2/mpconfigport.h | 2 + ports/rp2/pico_extras_import.cmake | 63 +++++++++++ 11 files changed, 231 insertions(+), 4 deletions(-) create mode 160000 lib/pico-extras create mode 100644 ports/rp2/modpicosleep.c create mode 100644 ports/rp2/pico_extras_import.cmake diff --git a/.gitmodules b/.gitmodules index 75bffdadddeb8..95675132938ef 100644 --- a/.gitmodules +++ b/.gitmodules @@ -59,3 +59,6 @@ [submodule "lib/protobuf-c"] path = lib/protobuf-c url = https://github.com/protobuf-c/protobuf-c.git +[submodule "lib/pico-extras"] + path = lib/pico-extras + url = https://github.com/raspberrypi/pico-extras.git diff --git a/README.md b/README.md index f5bc6d78f0a40..ca2450ea292b6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,38 @@ [![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) +This is a fork of the MicroPython project to allow deep sleeping and waking +from the internal real time clock of the Raspberry Pico. + +This can be built with the following commands: + +```bash +git clone https://github.com/ghubcoder/micropython-pico-deepsleep.git +cd micropython-pico-deepsleep/ +make -C mpy-cross/ +git submodule update --init -- lib/pico-sdk +git submodule update --init -- lib/pico-extras +git submodule update --init -- lib/tinyusb +cd ports/rp2sleep +make -j4 +``` + +This will create a `firmware.uf2` file which can then be loaded onto your +Pico in the usual way using the BOOTSEL button. + +A precompiled binary can be found [here](https://github.com/ghubcoder/micropython-pico-deepsleep/releases/tag/v1.1-pico-deepsleep). + +Example usage: + +```python +import picosleep +picosleep.seconds(60) +``` + +Please see [this](https://ghubcoder.github.io/posts/deep-sleeping-the-pico-micropython/) +post for more information. + +Original readme follows: + The MicroPython project =======================

diff --git a/lib/fsp b/lib/fsp index e78939d32d1cc..55bffd3a71cbe 160000 --- a/lib/fsp +++ b/lib/fsp @@ -1 +1 @@ -Subproject commit e78939d32d1ccea9f0ba8bb42c51aceffd386b9b +Subproject commit 55bffd3a71cbeed2104cf30e7a39b641d8c1ff48 diff --git a/lib/pico-extras b/lib/pico-extras new file mode 160000 index 0000000000000..2309d56a3af1d --- /dev/null +++ b/lib/pico-extras @@ -0,0 +1 @@ +Subproject commit 2309d56a3af1df697b33275073c98e92ac93b196 diff --git a/lib/stm32lib b/lib/stm32lib index 928df866e4d28..eb80f0126e506 160000 --- a/lib/stm32lib +++ b/lib/stm32lib @@ -1 +1 @@ -Subproject commit 928df866e4d287ebc3c60726151513ebee609128 +Subproject commit eb80f0126e50687aac966f4c39a2b5a5deffbe78 diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 3a46fdaa7f47b..c9fa6746d4916 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -14,6 +14,12 @@ else() set(PICO_SDK_PATH ../../lib/pico-sdk) endif() +if (PICO_EXTRAS_PATH_OVERRIDE) + set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH_OVERRIDE}) +else() + set(PICO_EXTRAS_PATH ../../lib/pico-extras) +endif() + # Use the local tinyusb instead of the one in pico-sdk set(PICO_TINYUSB_PATH ${MICROPY_DIR}/lib/tinyusb) # Use the local lwip instead of the one in pico-sdk @@ -71,6 +77,7 @@ string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/tinyusb) include(${MICROPY_DIR}/py/py.cmake) include(${MICROPY_DIR}/extmod/extmod.cmake) include(${PICO_SDK_PATH}/pico_sdk_init.cmake) +include(pico_extras_import.cmake) # Define the top-level project project(${MICROPY_TARGET}) @@ -125,6 +132,7 @@ set(MICROPY_SOURCE_PORT machine_spi.c machine_timer.c main.c + modpicosleep.c modrp2.c mphalport.c mpnetworkport.c @@ -154,6 +162,7 @@ set(MICROPY_SOURCE_QSTR ${MICROPY_PORT_DIR}/machine_timer.c ${MICROPY_PORT_DIR}/machine_uart.c ${MICROPY_PORT_DIR}/machine_wdt.c + ${MICROPY_PORT_DIR}/modpicosleep.c ${MICROPY_PORT_DIR}/modrp2.c ${MICROPY_PORT_DIR}/modos.c ${MICROPY_PORT_DIR}/rp2_flash.c @@ -177,6 +186,8 @@ set(PICO_SDK_COMPONENTS hardware_pwm hardware_regs hardware_rtc + hardware_rosc + hardware_sleep hardware_spi hardware_structs hardware_sync @@ -189,6 +200,7 @@ set(PICO_SDK_COMPONENTS pico_bootrom pico_multicore pico_platform + pico_runtime pico_stdio pico_stdlib pico_sync diff --git a/ports/rp2/boards/RPI_PICO/mpconfigboard.h b/ports/rp2/boards/RPI_PICO/mpconfigboard.h index c39bc4d489bb6..aee239621ea8c 100644 --- a/ports/rp2/boards/RPI_PICO/mpconfigboard.h +++ b/ports/rp2/boards/RPI_PICO/mpconfigboard.h @@ -1,3 +1,3 @@ // Board and hardware specific configuration -#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico" +#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico (sleep)" #define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024) diff --git a/ports/rp2/boards/RPI_PICO_W/mpconfigboard.h b/ports/rp2/boards/RPI_PICO_W/mpconfigboard.h index ef812b6301356..dfbe0906d3916 100644 --- a/ports/rp2/boards/RPI_PICO_W/mpconfigboard.h +++ b/ports/rp2/boards/RPI_PICO_W/mpconfigboard.h @@ -1,5 +1,5 @@ // Board and hardware specific configuration -#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico W" +#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico W (sleep)" // todo: We need something to check our binary size #define MICROPY_HW_FLASH_STORAGE_BYTES (848 * 1024) diff --git a/ports/rp2/modpicosleep.c b/ports/rp2/modpicosleep.c new file mode 100644 index 0000000000000..2b4be7e8a33a9 --- /dev/null +++ b/ports/rp2/modpicosleep.c @@ -0,0 +1,113 @@ + +#include "py/runtime.h" +#include "pico/sleep.h" +#include "pico/stdlib.h" +#include +#include +#include +#include +#include +#include "hardware/clocks.h" +#include "hardware/rosc.h" +#include "hardware/structs/scb.h" + +static void sleep_callback(void) +{ + return; +} + +static void rtc_sleep_seconds(uint32_t seconds_to_sleep) +{ + + // Hangs if we attempt to sleep for 1 second.... + // Guard against this and perform a normal sleep + if (seconds_to_sleep == 1) + { + sleep_ms(1000); + return; + } + + int y = 2020, m = 6, d = 5, hour = 15, mins = 45, secs = 0; + struct tm t = {.tm_year = y - 1900, + .tm_mon = m - 1, + .tm_mday = d, + .tm_hour = hour, + .tm_min = mins, + .tm_sec = secs}; + + t.tm_sec += seconds_to_sleep; + mktime(&t); + + datetime_t t_alarm = { + .year = t.tm_year + 1900, + .month = t.tm_mon + 1, + .day = t.tm_mday, + .dotw = t.tm_wday, // 0 is Sunday, so 5 is Friday + .hour = t.tm_hour, + .min = t.tm_min, + .sec = t.tm_sec}; + + sleep_goto_sleep_until(&t_alarm, &sleep_callback); +} + +void recover_from_sleep(uint scb_orig, uint clock0_orig, uint clock1_orig) +{ + + // Re-enable ring Oscillator control + rosc_write(&rosc_hw->ctrl, ROSC_CTRL_ENABLE_BITS); + + // reset procs back to default + scb_hw->scr = scb_orig; + clocks_hw->sleep_en0 = clock0_orig; + clocks_hw->sleep_en1 = clock1_orig; + + // reset clocks + clocks_init(); + stdio_init_all(); + + return; +} + +STATIC mp_obj_t picosleep_seconds(mp_obj_t seconds_obj) +{ + mp_int_t seconds = mp_obj_get_int(seconds_obj); + stdio_init_all(); + // save values for later + uint scb_orig = scb_hw->scr; + uint clock0_orig = clocks_hw->sleep_en0; + uint clock1_orig = clocks_hw->sleep_en1; + + // crudely reset the clock each time + // to the value below + datetime_t t = { + .year = 2020, + .month = 06, + .day = 05, + .dotw = 5, // 0 is Sunday, so 5 is Friday + .hour = 15, + .min = 45, + .sec = 00}; + + // Start the Real time clock + rtc_init(); + sleep_run_from_xosc(); + rtc_set_datetime(&t); + rtc_sleep_seconds(seconds); + recover_from_sleep(scb_orig, clock0_orig, clock1_orig); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(picosleep_seconds_obj, picosleep_seconds); + +STATIC const mp_rom_map_elem_t picosleep_module_globals_table[] = { + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picosleep)}, + {MP_ROM_QSTR(MP_QSTR_seconds), MP_ROM_PTR(&picosleep_seconds_obj)}, +}; +STATIC MP_DEFINE_CONST_DICT(picosleep_module_globals, picosleep_module_globals_table); + +const mp_obj_module_t mp_module_picosleep = { + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&picosleep_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_picosleep, mp_module_picosleep); \ No newline at end of file diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 8f073002e8632..2eeed7925a25e 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -185,6 +185,8 @@ #endif #endif +extern const struct _mp_obj_module_t mp_module_picosleep; + #if MICROPY_PY_NETWORK_CYW43 extern const struct _mp_obj_type_t mp_network_cyw43_type; #define MICROPY_HW_NIC_CYW43 \ diff --git a/ports/rp2/pico_extras_import.cmake b/ports/rp2/pico_extras_import.cmake new file mode 100644 index 0000000000000..c7117c4f8105f --- /dev/null +++ b/ports/rp2/pico_extras_import.cmake @@ -0,0 +1,63 @@ +# This is a copy of /external/pico_extras_import.cmake + +# This can be dropped into an external project to help locate pico-extras +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_EXTRAS_PATH} AND (NOT PICO_EXTRAS_PATH)) + set(PICO_EXTRAS_PATH $ENV{PICO_EXTRAS_PATH}) + message("Using PICO_EXTRAS_PATH from environment ('${PICO_EXTRAS_PATH}')") +endif () + +if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT)) + set(PICO_EXTRAS_FETCH_FROM_GIT $ENV{PICO_EXTRAS_FETCH_FROM_GIT}) + message("Using PICO_EXTRAS_FETCH_FROM_GIT from environment ('${PICO_EXTRAS_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT_PATH)) + set(PICO_EXTRAS_FETCH_FROM_GIT_PATH $ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH}) + message("Using PICO_EXTRAS_FETCH_FROM_GIT_PATH from environment ('${PICO_EXTRAS_FETCH_FROM_GIT_PATH}')") +endif () + +if (NOT PICO_EXTRAS_PATH) + if (PICO_EXTRAS_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_EXTRAS_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_extras + GIT_REPOSITORY https://github.com/raspberrypi/pico-extras + GIT_TAG master + ) + if (NOT pico_extras) + message("Downloading Raspberry Pi Pico Extras") + FetchContent_Populate(pico_extras) + set(PICO_EXTRAS_PATH ${pico_extras_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + if (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../pico-extras") + set(PICO_EXTRAS_PATH ${PICO_SDK_PATH}/../pico-extras) + message("Defaulting PICO_EXTRAS_PATH as sibling of PICO_SDK_PATH: ${PICO_EXTRAS_PATH}") + else() + message(FATAL_ERROR + "PICO EXTRAS location was not specified. Please set PICO_EXTRAS_PATH or set PICO_EXTRAS_FETCH_FROM_GIT to on to fetch from git." + ) + endif() + endif () +endif () + +set(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" CACHE PATH "Path to the PICO EXTRAS") +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") +set(PICO_EXTRAS_FETCH_FROM_GIT_PATH "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download EXTRAS") + +get_filename_component(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" REALPATH BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") +message("PICO_EXTRAS_PATH is ${CMAKE_CURRENT_LIST_DIR}") +if (NOT EXISTS ${PICO_EXTRAS_PATH}) + message(FATAL_ERROR "Directory '${PICO_EXTRAS_PATH}' not found") +endif () + +set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH} CACHE PATH "Path to the PICO EXTRAS" FORCE) + +add_subdirectory(${PICO_EXTRAS_PATH} pico_extras) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy