Skip to content

Commit

Permalink
Move simulated deep sleep restart to main.c
Browse files Browse the repository at this point in the history
  • Loading branch information
dhalbert committed Dec 2, 2020
1 parent 72fa7d8 commit 7ae6b94
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 15 deletions.
11 changes: 7 additions & 4 deletions lib/utils/pyexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,16 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input
if (exec_flags & EXEC_FLAG_PRINT_EOF) {
mp_hal_stdout_tx_strn("\x04", 1);
}
// check for SystemExit
if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) {
// check for program termination exceptions: SystemExit and deep sleep.
const mp_obj_type_t *exception_type = mp_obj_get_type((mp_obj_t)nlr.ret_val);
if (mp_obj_is_subclass_fast(exception_type, &mp_type_SystemExit)) {
// at the moment, the value of SystemExit is unused
ret = pyexec_system_exit;
#if CIRCUITPY_ALARM
} else if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_DeepSleepRequest)) {
ret = PYEXEC_DEEP_SLEEP;
} else if (mp_obj_is_subclass_fast(exception_type, &mp_type__DeepSleepRequest)) {
ret = PYEXEC_DEEP_SLEEP_REQUEST;
} else if (mp_obj_is_subclass_fast(exception_type, &mp_type__DeepSleepRestart)) {
ret = PYEXEC_DEEP_SLEEP_RESTART;
#endif
} else {
if ((mp_obj_t) nlr.ret_val != MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
Expand Down
11 changes: 7 additions & 4 deletions lib/utils/pyexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,13 @@ extern pyexec_mode_kind_t pyexec_mode_kind;
// It will reset to 0 at the start of each execution (eg each REPL entry).
extern int pyexec_system_exit;

#define PYEXEC_FORCED_EXIT (0x100)
#define PYEXEC_SWITCH_MODE (0x200)
#define PYEXEC_EXCEPTION (0x400)
#define PYEXEC_DEEP_SLEEP (0x800)
// These constants are meant to be or'd into the argument <n> in sys.exit(<n>)
// <n> is usually restricted to 0-127 in CPython, so they start above that.
#define PYEXEC_FORCED_EXIT (0x0100)
#define PYEXEC_SWITCH_MODE (0x0200)
#define PYEXEC_EXCEPTION (0x0400)
#define PYEXEC_DEEP_SLEEP_REQUEST (0x0800)
#define PYEXEC_DEEP_SLEEP_RESTART (0x1000)

int pyexec_raw_repl(void);
int pyexec_friendly_repl(void);
Expand Down
10 changes: 9 additions & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,18 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
}

#if CIRCUITPY_ALARM
if (result.return_code & PYEXEC_DEEP_SLEEP) {
if (result.return_code & PYEXEC_DEEP_SLEEP_REQUEST) {
// alarm.exit_and_deep_sleep_until_alarms() has requested a deep sleep.
common_hal_alarm_enter_deep_sleep();
// Does not return.
}
// alarm.exit_and_deep_sleep_until_alarms() simulated a deep sleep.
// After that, do a restart, to simulate the board being reset.
// We don't actually reset so we can preserve a connection to the host computer.
if (result.return_code & PYEXEC_DEEP_SLEEP_RESTART) {
supervisor_set_run_reason(RUN_REASON_STARTUP);
return true;
}
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion ports/esp32s2/common-hal/alarm/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ void common_hal_alarm_exit_and_deep_sleep_until_alarms(size_t n_alarms, const mp
setup_sleep_alarms(n_alarms, alarms);

// Raise an exception, which will be processed in main.c.
mp_raise_arg1(&mp_type_DeepSleepRequest, NULL);
mp_raise_arg1(&mp_type__DeepSleepRequest, NULL);
}

void common_hal_alarm_prepare_for_deep_sleep(void) {
Expand Down
3 changes: 2 additions & 1 deletion py/obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,8 @@ extern const mp_obj_type_t mp_type_ValueError;
extern const mp_obj_type_t mp_type_ViperTypeError;
extern const mp_obj_type_t mp_type_ZeroDivisionError;
#if CIRCUITPY_ALARM
extern const mp_obj_type_t mp_type_DeepSleepRequest;
extern const mp_obj_type_t mp_type__DeepSleepRequest;
extern const mp_obj_type_t mp_type__DeepSleepRestart;
#endif


Expand Down
5 changes: 4 additions & 1 deletion py/objexcept.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,10 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
//TODO: Implement more UnicodeError subclasses which take arguments
#endif
#if CIRCUITPY_ALARM
MP_DEFINE_EXCEPTION(DeepSleepRequest, BaseException)
// These are prefixed with underscore because they should not be used from Python.
// They are a mechanism to communicate deep sleep state to main.c.
MP_DEFINE_EXCEPTION(_DeepSleepRequest, BaseException)
MP_DEFINE_EXCEPTION(_DeepSleepRestart, BaseException)
#endif
MP_DEFINE_EXCEPTION(MpyError, ValueError)
/*
Expand Down
5 changes: 2 additions & 3 deletions shared-bindings/alarm/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,8 @@ STATIC mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_o
if (supervisor_workflow_active()) {
// Simulate deep sleep by waiting for an alarm and then restarting when done.
common_hal_alarm_wait_until_alarms(n_args, args);
reload_requested = true;
supervisor_set_run_reason(RUN_REASON_STARTUP);
mp_raise_reload_exception();
// Raise an exception, which will be processed in main.c.
mp_raise_arg1(&mp_type__DeepSleepRestart, NULL);
} else {
common_hal_alarm_exit_and_deep_sleep_until_alarms(n_args, args);
// Does not return.
Expand Down

0 comments on commit 7ae6b94

Please sign in to comment.