Style changes and wakeup detection

This commit is contained in:
Lucian Copeland 2021-03-27 13:16:12 -04:00
parent d8a2d69e10
commit 529fb52309
9 changed files with 88 additions and 59 deletions

24
main.c
View File

@ -323,12 +323,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
rgb_status_animation_t animation;
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
bool asleep = false;
bool fake_sleeping = false;
while (true) {
RUN_BACKGROUND_TASKS;
if (reload_requested) {
#if CIRCUITPY_ALARM
if (asleep) {
if (fake_sleeping) {
board_init();
}
#endif
@ -339,7 +339,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
if (serial_connected() && serial_bytes_available()) {
#if CIRCUITPY_ALARM
if (asleep) {
if (fake_sleeping) {
board_init();
}
#endif
@ -355,7 +355,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
// an alarm alerts faster than our USB delay or if we pretended to deep
// sleep.
#if CIRCUITPY_ALARM
if (asleep && common_hal_alarm_woken_from_sleep()) {
if (fake_sleeping && common_hal_alarm_woken_from_sleep()) {
serial_write_compressed(translate("Woken up by alarm.\n"));
board_init();
supervisor_set_run_reason(RUN_REASON_STARTUP);
@ -394,14 +394,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
if (result.return_code & PYEXEC_DEEP_SLEEP) {
// Make sure we have been awake long enough for USB to connect (enumeration delay).
int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL);
if (connecting_delay_ticks > 0) {
// Set when we've waited long enough so that we wake up from the
// port_idle_until_interrupt below and loop around to the real deep
// sleep in the else clause.
port_interrupt_after_ticks(connecting_delay_ticks);
// Deep sleep if we're not connected to a host.
} else if (!asleep) {
asleep = true;
// Until it's safe to decide whether we're real/fake sleeping, just run the RGB
// if (connecting_delay_ticks > 0) {
// port_interrupt_after_ticks(connecting_delay_ticks);
// // } else if (!fake_sleeping) {
if (connecting_delay_ticks < 0 && !fake_sleeping) {
fake_sleeping = true;
new_status_color(BLACK);
board_deinit();
if (!supervisor_workflow_active()) {
@ -416,7 +414,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
}
#endif
if (!asleep) {
if (!fake_sleeping) {
tick_rgb_status_animation(&animation);
} else {
// This waits until a pretend deep sleep alarm occurs. They are set

View File

@ -101,7 +101,7 @@ bool alarm_pin_pinalarm_woke_us_up(void) {
}
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
// First, check to see if we match any given alarms.
// For light sleep, we check if we match any existing alarms
uint64_t pin_status = ((uint64_t) pin_63_32_status) << 32 | pin_31_0_status;
for (size_t i = 0; i < n_alarms; i++) {
if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) {
@ -112,6 +112,7 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
return alarms[i];
}
}
// For deep sleep, a new alarm must be created
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
size_t pin_number = 64;
if (cause == ESP_SLEEP_WAKEUP_EXT0) {
@ -151,7 +152,7 @@ static uint64_t high_alarms = 0;
static uint64_t low_alarms = 0;
static uint64_t pull_pins = 0;
void alarm_pin_pinalarm_reset(void) {
void alarm_pin_pinalarm_reset_alarms(void) {
if (gpio_interrupt_handle != NULL) {
esp_intr_free(gpio_interrupt_handle);
gpio_interrupt_handle = NULL;

View File

@ -37,6 +37,3 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -39,70 +39,73 @@
#include "supervisor/port.h"
#include "supervisor/shared/workflow.h"
#define STM_WAKEUP_UNDEF 0
#define STM_WAKEUP_GPIO 1
#define STM_WAKEUP_TIMER 2
#define STM_WAKEUP_RTC 2
#define STM_ALARM_FLAG RTC->BKP0R
void common_hal_alarm_reset(void) {
// Reset the alarm flag
STM_ALARM_FLAG = 0x00;
// alarm_sleep_memory_reset();
alarm_pin_pinalarm_reset();
alarm_time_timealarm_reset();
// alarm_touch_touchalarm_reset();
// esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
}
STATIC uint8_t _get_wakeup_cause(void) {
// If in light/fake sleep, check modules
if (alarm_pin_pinalarm_woke_us_up()) {
return STM_WAKEUP_GPIO;
}
if (alarm_time_timealarm_woke_us_up()) {
return STM_WAKEUP_TIMER;
return STM_WAKEUP_RTC;
}
return 0;
if (RTC->BKP0R & 0x01) {
// We've woken from deep sleep. Was it the WKUP pin or the RTC?
if (RTC->ISR & RTC_FLAG_ALRBF) {
// Alarm B is the deep sleep alarm
return STM_WAKEUP_RTC;
} else {
return STM_WAKEUP_GPIO;
}
}
return STM_WAKEUP_UNDEF;
}
bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != 0;
return _get_wakeup_cause() != STM_WAKEUP_UNDEF;
}
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
if (alarm_pin_pinalarm_woke_us_up()) {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
}
// esp_sleep_wakeup_cause_t cause = _get_wakeup_cause();
// switch (cause) {
// case ESP_SLEEP_WAKEUP_TIMER: {
// return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
// }
// case ESP_SLEEP_WAKEUP_GPIO:
// case ESP_SLEEP_WAKEUP_EXT0:
// case ESP_SLEEP_WAKEUP_EXT1: {
// return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
// }
// case ESP_SLEEP_WAKEUP_TOUCHPAD: {
// return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms);
// }
// case ESP_SLEEP_WAKEUP_UNDEFINED:
// default:
// // Not a deep sleep reset.
// break;
// }
// return mp_const_none;
uint8_t cause = _get_wakeup_cause();
switch (cause) {
case STM_WAKEUP_RTC: {
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
}
case STM_WAKEUP_GPIO: {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
}
case STM_WAKEUP_UNDEF:
default:
// Not a deep sleep reset.
break;
}
return mp_const_none;
}
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
//return _get_wake_alarm(0, NULL);
return mp_const_none;
return _get_wake_alarm(0, NULL);
}
// Set up light sleep or deep sleep alarms.
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
// alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
}
STATIC void _idle_until_alarm(void) {
@ -144,16 +147,19 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,1);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,0);
alarm_pin_pinalarm_prepare_for_deep_sleep();
alarm_time_timealarm_prepare_for_deep_sleep();
port_disable_tick();
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
// alarm_touch_touchalarm_prepare_for_deep_sleep();
// Set a flag in the backup registers to indicate sleep wakeup
STM_ALARM_FLAG = 0x01;
// HAL_PWR_EnableBkUpAccess();
// __HAL_RCC_BACKUPRESET_FORCE();
// __HAL_RCC_BACKUPRESET_RELEASE();
HAL_PWR_EnterSTANDBYMode();
// Should never hit this
// The above shuts down RAM, so we should never hit this
while(1);
}

View File

@ -109,6 +109,7 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
}
void alarm_pin_pinalarm_reset(void) {
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
alarm_pin_triggered = 0;
woke_up = false;
}
@ -118,20 +119,18 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob
for (size_t i = 0; i < n_alarms; i++) {
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) {
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
if (deep_sleep) {
// Deep sleep only wakes on a rising edge from one pin, WKUP (PA00)
// All pin settings are handled automatically.
if (alarm->pin != &pin_PA00) {
mp_raise_ValueError(translate("Only the WKUP pin can be used to wake from Deep Sleep"));
}
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
// We can't actually turn WakeUp on here, since enabling it disables EXTI,
// so we put it off until right before sleeping.
deep_wkup_enabled = true;
} else {
stm_peripherals_exti_enable(alarm->pin->number);
}
stm_peripherals_exti_enable(alarm->pin->number);
}
}
}
@ -150,7 +149,9 @@ void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_
// If we don't have WKUP enabled, ensure it's disabled
// TODO; is this really required?
void alarm_pin_pinalarm_prepare_for_deep_sleep(void) {
if (!deep_wkup_enabled) {
if (deep_wkup_enabled) {
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
}
}

View File

@ -34,6 +34,7 @@
#include STM32_HAL_H
STATIC volatile bool woke_up;
STATIC uint32_t deep_sleep_ticks;
void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) {
self->monotonic_time = monotonic_time;
@ -95,7 +96,24 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_
uint32_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs);
uint32_t wakeup_in_ticks = wakeup_in_secs * 1024;
// In the deep sleep case, we can't start the timer until the USB delay has finished
if (deep_sleep) {
deep_sleep_ticks = wakeup_in_ticks;
} else {
deep_sleep_ticks = 0;
}
// Use alarm B, since port reserves A
// If true deep sleep is called, it will either ignore or overwrite this depending on
// whether it is shorter or longer than the USB delay
stm32_peripherals_rtc_assign_alarm_callback(PERIPHERALS_ALARM_B,timer_callback);
stm32_peripherals_rtc_set_alarm(PERIPHERALS_ALARM_B,wakeup_in_ticks);
}
void alarm_time_timealarm_prepare_for_deep_sleep(void) {
if (deep_sleep_ticks) {
// This is used for both fake and real deep sleep, so it still needs the callback
stm32_peripherals_rtc_assign_alarm_callback(PERIPHERALS_ALARM_B,timer_callback);
stm32_peripherals_rtc_set_alarm(PERIPHERALS_ALARM_B,deep_sleep_ticks);
deep_sleep_ticks = 0;
}
}

View File

@ -38,3 +38,5 @@ mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *
bool alarm_time_timealarm_woke_us_up(void);
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_time_timealarm_reset(void);
void alarm_time_timealarm_prepare_for_deep_sleep(void);

View File

@ -369,3 +369,9 @@ void _init(void)
{
}
#if CIRCUITPY_ALARM
// in case boards/xxx/board.c does not provide board_deinit()
MP_WEAK void board_deinit(void) {
}
#endif

View File

@ -92,7 +92,7 @@ void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) {
//| This allows the user to interrupt an existing program with ctrl-C,
//| and to edit the files in CIRCUITPY, which would not be possible in true light sleep.
//| Thus, to use light sleep and save significant power,
// it may be necessary to disconnect from the host.
//| it may be necessary to disconnect from the host.
//| """
//| ...
//|