5252#include "supervisor/memory.h"
5353#include "supervisor/port.h"
5454#include "supervisor/serial.h"
55- #include "supervisor/shared/autoreload .h"
55+ #include "supervisor/shared/reload .h"
5656#include "supervisor/shared/safe_mode.h"
5757#include "supervisor/shared/stack.h"
5858#include "supervisor/shared/status_leds.h"
@@ -124,7 +124,6 @@ static void reset_devices(void) {
124124}
125125
126126STATIC void start_mp (supervisor_allocation * heap , bool first_run ) {
127- autoreload_stop ();
128127 supervisor_workflow_reset ();
129128
130129 // Stack limit should be less than real stack size, so we have a chance
@@ -329,14 +328,20 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
329328 result .exception = MP_OBJ_NULL ;
330329 result .exception_line = 0 ;
331330
332- bool skip_repl ;
331+ bool skip_repl = false ;
333332 bool skip_wait = false;
334333 bool found_main = false;
335334 uint8_t next_code_options = 0 ;
336335 // Collects stickiness bits that apply in the current situation.
337336 uint8_t next_code_stickiness_situation = SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET ;
338337
338+ // Do the filesystem flush check before reload in case another write comes
339+ // in while we're doing the flush.
339340 if (safe_mode == NO_SAFE_MODE ) {
341+ stack_resize ();
342+ filesystem_flush ();
343+ }
344+ if (safe_mode == NO_SAFE_MODE && !autoreload_pending ()) {
340345 static const char * const supported_filenames [] = STRING_LIST (
341346 "code.txt" , "code.py" , "main.py" , "main.txt" );
342347 #if CIRCUITPY_FULL_BUILD
@@ -345,8 +350,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
345350 "main.txt.py" , "main.py.txt" , "main.txt.txt" ,"main.py.py" );
346351 #endif
347352
348- stack_resize ();
349- filesystem_flush ();
350353 supervisor_allocation * heap = allocate_remaining_memory ();
351354
352355 // Prepare the VM state. Includes an alarm check/reset for sleep.
@@ -389,13 +392,14 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
389392
390393 // Print done before resetting everything so that we get the message over
391394 // BLE before it is reset and we have a delay before reconnect.
392- if (reload_requested && result . return_code == PYEXEC_EXCEPTION ) {
393- serial_write_compressed (translate ("\nCode stopped by auto-reload.\n" ));
395+ if (( result . return_code & PYEXEC_RELOAD ) && supervisor_get_run_reason () == RUN_REASON_AUTO_RELOAD ) {
396+ serial_write_compressed (translate ("\nCode stopped by auto-reload. Reloading soon. \n" ));
394397 } else {
395398 serial_write_compressed (translate ("\nCode done running.\n" ));
396399 }
397400
398- // Finished executing python code. Cleanup includes a board reset.
401+
402+ // Finished executing python code. Cleanup includes filesystem flush and a board reset.
399403 cleanup_after_vm (heap , result .exception );
400404
401405 // If a new next code file was set, that is a reason to keep it (obviously). Stuff this into
@@ -407,7 +411,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
407411 next_code_options |= SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET ;
408412 }
409413
410- if (reload_requested ) {
414+ if (result . return_code & PYEXEC_RELOAD ) {
411415 next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD ;
412416 } else if (result .return_code == 0 ) {
413417 next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_SUCCESS ;
@@ -426,7 +430,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
426430 }
427431 }
428432 if (result .return_code & PYEXEC_FORCED_EXIT ) {
429- skip_repl = reload_requested ;
433+ skip_repl = false ;
430434 skip_wait = true;
431435 }
432436 }
@@ -466,22 +470,27 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
466470 size_t total_time = blink_time + LED_SLEEP_TIME_MS ;
467471 #endif
468472
473+ // This loop is waits after code completes. It waits for fake sleeps to
474+ // finish, user input or autoreloads.
469475 #if CIRCUITPY_ALARM
470476 bool fake_sleeping = false;
471477 #endif
472478 while (!skip_wait ) {
473479 RUN_BACKGROUND_TASKS ;
474480
475- // If a reload was requested by the supervisor or autoreload, return
476- if (reload_requested ) {
481+ // If a reload was requested by the supervisor or autoreload, return.
482+ if (autoreload_ready () ) {
477483 next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD ;
478484 // Should the STICKY_ON_SUCCESS and STICKY_ON_ERROR bits be cleared in
479485 // next_code_stickiness_situation? I can see arguments either way, but I'm deciding
480486 // "no" for now, mainly because it's a bit less code. At this point, we have both a
481487 // success or error and a reload, so let's have both of the respective options take
482488 // effect (in OR combination).
483- reload_requested = false;
484489 skip_repl = true;
490+ // We're kicking off the autoreload process so reset now. If any
491+ // other reloads trigger after this, then we'll want another wait
492+ // period.
493+ autoreload_reset ();
485494 break ;
486495 }
487496
@@ -508,7 +517,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
508517 #endif
509518
510519 // If messages haven't been printed yet, print them
511- if (!printed_press_any_key && serial_connected ()) {
520+ if (!printed_press_any_key && serial_connected () && ! autoreload_pending () ) {
512521 if (!serial_connected_at_start ) {
513522 print_code_py_status_message (safe_mode );
514523 }
@@ -627,13 +636,14 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
627636 }
628637 }
629638
639+ // Done waiting, start the board back up.
640+
630641 // free code allocation if unused
631642 if ((next_code_options & next_code_stickiness_situation ) == 0 ) {
632643 free_memory (next_code_allocation );
633644 next_code_allocation = NULL ;
634645 }
635646
636- // Done waiting, start the board back up.
637647 #if CIRCUITPY_STATUS_LED
638648 if (led_active ) {
639649 new_status_color (BLACK );
@@ -757,7 +767,7 @@ STATIC int run_repl(bool first_run) {
757767 usb_setup_with_vm ();
758768 #endif
759769
760- autoreload_suspend (AUTORELOAD_LOCK_REPL );
770+ autoreload_suspend (AUTORELOAD_SUSPEND_REPL );
761771
762772 // Set the status LED to the REPL color before running the REPL. For
763773 // NeoPixels and DotStars this will be sticky but for PWM or single LED it
@@ -787,7 +797,7 @@ STATIC int run_repl(bool first_run) {
787797 status_led_deinit ();
788798 #endif
789799
790- autoreload_resume (AUTORELOAD_LOCK_REPL );
800+ autoreload_resume (AUTORELOAD_SUSPEND_REPL );
791801 return exit_code ;
792802}
793803
0 commit comments