Skip to content

Commit 7a45afc

Browse files
committed
working, but need to avoid deep sleeping too fast before USB ready
1 parent 3abee9b commit 7a45afc

File tree

13 files changed

+153
-75
lines changed

13 files changed

+153
-75
lines changed

main.c

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,17 @@
4747
#include "mpconfigboard.h"
4848
#include "supervisor/background_callback.h"
4949
#include "supervisor/cpu.h"
50+
#include "supervisor/filesystem.h"
5051
#include "supervisor/memory.h"
5152
#include "supervisor/port.h"
52-
#include "supervisor/filesystem.h"
53+
#include "supervisor/serial.h"
5354
#include "supervisor/shared/autoreload.h"
54-
#include "supervisor/shared/translate.h"
5555
#include "supervisor/shared/rgb_led_status.h"
5656
#include "supervisor/shared/safe_mode.h"
57-
#include "supervisor/shared/status_leds.h"
5857
#include "supervisor/shared/stack.h"
58+
#include "supervisor/shared/status_leds.h"
59+
#include "supervisor/shared/translate.h"
5960
#include "supervisor/shared/workflow.h"
60-
#include "supervisor/serial.h"
6161
#include "supervisor/usb.h"
6262

6363
#include "shared-bindings/microcontroller/__init__.h"
@@ -66,6 +66,8 @@
6666

6767
#include "boards/board.h"
6868

69+
#include "esp_log.h"
70+
6971
#if CIRCUITPY_ALARM
7072
#include "shared-bindings/alarm/__init__.h"
7173
#endif
@@ -101,26 +103,6 @@
101103
// How long to flash errors on the RGB status LED before going to sleep (secs)
102104
#define CIRCUITPY_FLASH_ERROR_PERIOD 10
103105

104-
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
105-
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
106-
if (lex == NULL) {
107-
//printf("MemoryError: lexer could not allocate memory\n");
108-
return;
109-
}
110-
111-
nlr_buf_t nlr;
112-
if (nlr_push(&nlr) == 0) {
113-
qstr source_name = lex->source_name;
114-
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
115-
mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true);
116-
mp_call_function_0(module_fun);
117-
nlr_pop();
118-
} else {
119-
// uncaught exception
120-
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
121-
}
122-
}
123-
124106
#if MICROPY_ENABLE_PYSTACK
125107
static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]);
126108
#endif
@@ -131,9 +113,13 @@ static void reset_devices(void) {
131113
#endif
132114
}
133115

134-
void start_mp(supervisor_allocation* heap) {
116+
STATIC void start_mp(supervisor_allocation* heap) {
135117
reset_status_led();
136118
autoreload_stop();
119+
supervisor_workflow_reset();
120+
#if CIRCUITPY_ALARM
121+
alarm_reset();
122+
#endif
137123

138124
// Stack limit should be less than real stack size, so we have a chance
139125
// to recover from limit hit. (Limit is measured in bytes.)
@@ -182,7 +168,7 @@ void start_mp(supervisor_allocation* heap) {
182168
#endif
183169
}
184170

185-
void stop_mp(void) {
171+
STATIC void stop_mp(void) {
186172
#if CIRCUITPY_NETWORK
187173
network_module_deinit();
188174
#endif
@@ -207,7 +193,7 @@ void stop_mp(void) {
207193

208194
// Look for the first file that exists in the list of filenames, using mp_import_stat().
209195
// Return its index. If no file found, return -1.
210-
const char* first_existing_file_in_list(const char * const * filenames) {
196+
STATIC const char* first_existing_file_in_list(const char * const * filenames) {
211197
for (int i = 0; filenames[i] != (char*)""; i++) {
212198
mp_import_stat_t stat = mp_import_stat(filenames[i]);
213199
if (stat == MP_IMPORT_STAT_FILE) {
@@ -217,7 +203,7 @@ const char* first_existing_file_in_list(const char * const * filenames) {
217203
return NULL;
218204
}
219205

220-
bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result) {
206+
STATIC bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result) {
221207
const char* filename = first_existing_file_in_list(filenames);
222208
if (filename == NULL) {
223209
return false;
@@ -231,7 +217,7 @@ bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result
231217
return true;
232218
}
233219

234-
void cleanup_after_vm(supervisor_allocation* heap) {
220+
STATIC void cleanup_after_vm(supervisor_allocation* heap) {
235221
// Reset port-independent devices, like CIRCUITPY_BLEIO_HCI.
236222
reset_devices();
237223
// Turn off the display and flush the fileystem before the heap disappears.
@@ -260,7 +246,7 @@ void cleanup_after_vm(supervisor_allocation* heap) {
260246
reset_status_led();
261247
}
262248

263-
void print_code_py_status_message(safe_mode_t safe_mode) {
249+
STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
264250
if (autoreload_is_enabled()) {
265251
serial_write_compressed(translate("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\n"));
266252
} else {
@@ -272,7 +258,7 @@ void print_code_py_status_message(safe_mode_t safe_mode) {
272258
}
273259
}
274260

275-
bool run_code_py(safe_mode_t safe_mode) {
261+
STATIC bool run_code_py(safe_mode_t safe_mode) {
276262
bool serial_connected_at_start = serial_connected();
277263
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
278264
if (serial_connected_at_start) {
@@ -318,6 +304,8 @@ bool run_code_py(safe_mode_t safe_mode) {
318304
}
319305
}
320306

307+
// Program has finished running.
308+
321309
// Display a different completion message if the user has no USB attached (cannot save files)
322310
if (!serial_connected_at_start) {
323311
serial_write_compressed(translate("\nCode done running. Waiting for reload.\n"));
@@ -329,11 +317,26 @@ bool run_code_py(safe_mode_t safe_mode) {
329317
#endif
330318
rgb_status_animation_t animation;
331319
bool ok = result.return_code != PYEXEC_EXCEPTION;
332-
// If USB isn't enumerated then deep sleep.
333-
if (ok && !supervisor_workflow_active() && supervisor_ticks_ms64() > CIRCUITPY_USB_ENUMERATION_DELAY * 1024) {
334-
common_hal_mcu_deep_sleep();
335-
}
336-
// Show the animation every N seconds.
320+
321+
ESP_LOGI("main", "common_hal_alarm_enable_deep_sleep_alarms()");
322+
// Decide whether to deep sleep.
323+
#if CIRCUITPY_ALARM
324+
// Enable pin or time alarms before sleeping.
325+
common_hal_alarm_enable_deep_sleep_alarms();
326+
#endif
327+
328+
// Normally we won't deep sleep if there was an error or if we are connected to a host
329+
// but either of those can be enabled.
330+
// *********DON'T SLEEP IF USB HASN'T HAD TIME TO ENUMERATE.
331+
bool will_deep_sleep =
332+
(ok || supervisor_workflow_get_allow_deep_sleep_on_error()) &&
333+
(!supervisor_workflow_active() || supervisor_workflow_get_allow_deep_sleep_when_connected());
334+
335+
ESP_LOGI("main", "ok %d", will_deep_sleep);
336+
ESP_LOGI("main", "...on_error() %d", supervisor_workflow_get_allow_deep_sleep_on_error());
337+
ESP_LOGI("main", "supervisor_workflow_active() %d", supervisor_workflow_active());
338+
ESP_LOGI("main", "...when_connected() %d", supervisor_workflow_get_allow_deep_sleep_when_connected());
339+
will_deep_sleep = false;
337340
prep_rgb_status_animation(&result, found_main, safe_mode, &animation);
338341
while (true) {
339342
RUN_BACKGROUND_TASKS;
@@ -356,9 +359,12 @@ bool run_code_py(safe_mode_t safe_mode) {
356359
if (!serial_connected_at_start) {
357360
print_code_py_status_message(safe_mode);
358361
}
359-
print_safe_mode_message(safe_mode);
360-
serial_write("\n");
361-
serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload."));
362+
// We won't be going into the REPL if we're going to sleep.
363+
if (!will_deep_sleep) {
364+
print_safe_mode_message(safe_mode);
365+
serial_write("\n");
366+
serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload."));
367+
}
362368
}
363369
if (serial_connected_before_animation && !serial_connected()) {
364370
serial_connected_at_start = false;
@@ -371,16 +377,22 @@ bool run_code_py(safe_mode_t safe_mode) {
371377
refreshed_epaper_display = maybe_refresh_epaperdisplay();
372378
}
373379
#endif
374-
bool animation_done = tick_rgb_status_animation(&animation);
375-
if (animation_done && supervisor_workflow_active()) {
376-
#if CIRCUITPY_ALARM
380+
381+
bool animation_done = false;
382+
if (will_deep_sleep && ok) {
383+
// Skip animation if everything is OK.
384+
animation_done = true;
385+
} else {
386+
animation_done = tick_rgb_status_animation(&animation);
387+
}
388+
// Do an error animation only once before deep-sleeping.
389+
if (animation_done && will_deep_sleep) {
377390
int64_t remaining_enumeration_wait = CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64();
378391
// If USB isn't enumerated then deep sleep after our waiting period.
379392
if (ok && remaining_enumeration_wait < 0) {
380393
common_hal_mcu_deep_sleep();
381-
return false; // Doesn't actually get here.
394+
// Does not return.
382395
}
383-
#endif
384396
// Wake up every so often to flash the error code.
385397
if (!ok) {
386398
port_interrupt_after_ticks(CIRCUITPY_FLASH_ERROR_PERIOD * 1024);
@@ -394,7 +406,7 @@ bool run_code_py(safe_mode_t safe_mode) {
394406

395407
FIL* boot_output_file;
396408

397-
void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
409+
STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
398410
// If not in safe mode, run boot before initing USB and capture output in a
399411
// file.
400412
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) {
473485
}
474486
}
475487

476-
int run_repl(void) {
488+
STATIC int run_repl(void) {
477489
int exit_code = PYEXEC_FORCED_EXIT;
478490
stack_resize();
479491
filesystem_flush();

ports/esp32s2/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,10 @@ $(BUILD)/firmware.uf2: $(BUILD)/circuitpython-firmware.bin
332332
$(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xbfdd4eee -b 0x0000 -c -o $@ $^
333333

334334
flash: $(BUILD)/firmware.bin
335-
esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x0000 $^
335+
esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=no_reset write_flash $(FLASH_FLAGS) 0x0000 $^
336336

337337
flash-circuitpython-only: $(BUILD)/circuitpython-firmware.bin
338-
esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x10000 $^
338+
esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=no_reset write_flash $(FLASH_FLAGS) 0x10000 $^
339339

340340
include $(TOP)/py/mkrules.mk
341341

ports/esp32s2/common-hal/alarm/__init__.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
9595
_deep_sleep_alarms = mp_obj_new_tuple(n_alarms, alarms);
9696
}
9797

98-
void common_hal_deep_sleep_with_alarms(void) {
98+
void common_hal_alarm_enable_deep_sleep_alarms(void) {
9999
for (size_t i = 0; i < _deep_sleep_alarms->len; i++) {
100100
mp_obj_t alarm = _deep_sleep_alarms->items[i];
101101
if (MP_OBJ_IS_TYPE(alarm, &alarm_time_duration_alarm_type)) {
@@ -105,6 +105,4 @@ void common_hal_deep_sleep_with_alarms(void) {
105105
}
106106
// TODO: handle pin alarms
107107
}
108-
109-
common_hal_mcu_deep_sleep();
110108
}

ports/esp32s2/common-hal/microcontroller/__init__.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,9 @@ void common_hal_mcu_reset(void) {
8080
while(1);
8181
}
8282

83-
void common_hal_mcu_deep_sleep(void) {
83+
void NORETURN common_hal_mcu_deep_sleep(void) {
8484
// Shut down wifi cleanly.
8585
esp_wifi_stop();
86-
87-
// Does not return.
8886
esp_deep_sleep_start();
8987
}
9088

py/circuitpy_defns.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ $(filter $(SRC_PATTERNS), \
403403
math/__init__.c \
404404
microcontroller/ResetReason.c \
405405
microcontroller/RunMode.c \
406+
supervisor/RunReason.c \
406407
)
407408

408409
SRC_BINDINGS_ENUMS += \

shared-bindings/alarm/__init__.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@
2929

3030
#include "py/obj.h"
3131

32+
#include "common-hal/alarm/__init__.h"
33+
3234
extern mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms);
35+
extern void common_hal_alarm_enable_deep_sleep_alarms(void);
3336
extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms);
3437

3538
// Used by wake-up code.

shared-bindings/microcontroller/__init__.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,6 @@
5656
//| This object is the sole instance of `microcontroller.Processor`."""
5757
//|
5858

59-
//| def deep_sleep() -> None:
60-
//| Go into deep sleep. If the board is connected via USB, disconnect USB first.
61-
//|
62-
//| The board will awake from deep sleep only if the reset button is pressed
63-
//| or it is awoken by an alarm set by `alarm.set_deep_sleep_alarms()`.
64-
//| ...
65-
//|
66-
STATIC mp_obj_t mcu_deep_sleep(void){
67-
68-
return mp_const_none;
69-
}
70-
MP_DEFINE_CONST_FUN_OBJ_0(mcu_deep_sleep_obj, mcu_deep_sleep);
71-
7259
//| def delay_us(delay: int) -> None:
7360
//| """Dedicated delay method used for very short delays. **Do not** do long delays
7461
//| 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 = {
177164
STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = {
178165
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_microcontroller) },
179166
{ MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&common_hal_mcu_processor_obj) },
180-
{ MP_ROM_QSTR(MP_QSTR_deep_sleep), MP_ROM_PTR(&mcu_deep_sleep_obj) },
181167
{ MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) },
182168
{ MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) },
183169
{ MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) },

shared-bindings/microcontroller/__init__.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ extern void common_hal_mcu_enable_interrupts(void);
4343
extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode);
4444
extern void common_hal_mcu_reset(void);
4545

46-
extern void common_hal_mcu_deep_sleep(void);
46+
extern void NORETURN common_hal_mcu_deep_sleep(void);
4747

4848
extern const mp_obj_dict_t mcu_pin_globals;
4949

shared-bindings/supervisor/RunReason.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "shared-bindings/supervisor/RunReason.h"
3030

3131
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, STARTUP, RUN_REASON_STARTUP);
32-
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTORELOAD, RUN_REASON_AUTO_RELOAD);
32+
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTO_RELOAD, RUN_REASON_AUTO_RELOAD);
3333
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, SUPERVISOR_RELOAD, RUN_REASON_SUPERVISOR_RELOAD);
3434
MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_REPL_RELOAD);
3535

@@ -49,7 +49,7 @@ MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_
4949
//| REPL_RELOAD: object
5050
//| """CircuitPython started due to the user typing CTRL-D in the REPL."""
5151
//|
52-
MAKE_ENUM_MAP(run_reason) {
52+
MAKE_ENUM_MAP(supervisor_run_reason) {
5353
MAKE_ENUM_MAP_ENTRY(run_reason, STARTUP),
5454
MAKE_ENUM_MAP_ENTRY(run_reason, AUTO_RELOAD),
5555
MAKE_ENUM_MAP_ENTRY(run_reason, SUPERVISOR_RELOAD),

shared-bindings/supervisor/Runtime.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525
*/
2626

2727
#include <stdbool.h>
28+
#include "py/obj.h"
2829
#include "py/enum.h"
30+
#include "py/runtime.h"
2931
#include "py/objproperty.h"
32+
3033
#include "shared-bindings/supervisor/RunReason.h"
3134
#include "shared-bindings/supervisor/Runtime.h"
3235

0 commit comments

Comments
 (0)