working, but need to avoid deep sleeping too fast before USB ready
This commit is contained in:
parent
3abee9b256
commit
7a45afc549
104
main.c
104
main.c
|
@ -47,17 +47,17 @@
|
||||||
#include "mpconfigboard.h"
|
#include "mpconfigboard.h"
|
||||||
#include "supervisor/background_callback.h"
|
#include "supervisor/background_callback.h"
|
||||||
#include "supervisor/cpu.h"
|
#include "supervisor/cpu.h"
|
||||||
|
#include "supervisor/filesystem.h"
|
||||||
#include "supervisor/memory.h"
|
#include "supervisor/memory.h"
|
||||||
#include "supervisor/port.h"
|
#include "supervisor/port.h"
|
||||||
#include "supervisor/filesystem.h"
|
#include "supervisor/serial.h"
|
||||||
#include "supervisor/shared/autoreload.h"
|
#include "supervisor/shared/autoreload.h"
|
||||||
#include "supervisor/shared/translate.h"
|
|
||||||
#include "supervisor/shared/rgb_led_status.h"
|
#include "supervisor/shared/rgb_led_status.h"
|
||||||
#include "supervisor/shared/safe_mode.h"
|
#include "supervisor/shared/safe_mode.h"
|
||||||
#include "supervisor/shared/status_leds.h"
|
|
||||||
#include "supervisor/shared/stack.h"
|
#include "supervisor/shared/stack.h"
|
||||||
|
#include "supervisor/shared/status_leds.h"
|
||||||
|
#include "supervisor/shared/translate.h"
|
||||||
#include "supervisor/shared/workflow.h"
|
#include "supervisor/shared/workflow.h"
|
||||||
#include "supervisor/serial.h"
|
|
||||||
#include "supervisor/usb.h"
|
#include "supervisor/usb.h"
|
||||||
|
|
||||||
#include "shared-bindings/microcontroller/__init__.h"
|
#include "shared-bindings/microcontroller/__init__.h"
|
||||||
|
@ -66,6 +66,8 @@
|
||||||
|
|
||||||
#include "boards/board.h"
|
#include "boards/board.h"
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
#if CIRCUITPY_ALARM
|
#if CIRCUITPY_ALARM
|
||||||
#include "shared-bindings/alarm/__init__.h"
|
#include "shared-bindings/alarm/__init__.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -101,26 +103,6 @@
|
||||||
// How long to flash errors on the RGB status LED before going to sleep (secs)
|
// How long to flash errors on the RGB status LED before going to sleep (secs)
|
||||||
#define CIRCUITPY_FLASH_ERROR_PERIOD 10
|
#define CIRCUITPY_FLASH_ERROR_PERIOD 10
|
||||||
|
|
||||||
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
|
|
||||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
|
|
||||||
if (lex == NULL) {
|
|
||||||
//printf("MemoryError: lexer could not allocate memory\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nlr_buf_t nlr;
|
|
||||||
if (nlr_push(&nlr) == 0) {
|
|
||||||
qstr source_name = lex->source_name;
|
|
||||||
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
|
|
||||||
mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true);
|
|
||||||
mp_call_function_0(module_fun);
|
|
||||||
nlr_pop();
|
|
||||||
} else {
|
|
||||||
// uncaught exception
|
|
||||||
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MICROPY_ENABLE_PYSTACK
|
#if MICROPY_ENABLE_PYSTACK
|
||||||
static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]);
|
static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]);
|
||||||
#endif
|
#endif
|
||||||
|
@ -131,9 +113,13 @@ static void reset_devices(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_mp(supervisor_allocation* heap) {
|
STATIC void start_mp(supervisor_allocation* heap) {
|
||||||
reset_status_led();
|
reset_status_led();
|
||||||
autoreload_stop();
|
autoreload_stop();
|
||||||
|
supervisor_workflow_reset();
|
||||||
|
#if CIRCUITPY_ALARM
|
||||||
|
alarm_reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Stack limit should be less than real stack size, so we have a chance
|
// Stack limit should be less than real stack size, so we have a chance
|
||||||
// to recover from limit hit. (Limit is measured in bytes.)
|
// to recover from limit hit. (Limit is measured in bytes.)
|
||||||
|
@ -182,7 +168,7 @@ void start_mp(supervisor_allocation* heap) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_mp(void) {
|
STATIC void stop_mp(void) {
|
||||||
#if CIRCUITPY_NETWORK
|
#if CIRCUITPY_NETWORK
|
||||||
network_module_deinit();
|
network_module_deinit();
|
||||||
#endif
|
#endif
|
||||||
|
@ -207,7 +193,7 @@ void stop_mp(void) {
|
||||||
|
|
||||||
// Look for the first file that exists in the list of filenames, using mp_import_stat().
|
// Look for the first file that exists in the list of filenames, using mp_import_stat().
|
||||||
// Return its index. If no file found, return -1.
|
// Return its index. If no file found, return -1.
|
||||||
const char* first_existing_file_in_list(const char * const * filenames) {
|
STATIC const char* first_existing_file_in_list(const char * const * filenames) {
|
||||||
for (int i = 0; filenames[i] != (char*)""; i++) {
|
for (int i = 0; filenames[i] != (char*)""; i++) {
|
||||||
mp_import_stat_t stat = mp_import_stat(filenames[i]);
|
mp_import_stat_t stat = mp_import_stat(filenames[i]);
|
||||||
if (stat == MP_IMPORT_STAT_FILE) {
|
if (stat == MP_IMPORT_STAT_FILE) {
|
||||||
|
@ -217,7 +203,7 @@ const char* first_existing_file_in_list(const char * const * filenames) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result) {
|
STATIC bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result) {
|
||||||
const char* filename = first_existing_file_in_list(filenames);
|
const char* filename = first_existing_file_in_list(filenames);
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -231,7 +217,7 @@ bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_after_vm(supervisor_allocation* heap) {
|
STATIC void cleanup_after_vm(supervisor_allocation* heap) {
|
||||||
// Reset port-independent devices, like CIRCUITPY_BLEIO_HCI.
|
// Reset port-independent devices, like CIRCUITPY_BLEIO_HCI.
|
||||||
reset_devices();
|
reset_devices();
|
||||||
// Turn off the display and flush the fileystem before the heap disappears.
|
// Turn off the display and flush the fileystem before the heap disappears.
|
||||||
|
@ -260,7 +246,7 @@ void cleanup_after_vm(supervisor_allocation* heap) {
|
||||||
reset_status_led();
|
reset_status_led();
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_code_py_status_message(safe_mode_t safe_mode) {
|
STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
|
||||||
if (autoreload_is_enabled()) {
|
if (autoreload_is_enabled()) {
|
||||||
serial_write_compressed(translate("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\n"));
|
serial_write_compressed(translate("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\n"));
|
||||||
} else {
|
} else {
|
||||||
|
@ -272,7 +258,7 @@ void print_code_py_status_message(safe_mode_t safe_mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool run_code_py(safe_mode_t safe_mode) {
|
STATIC bool run_code_py(safe_mode_t safe_mode) {
|
||||||
bool serial_connected_at_start = serial_connected();
|
bool serial_connected_at_start = serial_connected();
|
||||||
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
|
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
|
||||||
if (serial_connected_at_start) {
|
if (serial_connected_at_start) {
|
||||||
|
@ -318,6 +304,8 @@ bool run_code_py(safe_mode_t safe_mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Program has finished running.
|
||||||
|
|
||||||
// Display a different completion message if the user has no USB attached (cannot save files)
|
// Display a different completion message if the user has no USB attached (cannot save files)
|
||||||
if (!serial_connected_at_start) {
|
if (!serial_connected_at_start) {
|
||||||
serial_write_compressed(translate("\nCode done running. Waiting for reload.\n"));
|
serial_write_compressed(translate("\nCode done running. Waiting for reload.\n"));
|
||||||
|
@ -329,11 +317,26 @@ bool run_code_py(safe_mode_t safe_mode) {
|
||||||
#endif
|
#endif
|
||||||
rgb_status_animation_t animation;
|
rgb_status_animation_t animation;
|
||||||
bool ok = result.return_code != PYEXEC_EXCEPTION;
|
bool ok = result.return_code != PYEXEC_EXCEPTION;
|
||||||
// If USB isn't enumerated then deep sleep.
|
|
||||||
if (ok && !supervisor_workflow_active() && supervisor_ticks_ms64() > CIRCUITPY_USB_ENUMERATION_DELAY * 1024) {
|
ESP_LOGI("main", "common_hal_alarm_enable_deep_sleep_alarms()");
|
||||||
common_hal_mcu_deep_sleep();
|
// Decide whether to deep sleep.
|
||||||
}
|
#if CIRCUITPY_ALARM
|
||||||
// Show the animation every N seconds.
|
// Enable pin or time alarms before sleeping.
|
||||||
|
common_hal_alarm_enable_deep_sleep_alarms();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Normally we won't deep sleep if there was an error or if we are connected to a host
|
||||||
|
// but either of those can be enabled.
|
||||||
|
// *********DON'T SLEEP IF USB HASN'T HAD TIME TO ENUMERATE.
|
||||||
|
bool will_deep_sleep =
|
||||||
|
(ok || supervisor_workflow_get_allow_deep_sleep_on_error()) &&
|
||||||
|
(!supervisor_workflow_active() || supervisor_workflow_get_allow_deep_sleep_when_connected());
|
||||||
|
|
||||||
|
ESP_LOGI("main", "ok %d", will_deep_sleep);
|
||||||
|
ESP_LOGI("main", "...on_error() %d", supervisor_workflow_get_allow_deep_sleep_on_error());
|
||||||
|
ESP_LOGI("main", "supervisor_workflow_active() %d", supervisor_workflow_active());
|
||||||
|
ESP_LOGI("main", "...when_connected() %d", supervisor_workflow_get_allow_deep_sleep_when_connected());
|
||||||
|
will_deep_sleep = false;
|
||||||
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
|
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
|
||||||
while (true) {
|
while (true) {
|
||||||
RUN_BACKGROUND_TASKS;
|
RUN_BACKGROUND_TASKS;
|
||||||
|
@ -356,9 +359,12 @@ bool run_code_py(safe_mode_t safe_mode) {
|
||||||
if (!serial_connected_at_start) {
|
if (!serial_connected_at_start) {
|
||||||
print_code_py_status_message(safe_mode);
|
print_code_py_status_message(safe_mode);
|
||||||
}
|
}
|
||||||
print_safe_mode_message(safe_mode);
|
// We won't be going into the REPL if we're going to sleep.
|
||||||
serial_write("\n");
|
if (!will_deep_sleep) {
|
||||||
serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload."));
|
print_safe_mode_message(safe_mode);
|
||||||
|
serial_write("\n");
|
||||||
|
serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (serial_connected_before_animation && !serial_connected()) {
|
if (serial_connected_before_animation && !serial_connected()) {
|
||||||
serial_connected_at_start = false;
|
serial_connected_at_start = false;
|
||||||
|
@ -371,16 +377,22 @@ bool run_code_py(safe_mode_t safe_mode) {
|
||||||
refreshed_epaper_display = maybe_refresh_epaperdisplay();
|
refreshed_epaper_display = maybe_refresh_epaperdisplay();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bool animation_done = tick_rgb_status_animation(&animation);
|
|
||||||
if (animation_done && supervisor_workflow_active()) {
|
bool animation_done = false;
|
||||||
#if CIRCUITPY_ALARM
|
if (will_deep_sleep && ok) {
|
||||||
|
// Skip animation if everything is OK.
|
||||||
|
animation_done = true;
|
||||||
|
} else {
|
||||||
|
animation_done = tick_rgb_status_animation(&animation);
|
||||||
|
}
|
||||||
|
// Do an error animation only once before deep-sleeping.
|
||||||
|
if (animation_done && will_deep_sleep) {
|
||||||
int64_t remaining_enumeration_wait = CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64();
|
int64_t remaining_enumeration_wait = CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64();
|
||||||
// If USB isn't enumerated then deep sleep after our waiting period.
|
// If USB isn't enumerated then deep sleep after our waiting period.
|
||||||
if (ok && remaining_enumeration_wait < 0) {
|
if (ok && remaining_enumeration_wait < 0) {
|
||||||
common_hal_mcu_deep_sleep();
|
common_hal_mcu_deep_sleep();
|
||||||
return false; // Doesn't actually get here.
|
// Does not return.
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
// Wake up every so often to flash the error code.
|
// Wake up every so often to flash the error code.
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
port_interrupt_after_ticks(CIRCUITPY_FLASH_ERROR_PERIOD * 1024);
|
port_interrupt_after_ticks(CIRCUITPY_FLASH_ERROR_PERIOD * 1024);
|
||||||
|
@ -394,7 +406,7 @@ bool run_code_py(safe_mode_t safe_mode) {
|
||||||
|
|
||||||
FIL* boot_output_file;
|
FIL* boot_output_file;
|
||||||
|
|
||||||
void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
|
STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
|
||||||
// If not in safe mode, run boot before initing USB and capture output in a
|
// If not in safe mode, run boot before initing USB and capture output in a
|
||||||
// file.
|
// file.
|
||||||
if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
|
if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
|
||||||
|
@ -473,7 +485,7 @@ void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_repl(void) {
|
STATIC int run_repl(void) {
|
||||||
int exit_code = PYEXEC_FORCED_EXIT;
|
int exit_code = PYEXEC_FORCED_EXIT;
|
||||||
stack_resize();
|
stack_resize();
|
||||||
filesystem_flush();
|
filesystem_flush();
|
||||||
|
|
|
@ -332,10 +332,10 @@ $(BUILD)/firmware.uf2: $(BUILD)/circuitpython-firmware.bin
|
||||||
$(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xbfdd4eee -b 0x0000 -c -o $@ $^
|
$(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xbfdd4eee -b 0x0000 -c -o $@ $^
|
||||||
|
|
||||||
flash: $(BUILD)/firmware.bin
|
flash: $(BUILD)/firmware.bin
|
||||||
esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x0000 $^
|
esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=no_reset write_flash $(FLASH_FLAGS) 0x0000 $^
|
||||||
|
|
||||||
flash-circuitpython-only: $(BUILD)/circuitpython-firmware.bin
|
flash-circuitpython-only: $(BUILD)/circuitpython-firmware.bin
|
||||||
esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x10000 $^
|
esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=no_reset write_flash $(FLASH_FLAGS) 0x10000 $^
|
||||||
|
|
||||||
include $(TOP)/py/mkrules.mk
|
include $(TOP)/py/mkrules.mk
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
|
||||||
_deep_sleep_alarms = mp_obj_new_tuple(n_alarms, alarms);
|
_deep_sleep_alarms = mp_obj_new_tuple(n_alarms, alarms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_deep_sleep_with_alarms(void) {
|
void common_hal_alarm_enable_deep_sleep_alarms(void) {
|
||||||
for (size_t i = 0; i < _deep_sleep_alarms->len; i++) {
|
for (size_t i = 0; i < _deep_sleep_alarms->len; i++) {
|
||||||
mp_obj_t alarm = _deep_sleep_alarms->items[i];
|
mp_obj_t alarm = _deep_sleep_alarms->items[i];
|
||||||
if (MP_OBJ_IS_TYPE(alarm, &alarm_time_duration_alarm_type)) {
|
if (MP_OBJ_IS_TYPE(alarm, &alarm_time_duration_alarm_type)) {
|
||||||
|
@ -105,6 +105,4 @@ void common_hal_deep_sleep_with_alarms(void) {
|
||||||
}
|
}
|
||||||
// TODO: handle pin alarms
|
// TODO: handle pin alarms
|
||||||
}
|
}
|
||||||
|
|
||||||
common_hal_mcu_deep_sleep();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,11 +80,9 @@ void common_hal_mcu_reset(void) {
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_mcu_deep_sleep(void) {
|
void NORETURN common_hal_mcu_deep_sleep(void) {
|
||||||
// Shut down wifi cleanly.
|
// Shut down wifi cleanly.
|
||||||
esp_wifi_stop();
|
esp_wifi_stop();
|
||||||
|
|
||||||
// Does not return.
|
|
||||||
esp_deep_sleep_start();
|
esp_deep_sleep_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -403,6 +403,7 @@ $(filter $(SRC_PATTERNS), \
|
||||||
math/__init__.c \
|
math/__init__.c \
|
||||||
microcontroller/ResetReason.c \
|
microcontroller/ResetReason.c \
|
||||||
microcontroller/RunMode.c \
|
microcontroller/RunMode.c \
|
||||||
|
supervisor/RunReason.c \
|
||||||
)
|
)
|
||||||
|
|
||||||
SRC_BINDINGS_ENUMS += \
|
SRC_BINDINGS_ENUMS += \
|
||||||
|
|
|
@ -29,7 +29,10 @@
|
||||||
|
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#include "common-hal/alarm/__init__.h"
|
||||||
|
|
||||||
extern mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms);
|
extern mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms);
|
||||||
|
extern void common_hal_alarm_enable_deep_sleep_alarms(void);
|
||||||
extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms);
|
extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms);
|
||||||
|
|
||||||
// Used by wake-up code.
|
// Used by wake-up code.
|
||||||
|
|
|
@ -56,19 +56,6 @@
|
||||||
//| This object is the sole instance of `microcontroller.Processor`."""
|
//| This object is the sole instance of `microcontroller.Processor`."""
|
||||||
//|
|
//|
|
||||||
|
|
||||||
//| def deep_sleep() -> None:
|
|
||||||
//| Go into deep sleep. If the board is connected via USB, disconnect USB first.
|
|
||||||
//|
|
|
||||||
//| The board will awake from deep sleep only if the reset button is pressed
|
|
||||||
//| or it is awoken by an alarm set by `alarm.set_deep_sleep_alarms()`.
|
|
||||||
//| ...
|
|
||||||
//|
|
|
||||||
STATIC mp_obj_t mcu_deep_sleep(void){
|
|
||||||
|
|
||||||
return mp_const_none;
|
|
||||||
}
|
|
||||||
MP_DEFINE_CONST_FUN_OBJ_0(mcu_deep_sleep_obj, mcu_deep_sleep);
|
|
||||||
|
|
||||||
//| def delay_us(delay: int) -> None:
|
//| def delay_us(delay: int) -> None:
|
||||||
//| """Dedicated delay method used for very short delays. **Do not** do long delays
|
//| """Dedicated delay method used for very short delays. **Do not** do long delays
|
||||||
//| because this stops all other functions from completing. Think of this as an empty
|
//| because this stops all other functions from completing. Think of this as an empty
|
||||||
|
@ -177,7 +164,6 @@ const mp_obj_module_t mcu_pin_module = {
|
||||||
STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = {
|
STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_microcontroller) },
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_microcontroller) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&common_hal_mcu_processor_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&common_hal_mcu_processor_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_deep_sleep), MP_ROM_PTR(&mcu_deep_sleep_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) },
|
||||||
|
|
|
@ -43,7 +43,7 @@ extern void common_hal_mcu_enable_interrupts(void);
|
||||||
extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode);
|
extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode);
|
||||||
extern void common_hal_mcu_reset(void);
|
extern void common_hal_mcu_reset(void);
|
||||||
|
|
||||||
extern void common_hal_mcu_deep_sleep(void);
|
extern void NORETURN common_hal_mcu_deep_sleep(void);
|
||||||
|
|
||||||
extern const mp_obj_dict_t mcu_pin_globals;
|
extern const mp_obj_dict_t mcu_pin_globals;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include "shared-bindings/supervisor/RunReason.h"
|
#include "shared-bindings/supervisor/RunReason.h"
|
||||||
|
|
||||||
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, STARTUP, RUN_REASON_STARTUP);
|
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, STARTUP, RUN_REASON_STARTUP);
|
||||||
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTORELOAD, RUN_REASON_AUTO_RELOAD);
|
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTO_RELOAD, RUN_REASON_AUTO_RELOAD);
|
||||||
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, SUPERVISOR_RELOAD, RUN_REASON_SUPERVISOR_RELOAD);
|
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, SUPERVISOR_RELOAD, RUN_REASON_SUPERVISOR_RELOAD);
|
||||||
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_REPL_RELOAD);
|
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_REPL_RELOAD);
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_
|
||||||
//| REPL_RELOAD: object
|
//| REPL_RELOAD: object
|
||||||
//| """CircuitPython started due to the user typing CTRL-D in the REPL."""
|
//| """CircuitPython started due to the user typing CTRL-D in the REPL."""
|
||||||
//|
|
//|
|
||||||
MAKE_ENUM_MAP(run_reason) {
|
MAKE_ENUM_MAP(supervisor_run_reason) {
|
||||||
MAKE_ENUM_MAP_ENTRY(run_reason, STARTUP),
|
MAKE_ENUM_MAP_ENTRY(run_reason, STARTUP),
|
||||||
MAKE_ENUM_MAP_ENTRY(run_reason, AUTO_RELOAD),
|
MAKE_ENUM_MAP_ENTRY(run_reason, AUTO_RELOAD),
|
||||||
MAKE_ENUM_MAP_ENTRY(run_reason, SUPERVISOR_RELOAD),
|
MAKE_ENUM_MAP_ENTRY(run_reason, SUPERVISOR_RELOAD),
|
||||||
|
|
|
@ -25,8 +25,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "py/obj.h"
|
||||||
#include "py/enum.h"
|
#include "py/enum.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
#include "py/objproperty.h"
|
#include "py/objproperty.h"
|
||||||
|
|
||||||
#include "shared-bindings/supervisor/RunReason.h"
|
#include "shared-bindings/supervisor/RunReason.h"
|
||||||
#include "shared-bindings/supervisor/Runtime.h"
|
#include "shared-bindings/supervisor/Runtime.h"
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,9 @@
|
||||||
#include "supervisor/shared/rgb_led_status.h"
|
#include "supervisor/shared/rgb_led_status.h"
|
||||||
#include "supervisor/shared/stack.h"
|
#include "supervisor/shared/stack.h"
|
||||||
#include "supervisor/shared/translate.h"
|
#include "supervisor/shared/translate.h"
|
||||||
|
#include "supervisor/shared/workflow.h"
|
||||||
|
|
||||||
|
#include "shared-bindings/microcontroller/__init__.h"
|
||||||
#include "shared-bindings/supervisor/__init__.h"
|
#include "shared-bindings/supervisor/__init__.h"
|
||||||
#include "shared-bindings/supervisor/Runtime.h"
|
#include "shared-bindings/supervisor/Runtime.h"
|
||||||
|
|
||||||
|
@ -45,6 +47,47 @@
|
||||||
//| This object is the sole instance of `supervisor.Runtime`."""
|
//| This object is the sole instance of `supervisor.Runtime`."""
|
||||||
//|
|
//|
|
||||||
|
|
||||||
|
//| def allow_deep_sleep(*, when_connected: bool = False, on_error: bool = False):
|
||||||
|
//| """Configure when CircuitPython can go into deep sleep. Deep sleep can occur
|
||||||
|
//| after a program has finished running or when `supervisor.deep_sleep_now()` is called.
|
||||||
|
//|
|
||||||
|
//| :param bool when_connected: If ``True``, CircuitPython will go into deep sleep
|
||||||
|
//| when a program finishes, even if it is connected to a host computer over USB or other means.
|
||||||
|
//| It will disconnect from the host before sleeping.
|
||||||
|
//| If ``False``, deep sleep will not be entered if connected.
|
||||||
|
//| :param bool on_error: If ``True``, deep sleep will be entered if even a program
|
||||||
|
//| terminated due to an exception or fatal error. If ``False``, an error will cause
|
||||||
|
//| CircuitPython to stay awake, flashing error codes on the status RGB LED, if available.
|
||||||
|
//| ...
|
||||||
|
//|
|
||||||
|
STATIC mp_obj_t supervisor_allow_deep_sleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||||
|
enum { ARG_when_connected, ARG_on_error };
|
||||||
|
static const mp_arg_t allowed_args[] = {
|
||||||
|
{ MP_QSTR_when_connected, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||||
|
{ MP_QSTR_on_error, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||||
|
};
|
||||||
|
|
||||||
|
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||||
|
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
|
supervisor_workflow_set_allow_deep_sleep_when_connected(args[ARG_when_connected].u_bool);
|
||||||
|
supervisor_workflow_set_allow_deep_sleep_on_error(args[ARG_on_error].u_bool);
|
||||||
|
|
||||||
|
return mp_const_none;
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_allow_deep_sleep_obj, 0, supervisor_allow_deep_sleep);
|
||||||
|
|
||||||
|
//| def deep_sleep(): -> None
|
||||||
|
//| """Go into deep sleep mode immediately, if not connected to a host computer.
|
||||||
|
//| But if connected and `supervisor.runtime.allow_deep_sleep(when_connected=true)`
|
||||||
|
//| has not been called, simply restart.
|
||||||
|
//|
|
||||||
|
|
||||||
|
STATIC mp_obj_t supervisor_deep_sleep(void) {
|
||||||
|
common_hal_mcu_deep_sleep();
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_deep_sleep_obj, supervisor_deep_sleep);
|
||||||
|
|
||||||
//| def enable_autoreload() -> None:
|
//| def enable_autoreload() -> None:
|
||||||
//| """Enable autoreload based on USB file write activity."""
|
//| """Enable autoreload based on USB file write activity."""
|
||||||
//| ...
|
//| ...
|
||||||
|
@ -112,9 +155,11 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_next_stack_limit_obj, supervisor_set_ne
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
|
STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) },
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_allow_deep_sleep), MP_ROM_PTR(&supervisor_allow_deep_sleep_obj) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_deep_sleep), MP_ROM_PTR(&supervisor_deep_sleep_obj) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&supervisor_reload_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&supervisor_reload_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_set_next_stack_limit), MP_ROM_PTR(&supervisor_set_next_stack_limit_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_set_next_stack_limit), MP_ROM_PTR(&supervisor_set_next_stack_limit_obj) },
|
||||||
|
|
|
@ -25,10 +25,36 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "py/mpconfig.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
|
||||||
|
STATIC bool _allow_deep_sleep_when_connected;
|
||||||
|
STATIC bool _allow_deep_sleep_on_error;
|
||||||
|
|
||||||
|
|
||||||
|
void supervisor_workflow_reset(void) {
|
||||||
|
_allow_deep_sleep_when_connected = false;
|
||||||
|
_allow_deep_sleep_on_error = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool supervisor_workflow_active(void) {
|
bool supervisor_workflow_active(void) {
|
||||||
// Eventually there might be other non-USB workflows, such as BLE.
|
// Eventually there might be other non-USB workflows, such as BLE.
|
||||||
// tud_ready() checks for usb mounted and not suspended.
|
// tud_ready() checks for usb mounted and not suspended.
|
||||||
return tud_ready();
|
return tud_ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool supervisor_workflow_get_allow_deep_sleep_when_connected(void) {
|
||||||
|
return _allow_deep_sleep_when_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void supervisor_workflow_set_allow_deep_sleep_when_connected(bool allow) {
|
||||||
|
_allow_deep_sleep_when_connected = allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool supervisor_workflow_get_allow_deep_sleep_on_error(void) {
|
||||||
|
return _allow_deep_sleep_on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void supervisor_workflow_set_allow_deep_sleep_on_error(bool allow) {
|
||||||
|
_allow_deep_sleep_on_error = allow;
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
extern volatile bool _workflow_active;
|
extern void supervisor_workflow_reset(void);
|
||||||
|
|
||||||
extern bool supervisor_workflow_active(void);
|
extern bool supervisor_workflow_active(void);
|
||||||
|
|
||||||
|
extern bool supervisor_workflow_get_allow_deep_sleep_when_connected(void);
|
||||||
|
extern void supervisor_workflow_set_allow_deep_sleep_when_connected(bool allow);
|
||||||
|
|
||||||
|
extern bool supervisor_workflow_get_allow_deep_sleep_on_error(void);
|
||||||
|
extern void supervisor_workflow_set_allow_deep_sleep_on_error(bool allow);
|
||||||
|
|
Loading…
Reference in New Issue