Add RTC deep sleep alarm support

This commit is contained in:
Lucian Copeland 2021-05-28 13:52:05 -04:00
parent 24041f34b0
commit feff243e8f
7 changed files with 49 additions and 22 deletions

View File

@ -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"

View File

@ -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) {

View File

@ -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();

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);