Fix a couple fake sleep bugs on nrf and esp
On ESP ctrl-c during fake sleep will now stop the sleep. A crash on real deep sleep is now fixed as well. (Exception string saving was crashing on reading the deep sleep exception.) Fixes #4010 This also fixes nRF fake sleep after the first time. The internal variable wasn't being reset early enough. Fixes #4869
This commit is contained in:
parent
e9369d50e1
commit
cdf978f3af
@ -165,7 +165,12 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
|
||||
}
|
||||
if (result != NULL) {
|
||||
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) {
|
||||
#endif
|
||||
mp_obj_t return_value = (mp_obj_t)nlr.ret_val;
|
||||
result->exception = return_value;
|
||||
result->exception_line = -1;
|
||||
|
@ -62,6 +62,11 @@ void alarm_reset(void) {
|
||||
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) {
|
||||
// First check if the modules remember what last woke up
|
||||
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,
|
||||
// so check the deep wakeup cause manually
|
||||
return esp_sleep_get_wakeup_cause();
|
||||
if (!soft_wakeup) {
|
||||
soft_wakeup = true;
|
||||
return esp_sleep_get_wakeup_cause();
|
||||
}
|
||||
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||
}
|
||||
|
||||
bool common_hal_alarm_woken_from_sleep(void) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "supervisor/usb.h"
|
||||
#include "supervisor/esp_port.h"
|
||||
#include "supervisor/port.h"
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "lib/mp-readline/readline.h"
|
||||
|
||||
@ -109,6 +110,7 @@ void init_usb_hardware(void) {
|
||||
usb_device_stack,
|
||||
&usb_device_taskdef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked when received an "wanted" char.
|
||||
* @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)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
|
||||
// Compare mp_interrupt_char with wanted_char and ignore if not matched
|
||||
if (mp_interrupt_char == wanted_char) {
|
||||
tud_cdc_read_flush(); // flush read fifo
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
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));
|
||||
// We divide by size_t so that we can scan each 32-bit aligned value to see
|
||||
// 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) {
|
||||
|
@ -137,6 +137,8 @@ mp_obj_t common_hal_alarm_create_wake_alarm(void) {
|
||||
|
||||
// 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) {
|
||||
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_NONE;
|
||||
sleepmem_wakeup_pin = WAKEUP_PIN_UNDEF;
|
||||
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);
|
||||
@ -156,10 +158,6 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) {
|
||||
|
||||
if (timediff_ms != -1) {
|
||||
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) {
|
||||
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);
|
||||
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;
|
||||
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) {
|
||||
if (mp_hal_is_interrupted()) {
|
||||
WAKEUP_REASON('I');
|
||||
break;
|
||||
}
|
||||
if (serial_connected() && serial_bytes_available()) {
|
||||
WAKEUP_REASON('S');
|
||||
break;
|
||||
}
|
||||
RUN_BACKGROUND_TASKS;
|
||||
if (common_hal_alarm_woken_from_sleep()) {
|
||||
WAKEUP_REASON('W');
|
||||
break;
|
||||
}
|
||||
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
|
||||
// sleep.
|
||||
if (remaining < 1) {
|
||||
WAKEUP_REASON('t');
|
||||
break;
|
||||
}
|
||||
port_interrupt_after_ticks(remaining);
|
||||
}
|
||||
// Idle until an interrupt happens.
|
||||
port_idle_until_interrupt();
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
if (ct > 0) {
|
||||
mp_printf(&mp_plat_print, "_");
|
||||
--ct;
|
||||
}
|
||||
#endif
|
||||
if (have_timeout) {
|
||||
remaining = end_tick - port_get_raw_ticks(NULL);
|
||||
if (remaining <= 0) {
|
||||
sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_TIMER;
|
||||
WAKEUP_REASON('T');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef NRF_DEBUG_PRINT
|
||||
mp_printf(&mp_plat_print, "%c\r\n", reason);
|
||||
#endif
|
||||
|
||||
#if defined(MICROPY_QSPI_CS)
|
||||
qspi_flash_exit_sleep();
|
||||
#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 wake_alarm = mp_const_none;
|
||||
alarm_time_timealarm_clear_wakeup_time();
|
||||
_setup_sleep_alarms(false, n_alarms, alarms);
|
||||
|
||||
#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) {
|
||||
alarm_time_timealarm_clear_wakeup_time();
|
||||
_setup_sleep_alarms(true, n_alarms, alarms);
|
||||
}
|
||||
|
||||
|
@ -70,10 +70,6 @@ int64_t alarm_time_timealarm_get_wakeup_timediff_ms(void) {
|
||||
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) {
|
||||
port_disable_interrupt_after_ticks_ch(1);
|
||||
wakeup_time_saved = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user