From feff243e8fe84be080a8265c21d79606b2437a65 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 28 May 2021 13:52:05 -0400 Subject: [PATCH] Add RTC deep sleep alarm support --- locale/circuitpython.pot | 4 -- .../common-hal/alarm/SleepMemory.c | 2 +- ports/raspberrypi/common-hal/alarm/__init__.c | 49 +++++++++++++------ .../common-hal/alarm/pin/PinAlarm.c | 7 +++ .../common-hal/alarm/pin/PinAlarm.h | 1 + .../common-hal/alarm/time/TimeAlarm.c | 7 ++- .../common-hal/alarm/time/TimeAlarm.h | 1 + 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 5198c7d924..a710b1effb 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -611,10 +611,6 @@ msgstr "" msgid "Can't set CCCD on local Characteristic" msgstr "" -#: ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c -msgid "Cannot alarm from RTC in deep sleep" -msgstr "" - #: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c #: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c msgid "Cannot change USB devices now" diff --git a/ports/raspberrypi/common-hal/alarm/SleepMemory.c b/ports/raspberrypi/common-hal/alarm/SleepMemory.c index 4cf7abe305..a444cbf207 100644 --- a/ports/raspberrypi/common-hal/alarm/SleepMemory.c +++ b/ports/raspberrypi/common-hal/alarm/SleepMemory.c @@ -40,7 +40,7 @@ void alarm_sleep_memory_reset(void) { } uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) { - return 0;//sizeof(_sleep_mem); + return 0;// sizeof(_sleep_mem); } bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t *values, uint32_t len) { diff --git a/ports/raspberrypi/common-hal/alarm/__init__.c b/ports/raspberrypi/common-hal/alarm/__init__.c index ebed6286cd..7f22242e9f 100644 --- a/ports/raspberrypi/common-hal/alarm/__init__.c +++ b/ports/raspberrypi/common-hal/alarm/__init__.c @@ -58,25 +58,31 @@ // Not used elsewhere in the SDK for now, keep an eye on it #define RP_WKUP_SCRATCH_REG 0 -// Turn off nonvolatile Busio and other wake-only peripherals +// Light sleep turns off nonvolatile Busio and other wake-only peripherals // TODO: this only saves about 2mA right now, expand with other non-essentials const uint32_t RP_LIGHTSLEEP_EN0_MASK = ~( - CLOCKS_SLEEP_EN0_CLK_SYS_SPI1_BITS & - CLOCKS_SLEEP_EN0_CLK_PERI_SPI1_BITS & - CLOCKS_SLEEP_EN0_CLK_SYS_SPI0_BITS & - CLOCKS_SLEEP_EN0_CLK_PERI_SPI0_BITS & - CLOCKS_SLEEP_EN0_CLK_SYS_PWM_BITS & - CLOCKS_SLEEP_EN0_CLK_SYS_PIO1_BITS & - CLOCKS_SLEEP_EN0_CLK_SYS_PIO0_BITS & - CLOCKS_SLEEP_EN0_CLK_SYS_I2C1_BITS & - CLOCKS_SLEEP_EN0_CLK_SYS_I2C0_BITS & - CLOCKS_SLEEP_EN0_CLK_SYS_ADC_BITS & + CLOCKS_SLEEP_EN0_CLK_SYS_SPI1_BITS | + CLOCKS_SLEEP_EN0_CLK_PERI_SPI1_BITS | + CLOCKS_SLEEP_EN0_CLK_SYS_SPI0_BITS | + CLOCKS_SLEEP_EN0_CLK_PERI_SPI0_BITS | + CLOCKS_SLEEP_EN0_CLK_SYS_PWM_BITS | + CLOCKS_SLEEP_EN0_CLK_SYS_PIO1_BITS | + CLOCKS_SLEEP_EN0_CLK_SYS_PIO0_BITS | + CLOCKS_SLEEP_EN0_CLK_SYS_I2C1_BITS | + CLOCKS_SLEEP_EN0_CLK_SYS_I2C0_BITS | + CLOCKS_SLEEP_EN0_CLK_SYS_ADC_BITS | CLOCKS_SLEEP_EN0_CLK_ADC_ADC_BITS ); - // This bank has the USB clocks in it, leave it for now const uint32_t RP_LIGHTSLEEP_EN1_MASK = CLOCKS_SLEEP_EN1_RESET; +// Light sleeps used for TimeAlarm deep sleep turn off almost everything +const uint32_t RP_LIGHTSLEEP_EN0_MASK_HARSH = ( + CLOCKS_SLEEP_EN0_CLK_RTC_RTC_BITS | + CLOCKS_SLEEP_EN0_CLK_SYS_PADS_BITS + ); +const uint32_t RP_LIGHTSLEEP_EN1_MASK_HARSH = 0x0; + STATIC void prepare_for_dormant_xosc(void); // Singleton instance of SleepMemory. @@ -144,7 +150,6 @@ mp_obj_t common_hal_alarm_create_wake_alarm(void) { mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { _setup_sleep_alarms(false, n_alarms, alarms); - // alarm_pin_pinalarm_light_reset(); mp_obj_t wake_alarm = mp_const_none; @@ -173,7 +178,6 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj // Prune the clock for sleep clocks_hw->sleep_en0 &= RP_LIGHTSLEEP_EN0_MASK; clocks_hw->sleep_en1 = RP_LIGHTSLEEP_EN1_MASK; - // port_idle_until_interrupt(); // Enable System Control Block (SCB) deep sleep uint save = scb_hw->scr; @@ -195,8 +199,21 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala } void NORETURN common_hal_alarm_enter_deep_sleep(void) { - prepare_for_dormant_xosc(); - xosc_dormant(); + bool timealarm_set = alarm_time_timealarm_is_set(); + + // If there's a timealarm, just enter a very deep light sleep + if (timealarm_set) { + // Prune the clock for sleep + clocks_hw->sleep_en0 &= RP_LIGHTSLEEP_EN0_MASK_HARSH; + clocks_hw->sleep_en1 = RP_LIGHTSLEEP_EN1_MASK_HARSH; + // Enable System Control Block (SCB) deep sleep + uint save = scb_hw->scr; + scb_hw->scr = save | M0PLUS_SCR_SLEEPDEEP_BITS; + __wfi(); + } else { + prepare_for_dormant_xosc(); + xosc_dormant(); + } // // TODO: support ROSC when available in SDK // rosc_set_dormant(); diff --git a/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.c b/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.c index 72958ced87..276e2e409a 100644 --- a/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.c +++ b/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.c @@ -38,6 +38,7 @@ STATIC bool woke_up; STATIC uint64_t alarm_triggered_pins; // 36 actual pins STATIC uint64_t alarm_reserved_pins; // 36 actual pins +STATIC bool _pinalarm_set = false; #define GPIO_IRQ_ALL_EVENTS 0x15u @@ -152,6 +153,12 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob if (deep_sleep) { gpio_set_dormant_irq_enabled((uint)alarm->pin->number, event, true); } + + _pinalarm_set = true; } } } + +bool alarm_pin_pinalarm_is_set(void) { + return _pinalarm_set; +} diff --git a/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.h b/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.h index cd1a21fd0d..d31ac6c878 100644 --- a/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.h +++ b/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.h @@ -42,3 +42,4 @@ void alarm_pin_pinalarm_reset(void); void alarm_pin_pinalarm_light_reset(void); void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); bool alarm_pin_pinalarm_woke_this_cycle(void); +bool alarm_pin_pinalarm_is_set(void); diff --git a/ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c b/ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c index cb09b2a306..4302e9e8cd 100644 --- a/ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c +++ b/ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c @@ -35,6 +35,7 @@ #include "hardware/rtc.h" STATIC bool woke_up = false; +STATIC bool _timealarm_set = false; void timer_callback(void) { woke_up = true; @@ -92,7 +93,7 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ return; } if (deep_sleep) { - mp_raise_ValueError(translate("Cannot alarm from RTC in deep sleep")); + _timealarm_set = true; } // Compute how long to actually sleep, considering the time now. @@ -123,3 +124,7 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ woke_up = false; } + +bool alarm_time_timealarm_is_set(void) { + return _timealarm_set; +} diff --git a/ports/raspberrypi/common-hal/alarm/time/TimeAlarm.h b/ports/raspberrypi/common-hal/alarm/time/TimeAlarm.h index 233a881e6e..d5248551ae 100644 --- a/ports/raspberrypi/common-hal/alarm/time/TimeAlarm.h +++ b/ports/raspberrypi/common-hal/alarm/time/TimeAlarm.h @@ -38,3 +38,4 @@ mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void); void alarm_time_timealarm_reset(void); void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); bool alarm_time_timealarm_woke_this_cycle(void); +bool alarm_time_timealarm_is_set(void);