Merge pull request #5074 from tannewt/break_deep_sleep

Fix a couple fake sleep bugs on nrf and esp
This commit is contained in:
Scott Shawcroft 2021-07-30 09:19:08 -07:00 committed by GitHub
commit bfe29786ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 55 deletions

View File

@ -165,7 +165,12 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
} }
if (result != NULL) { if (result != NULL) {
result->return_code = ret; result->return_code = ret;
#if CIRCUITPY_ALARM
// Don't set the exception object if we exited for deep sleep.
if (ret != 0 && ret != PYEXEC_DEEP_SLEEP) {
#else
if (ret != 0) { if (ret != 0) {
#endif
mp_obj_t return_value = (mp_obj_t)nlr.ret_val; mp_obj_t return_value = (mp_obj_t)nlr.ret_val;
result->exception = return_value; result->exception = return_value;
result->exception_line = -1; result->exception_line = -1;

View File

@ -62,6 +62,11 @@ void alarm_reset(void) {
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
} }
// This will be reset to false by full resets when bss is cleared. Otherwise, the
// reload is due to CircuitPython and the ESP wakeup cause will be stale. This
// can happen if USB is connected after a deep sleep.
STATIC bool soft_wakeup = false;
STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) { STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
// First check if the modules remember what last woke up // First check if the modules remember what last woke up
if (alarm_pin_pinalarm_woke_this_cycle()) { if (alarm_pin_pinalarm_woke_this_cycle()) {
@ -75,7 +80,11 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) {
} }
// If waking from true deep sleep, modules will have lost their state, // If waking from true deep sleep, modules will have lost their state,
// so check the deep wakeup cause manually // so check the deep wakeup cause manually
if (!soft_wakeup) {
soft_wakeup = true;
return esp_sleep_get_wakeup_cause(); return esp_sleep_get_wakeup_cause();
}
return ESP_SLEEP_WAKEUP_UNDEFINED;
} }
bool common_hal_alarm_woken_from_sleep(void) { bool common_hal_alarm_woken_from_sleep(void) {

View File

@ -28,6 +28,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "supervisor/usb.h" #include "supervisor/usb.h"
#include "supervisor/esp_port.h" #include "supervisor/esp_port.h"
#include "supervisor/port.h"
#include "lib/utils/interrupt_char.h" #include "lib/utils/interrupt_char.h"
#include "lib/mp-readline/readline.h" #include "lib/mp-readline/readline.h"
@ -109,6 +110,7 @@ void init_usb_hardware(void) {
usb_device_stack, usb_device_stack,
&usb_device_taskdef); &usb_device_taskdef);
} }
/** /**
* Callback invoked when received an "wanted" char. * Callback invoked when received an "wanted" char.
* @param itf Interface index (for multiple cdc interfaces) * @param itf Interface index (for multiple cdc interfaces)
@ -116,13 +118,13 @@ void init_usb_hardware(void) {
*/ */
void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) {
(void)itf; // not used (void)itf; // not used
// CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB.
// So, we must notify the other task when a CTRL-C is received.
port_wake_main_task();
// Workaround for using lib/utils/interrupt_char.c // Workaround for using lib/utils/interrupt_char.c
// Compare mp_interrupt_char with wanted_char and ignore if not matched // Compare mp_interrupt_char with wanted_char and ignore if not matched
if (mp_interrupt_char == wanted_char) { if (mp_interrupt_char == wanted_char) {
tud_cdc_read_flush(); // flush read fifo tud_cdc_read_flush(); // flush read fifo
mp_sched_keyboard_interrupt(); mp_sched_keyboard_interrupt();
// CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB.
// So, we must notify the other task when a CTRL-C is received.
xTaskNotifyGive(circuitpython_task);
} }
} }

View File

@ -952,8 +952,11 @@ bool common_hal_bleio_adapter_is_bonded_to_central(bleio_adapter_obj_t *self) {
} }
void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) { void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) {
gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t)); // We divide by size_t so that we can scan each 32-bit aligned value to see
gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / sizeof(size_t)); // if it is a pointer. This allows us to change the structs without worrying
// about collecting new pointers.
gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / (sizeof(size_t)));
gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / (sizeof(size_t)));
} }
void bleio_adapter_reset(bleio_adapter_obj_t *adapter) { void bleio_adapter_reset(bleio_adapter_obj_t *adapter) {

View File

@ -137,6 +137,8 @@ mp_obj_t common_hal_alarm_create_wake_alarm(void) {
// Set up light sleep or deep sleep alarms. // 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) { STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_NONE;
sleepmem_wakeup_pin = WAKEUP_PIN_UNDEF;
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms); alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
alarm_time_timealarm_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); alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
@ -156,10 +158,6 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) {
if (timediff_ms != -1) { if (timediff_ms != -1) {
have_timeout = true; have_timeout = true;
#if 0
int64_t now = common_hal_time_monotonic_ms();
dbg_printf("now_ms=%ld timediff_ms=%ld\r\n", (long)now, (long)timediff_ms);
#endif
if (timediff_ms < 0) { if (timediff_ms < 0) {
timediff_ms = 0; timediff_ms = 0;
} }
@ -175,34 +173,17 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) {
start_tick = port_get_raw_ticks(NULL); start_tick = port_get_raw_ticks(NULL);
end_tick = start_tick + tickdiff; end_tick = start_tick + tickdiff;
} }
#if 0
dbg_printf("start_tick=%ld end_tick=%ld have_timeout=%c\r\n", (long)start_tick, (long)end_tick, have_timeout ? 'T' : 'F');
#endif
int64_t remaining; int64_t remaining;
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_NONE;
sleepmem_wakeup_pin = WAKEUP_PIN_UNDEF;
#ifdef NRF_DEBUG_PRINT
int ct = 40;
char reason = '?';
#define WAKEUP_REASON(x) reason = (x)
#else
#define WAKEUP_REASON(x)
#endif
while (1) { while (1) {
if (mp_hal_is_interrupted()) { if (mp_hal_is_interrupted()) {
WAKEUP_REASON('I');
break; break;
} }
if (serial_connected() && serial_bytes_available()) { if (serial_connected() && serial_bytes_available()) {
WAKEUP_REASON('S');
break; break;
} }
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
if (common_hal_alarm_woken_from_sleep()) { if (common_hal_alarm_woken_from_sleep()) {
WAKEUP_REASON('W');
break; break;
} }
if (have_timeout) { if (have_timeout) {
@ -210,51 +191,28 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) {
// We break a bit early so we don't risk setting the alarm before the time when we call // We break a bit early so we don't risk setting the alarm before the time when we call
// sleep. // sleep.
if (remaining < 1) { if (remaining < 1) {
WAKEUP_REASON('t');
break; break;
} }
port_interrupt_after_ticks(remaining); port_interrupt_after_ticks(remaining);
} }
// Idle until an interrupt happens. // Idle until an interrupt happens.
port_idle_until_interrupt(); port_idle_until_interrupt();
#ifdef NRF_DEBUG_PRINT
if (ct > 0) {
mp_printf(&mp_plat_print, "_");
--ct;
}
#endif
if (have_timeout) { if (have_timeout) {
remaining = end_tick - port_get_raw_ticks(NULL); remaining = end_tick - port_get_raw_ticks(NULL);
if (remaining <= 0) { if (remaining <= 0) {
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_TIMER; sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_TIMER;
WAKEUP_REASON('T');
break; break;
} }
} }
} }
#ifdef NRF_DEBUG_PRINT
mp_printf(&mp_plat_print, "%c\r\n", reason);
#endif
#if defined(MICROPY_QSPI_CS) #if defined(MICROPY_QSPI_CS)
qspi_flash_exit_sleep(); qspi_flash_exit_sleep();
#endif #endif
#ifdef NRF_DEBUG_PRINT
tickdiff = port_get_raw_ticks(NULL) - start_tick;
double sec;
if (prescaler == 0) {
sec = (double)tickdiff / 1024;
} else {
sec = (double)(tickdiff * prescaler) / 1024;
}
mp_printf(&mp_plat_print, "lapse %6.1f sec\r\n", sec);
#endif
} }
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
mp_obj_t wake_alarm = mp_const_none; mp_obj_t wake_alarm = mp_const_none;
alarm_time_timealarm_clear_wakeup_time();
_setup_sleep_alarms(false, n_alarms, alarms); _setup_sleep_alarms(false, n_alarms, alarms);
#ifdef NRF_DEBUG_PRINT #ifdef NRF_DEBUG_PRINT
@ -290,7 +248,6 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
} }
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) { void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
alarm_time_timealarm_clear_wakeup_time();
_setup_sleep_alarms(true, n_alarms, alarms); _setup_sleep_alarms(true, n_alarms, alarms);
} }

View File

@ -70,10 +70,6 @@ int64_t alarm_time_timealarm_get_wakeup_timediff_ms(void) {
return wakeup_time_saved - common_hal_time_monotonic_ms(); return wakeup_time_saved - common_hal_time_monotonic_ms();
} }
void alarm_time_timealarm_clear_wakeup_time(void) {
wakeup_time_saved = 0;
}
void alarm_time_timealarm_reset(void) { void alarm_time_timealarm_reset(void) {
port_disable_interrupt_after_ticks_ch(1); port_disable_interrupt_after_ticks_ch(1);
wakeup_time_saved = 0; wakeup_time_saved = 0;