46
46
#include "background.h"
47
47
#include "mpconfigboard.h"
48
48
#include "supervisor/background_callback.h"
49
+ #include "supervisor/board.h"
49
50
#include "supervisor/cpu.h"
50
51
#include "supervisor/filesystem.h"
51
52
#include "supervisor/memory.h"
64
65
#include "shared-bindings/microcontroller/Processor.h"
65
66
#include "shared-bindings/supervisor/Runtime.h"
66
67
67
- #include "boards/board.h"
68
-
69
68
#if CIRCUITPY_ALARM
70
69
#include "shared-bindings/alarm/__init__.h"
71
70
#endif
@@ -303,13 +302,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
303
302
if (result .return_code & PYEXEC_FORCED_EXIT ) {
304
303
return reload_requested ;
305
304
}
306
-
307
- #if CIRCUITPY_ALARM
308
- if (result .return_code & PYEXEC_DEEP_SLEEP ) {
309
- common_hal_alarm_enter_deep_sleep ();
310
- // Does not return.
311
- }
312
- #endif
313
305
}
314
306
315
307
// Program has finished running.
@@ -326,32 +318,55 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
326
318
327
319
rgb_status_animation_t animation ;
328
320
prep_rgb_status_animation (& result , found_main , safe_mode , & animation );
321
+ bool asleep = false;
329
322
while (true) {
330
-
331
323
RUN_BACKGROUND_TASKS ;
332
324
if (reload_requested ) {
325
+ #if CIRCUITPY_ALARM
326
+ if (asleep ) {
327
+ board_init ();
328
+ }
329
+ #endif
333
330
supervisor_set_run_reason (RUN_REASON_AUTO_RELOAD );
334
331
reload_requested = false;
335
332
return true;
336
333
}
337
334
338
335
if (serial_connected () && serial_bytes_available ()) {
336
+ #if CIRCUITPY_ALARM
337
+ if (asleep ) {
338
+ board_init ();
339
+ }
340
+ #endif
339
341
// Skip REPL if reload was requested.
340
342
bool ctrl_d = serial_read () == CHAR_CTRL_D ;
341
343
if (ctrl_d ) {
342
344
supervisor_set_run_reason (RUN_REASON_REPL_RELOAD );
343
345
}
344
- return ( ctrl_d ) ;
346
+ return ctrl_d ;
345
347
}
346
348
349
+ // Check for a deep sleep alarm and restart the VM. This can happen if
350
+ // an alarm alerts faster than our USB delay or if we pretended to deep
351
+ // sleep.
352
+ #if CIRCUITPY_ALARM
353
+ if (asleep && alarm_woken_from_sleep ()) {
354
+ serial_write_compressed (translate ("Woken up by alarm.\n" ));
355
+ board_init ();
356
+ supervisor_set_run_reason (RUN_REASON_STARTUP );
357
+ // TODO: Reset any volatile memory the user may have access to.
358
+ return true;
359
+ }
360
+ #endif
361
+
347
362
if (!serial_connected_before_animation && serial_connected ()) {
348
363
if (!serial_connected_at_start ) {
349
364
print_code_py_status_message (safe_mode );
350
365
}
351
366
352
367
print_safe_mode_message (safe_mode );
353
368
serial_write ("\n" );
354
- serial_write_compressed (translate ("Press any key to enter the REPL. Use CTRL-D to reload." ));
369
+ serial_write_compressed (translate ("Press any key to enter the REPL. Use CTRL-D to reload.\n " ));
355
370
}
356
371
if (serial_connected_before_animation && !serial_connected ()) {
357
372
serial_connected_at_start = false;
@@ -360,12 +375,52 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
360
375
361
376
// Refresh the ePaper display if we have one. That way it'll show an error message.
362
377
#if CIRCUITPY_DISPLAYIO
378
+ // Don't refresh the display if we're about to deep sleep.
379
+ #if CIRCUITPY_ALARM
380
+ refreshed_epaper_display = refreshed_epaper_display || result .return_code & PYEXEC_DEEP_SLEEP ;
381
+ #endif
363
382
if (!refreshed_epaper_display ) {
364
383
refreshed_epaper_display = maybe_refresh_epaperdisplay ();
365
384
}
366
385
#endif
367
386
368
- tick_rgb_status_animation (& animation );
387
+ // Sleep until our next interrupt.
388
+ #if CIRCUITPY_ALARM
389
+ if (result .return_code & PYEXEC_DEEP_SLEEP ) {
390
+ // Make sure we have been awake long enough for USB to connect (enumeration delay).
391
+ int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks (NULL );
392
+ if (connecting_delay_ticks > 0 ) {
393
+ // Set when we've waited long enough so that we wake up from the
394
+ // port_idle_until_interrupt below and loop around to the real deep
395
+ // sleep in the else clause.
396
+ port_interrupt_after_ticks (connecting_delay_ticks );
397
+ // Deep sleep if we're not connected to a host.
398
+ } else if (!asleep ) {
399
+ asleep = true;
400
+ new_status_color (BLACK );
401
+ board_deinit ();
402
+ if (!supervisor_workflow_active ()) {
403
+ // Enter true deep sleep. When we wake up we'll be back at the
404
+ // top of main(), not in this loop.
405
+ alarm_enter_deep_sleep ();
406
+ // Does not return.
407
+ } else {
408
+ serial_write_compressed (translate ("Pretending to deep sleep until alarm, any key or file write.\n" ));
409
+ }
410
+ }
411
+ }
412
+ #endif
413
+
414
+ if (!asleep ) {
415
+ tick_rgb_status_animation (& animation );
416
+ } else {
417
+ // This waits until a pretend deep sleep alarm occurs. They are set
418
+ // during common_hal_alarm_set_deep_sleep_alarms. On some platforms
419
+ // it may also return due to another interrupt, that's why we check
420
+ // for deep sleep alarms above. If it wasn't a deep sleep alarm,
421
+ // then we'll idle here again.
422
+ port_idle_until_interrupt ();
423
+ }
369
424
}
370
425
}
371
426
0 commit comments