Merge pull request #5074 from tannewt/break_deep_sleep
Fix a couple fake sleep bugs on nrf and esp
This commit is contained in:
commit
bfe29786ce
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user