@@ -204,6 +204,22 @@ STATIC void stop_mp(void) {
204
204
gc_deinit ();
205
205
}
206
206
207
+ STATIC const char * _current_executing_filename = NULL ;
208
+
209
+ STATIC pyexec_result_t _exec_result = {0 , MP_OBJ_NULL , 0 };
210
+
211
+ void supervisor_execution_status (void ) {
212
+ mp_obj_exception_t * exception = MP_OBJ_TO_PTR (_exec_result .exception );
213
+ if (_current_executing_filename != NULL ) {
214
+ serial_write (_current_executing_filename );
215
+ } else if ((_exec_result .return_code & PYEXEC_EXCEPTION ) != 0 &&
216
+ exception != NULL ) {
217
+ mp_printf (& mp_plat_print , "@%d %q" , _exec_result .exception_line , exception -> base .type -> name );
218
+ } else {
219
+ serial_write_compressed (translate ("Done" ));
220
+ }
221
+ }
222
+
207
223
#define STRING_LIST (...) {__VA_ARGS__, ""}
208
224
209
225
// Look for the first file that exists in the list of filenames, using mp_import_stat().
@@ -218,17 +234,23 @@ STATIC const char *first_existing_file_in_list(const char *const *filenames) {
218
234
return NULL ;
219
235
}
220
236
221
- STATIC bool maybe_run_list (const char * const * filenames , pyexec_result_t * exec_result ) {
222
- const char * filename = first_existing_file_in_list (filenames );
223
- if (filename == NULL ) {
237
+ STATIC bool maybe_run_list (const char * const * filenames ) {
238
+ _exec_result .return_code = 0 ;
239
+ _exec_result .exception = MP_OBJ_NULL ;
240
+ _exec_result .exception_line = 0 ;
241
+ _current_executing_filename = first_existing_file_in_list (filenames );
242
+ if (_current_executing_filename == NULL ) {
224
243
return false;
225
244
}
226
- mp_hal_stdout_tx_str (filename );
245
+ mp_hal_stdout_tx_str (_current_executing_filename );
227
246
serial_write_compressed (translate (" output:\n" ));
228
- pyexec_file (filename , exec_result );
247
+ supervisor_title_bar_update ();
248
+ pyexec_file (_current_executing_filename , & _exec_result );
229
249
#if CIRCUITPY_ATEXIT
230
- shared_module_atexit_execute (exec_result );
250
+ shared_module_atexit_execute (& _exec_result );
231
251
#endif
252
+ _current_executing_filename = NULL ;
253
+ supervisor_title_bar_update ();
232
254
return true;
233
255
}
234
256
@@ -347,12 +369,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
347
369
}
348
370
#endif
349
371
350
- pyexec_result_t result ;
351
-
352
- result .return_code = 0 ;
353
- result .exception = MP_OBJ_NULL ;
354
- result .exception_line = 0 ;
355
-
356
372
bool skip_repl = false;
357
373
bool skip_wait = false;
358
374
bool found_main = false;
@@ -391,7 +407,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
391
407
if (((next_code_info_t * )next_code_allocation -> ptr )-> filename [0 ] != '\0' ) {
392
408
const char * next_list [] = {((next_code_info_t * )next_code_allocation -> ptr )-> filename , "" };
393
409
// This is where the user's python code is actually executed:
394
- found_main = maybe_run_list (next_list , & result );
410
+ found_main = maybe_run_list (next_list );
395
411
if (!found_main ) {
396
412
serial_write (((next_code_info_t * )next_code_allocation -> ptr )-> filename );
397
413
serial_write_compressed (translate (" not found.\n" ));
@@ -401,11 +417,11 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
401
417
// Otherwise, default to the standard list of filenames
402
418
if (!found_main ) {
403
419
// This is where the user's python code is actually executed:
404
- found_main = maybe_run_list (supported_filenames , & result );
420
+ found_main = maybe_run_list (supported_filenames );
405
421
// If that didn't work, double check the extensions
406
422
#if CIRCUITPY_FULL_BUILD
407
423
if (!found_main ) {
408
- found_main = maybe_run_list (double_extension_filenames , & result );
424
+ found_main = maybe_run_list (double_extension_filenames );
409
425
if (found_main ) {
410
426
serial_write_compressed (translate ("WARNING: Your code filename has two extensions\n" ));
411
427
}
@@ -417,15 +433,15 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
417
433
418
434
// Print done before resetting everything so that we get the message over
419
435
// BLE before it is reset and we have a delay before reconnect.
420
- if ((result .return_code & PYEXEC_RELOAD ) && supervisor_get_run_reason () == RUN_REASON_AUTO_RELOAD ) {
436
+ if ((_exec_result .return_code & PYEXEC_RELOAD ) && supervisor_get_run_reason () == RUN_REASON_AUTO_RELOAD ) {
421
437
serial_write_compressed (translate ("\nCode stopped by auto-reload. Reloading soon.\n" ));
422
438
} else {
423
439
serial_write_compressed (translate ("\nCode done running.\n" ));
424
440
}
425
441
426
442
427
443
// Finished executing python code. Cleanup includes filesystem flush and a board reset.
428
- cleanup_after_vm (heap , result .exception );
444
+ cleanup_after_vm (heap , _exec_result .exception );
429
445
430
446
// If a new next code file was set, that is a reason to keep it (obviously). Stuff this into
431
447
// the options because it can be treated like any other reason-for-stickiness bit. The
@@ -436,15 +452,15 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
436
452
next_code_options |= SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET ;
437
453
}
438
454
439
- if (result .return_code & PYEXEC_RELOAD ) {
455
+ if (_exec_result .return_code & PYEXEC_RELOAD ) {
440
456
next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD ;
441
457
// Reload immediately unless the reload is due to autoreload. In that
442
458
// case, we wait below to see if any other writes occur.
443
459
if (supervisor_get_run_reason () != RUN_REASON_AUTO_RELOAD ) {
444
460
skip_repl = true;
445
461
skip_wait = true;
446
462
}
447
- } else if (result .return_code == 0 ) {
463
+ } else if (_exec_result .return_code == 0 ) {
448
464
next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_SUCCESS ;
449
465
if (next_code_options & SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_SUCCESS ) {
450
466
skip_repl = true;
@@ -455,12 +471,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
455
471
// Deep sleep cannot be skipped
456
472
// TODO: settings in deep sleep should persist, using a new sleep memory API
457
473
if (next_code_options & SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_ERROR
458
- && !(result .return_code & PYEXEC_DEEP_SLEEP )) {
474
+ && !(_exec_result .return_code & PYEXEC_DEEP_SLEEP )) {
459
475
skip_repl = true;
460
476
skip_wait = true;
461
477
}
462
478
}
463
- if (result .return_code & PYEXEC_FORCED_EXIT ) {
479
+ if (_exec_result .return_code & PYEXEC_FORCED_EXIT ) {
464
480
skip_repl = false;
465
481
skip_wait = true;
466
482
}
@@ -478,12 +494,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
478
494
uint8_t blink_count ;
479
495
bool led_active = false;
480
496
#if CIRCUITPY_ALARM
481
- if (result .return_code & PYEXEC_DEEP_SLEEP ) {
497
+ if (_exec_result .return_code & PYEXEC_DEEP_SLEEP ) {
482
498
color = BLACK ;
483
499
blink_count = 0 ;
484
500
} else
485
501
#endif
486
- if (result .return_code != PYEXEC_EXCEPTION ) {
502
+ if (_exec_result .return_code != PYEXEC_EXCEPTION ) {
487
503
if (safe_mode == NO_SAFE_MODE ) {
488
504
color = ALL_DONE ;
489
505
blink_count = ALL_DONE_BLINKS ;
@@ -568,7 +584,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
568
584
569
585
// Sleep until our next interrupt.
570
586
#if CIRCUITPY_ALARM
571
- if (result .return_code & PYEXEC_DEEP_SLEEP ) {
587
+ if (_exec_result .return_code & PYEXEC_DEEP_SLEEP ) {
572
588
const bool awoke_from_true_deep_sleep =
573
589
common_hal_mcu_processor_get_reset_reason () == RESET_REASON_DEEP_SLEEP_ALARM ;
574
590
@@ -730,19 +746,28 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
730
746
usb_set_defaults ();
731
747
#endif
732
748
733
- pyexec_result_t result = {0 , MP_OBJ_NULL , 0 };
734
-
735
749
if (ok_to_run ) {
736
750
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
751
+ // Turn off title bar updates when writing out to boot_out.txt.
752
+ supervisor_title_bar_suspend ();
737
753
vstr_t boot_text ;
738
754
vstr_init (& boot_text , 512 );
739
755
boot_output = & boot_text ;
740
756
#endif
741
757
742
758
// Write version info
743
759
mp_printf (& mp_plat_print , "%s\nBoard ID:%s\n" , MICROPY_FULL_VERSION_INFO , CIRCUITPY_BOARD_ID );
760
+ #if CIRCUITPY_MICROCONTROLLER && COMMON_HAL_MCU_PROCESSOR_UID_LENGTH > 0
761
+ uint8_t raw_id [COMMON_HAL_MCU_PROCESSOR_UID_LENGTH ];
762
+ common_hal_mcu_processor_get_uid (raw_id );
763
+ mp_printf (& mp_plat_print , "UID:" );
764
+ for (uint8_t i = 0 ; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH ; i ++ ) {
765
+ mp_printf (& mp_plat_print , "%02X" , raw_id [i ]);
766
+ }
767
+ mp_printf (& mp_plat_print , "\n" );
768
+ #endif
744
769
745
- bool found_boot = maybe_run_list (boot_py_filenames , & result );
770
+ bool found_boot = maybe_run_list (boot_py_filenames );
746
771
(void )found_boot ;
747
772
748
773
@@ -752,6 +777,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
752
777
FATFS * fs = & vfs -> fatfs ;
753
778
754
779
boot_output = NULL ;
780
+ supervisor_title_bar_resume ();
755
781
bool write_boot_output = true;
756
782
FIL boot_output_file ;
757
783
if (f_open (fs , & boot_output_file , CIRCUITPY_BOOT_OUTPUT_FILE , FA_READ ) == FR_OK ) {
@@ -794,7 +820,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
794
820
795
821
port_post_boot_py (true);
796
822
797
- cleanup_after_vm (heap , result .exception );
823
+ cleanup_after_vm (heap , _exec_result .exception );
798
824
799
825
port_post_boot_py (false);
800
826
@@ -831,7 +857,11 @@ STATIC int run_repl(bool first_run) {
831
857
exit_code = pyexec_raw_repl ();
832
858
supervisor_title_bar_resume ();
833
859
} else {
860
+ _current_executing_filename = "REPL" ;
861
+ supervisor_title_bar_update ();
834
862
exit_code = pyexec_friendly_repl ();
863
+ _current_executing_filename = NULL ;
864
+ supervisor_title_bar_update ();
835
865
}
836
866
#if CIRCUITPY_ATEXIT
837
867
pyexec_result_t result ;
@@ -841,6 +871,13 @@ STATIC int run_repl(bool first_run) {
841
871
}
842
872
#endif
843
873
cleanup_after_vm (heap , MP_OBJ_SENTINEL );
874
+
875
+ // Also reset bleio. The above call omits it in case workflows should continue. In this case,
876
+ // we're switching straight to another VM so we want to reset.
877
+ #if CIRCUITPY_BLEIO
878
+ bleio_reset ();
879
+ #endif
880
+
844
881
#if CIRCUITPY_STATUS_LED
845
882
status_led_init ();
846
883
new_status_color (BLACK );
0 commit comments