Skip to content

Commit ff0b3a9

Browse files
authored
Merge pull request #6153 from tannewt/refine_autoreload
Further refine autoreload
2 parents 0fd3da5 + 32ac396 commit ff0b3a9

File tree

8 files changed

+82
-57
lines changed

8 files changed

+82
-57
lines changed

locale/circuitpython.pot

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ msgstr ""
2525
#: main.c
2626
msgid ""
2727
"\n"
28-
"Code stopped by auto-reload.\n"
28+
"Code stopped by auto-reload. Reloading soon.\n"
2929
msgstr ""
3030

3131
#: supervisor/shared/safe_mode.c
@@ -584,10 +584,6 @@ msgstr ""
584584
msgid "Brightness must be 0-1.0"
585585
msgstr ""
586586

587-
#: shared-bindings/supervisor/__init__.c
588-
msgid "Brightness must be between 0 and 255"
589-
msgstr ""
590-
591587
#: shared-bindings/displayio/Display.c
592588
#: shared-bindings/framebufferio/FramebufferDisplay.c
593589
msgid "Brightness not adjustable"
@@ -688,6 +684,7 @@ msgstr ""
688684
msgid "Can only alarm on two low pins from deep sleep."
689685
msgstr ""
690686

687+
#: ports/espressif/common-hal/_bleio/Characteristic.c
691688
#: ports/nrf/common-hal/_bleio/Characteristic.c
692689
msgid "Can't set CCCD on local Characteristic"
693690
msgstr ""
@@ -1605,6 +1602,7 @@ msgstr ""
16051602
msgid "Nimble out of memory"
16061603
msgstr ""
16071604

1605+
#: ports/espressif/common-hal/_bleio/Characteristic.c
16081606
#: ports/nrf/common-hal/_bleio/Characteristic.c
16091607
msgid "No CCCD for this Characteristic"
16101608
msgstr ""
@@ -3642,7 +3640,7 @@ msgstr ""
36423640
msgid "matrix is not positive definite"
36433641
msgstr ""
36443642

3645-
#: shared-bindings/wifi/Radio.c
3643+
#: ports/espressif/common-hal/wifi/Radio.c
36463644
msgid "max_connections must be between 0 and 10"
36473645
msgstr ""
36483646

@@ -4061,13 +4059,15 @@ msgstr ""
40614059
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
40624060
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
40634061
#: ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h
4062+
#: ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.h
40644063
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
40654064
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
40664065
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
40674066
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
40684067
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
40694068
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
40704069
#: ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/mpconfigboard.h
4070+
#: ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/mpconfigboard.h
40714071
#: ports/espressif/boards/espressif_esp32s3_box/mpconfigboard.h
40724072
#: ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/mpconfigboard.h
40734073
#: ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2/mpconfigboard.h
@@ -4083,6 +4083,7 @@ msgstr ""
40834083
#: ports/espressif/boards/gravitech_cucumber_ms/mpconfigboard.h
40844084
#: ports/espressif/boards/gravitech_cucumber_r/mpconfigboard.h
40854085
#: ports/espressif/boards/gravitech_cucumber_rs/mpconfigboard.h
4086+
#: ports/espressif/boards/hiibot_iots2/mpconfigboard.h
40864087
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
40874088
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
40884089
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h

main.c

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ static void reset_devices(void) {
124124
}
125125

126126
STATIC void start_mp(supervisor_allocation *heap, bool first_run) {
127-
autoreload_reset();
128127
supervisor_workflow_reset();
129128

130129
// Stack limit should be less than real stack size, so we have a chance
@@ -336,7 +335,13 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
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.
@@ -390,22 +393,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
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.
392395
if ((result.return_code & PYEXEC_RELOAD) && supervisor_get_run_reason() == RUN_REASON_AUTO_RELOAD) {
393-
serial_write_compressed(translate("\nCode stopped by auto-reload.\n"));
394-
395-
// Wait for autoreload interval before reloading
396-
uint64_t start_ticks = 0;
397-
do {
398-
// Start waiting, or restart interval if another reload request was initiated
399-
// while we were waiting.
400-
if (reload_requested) {
401-
reload_requested = false;
402-
start_ticks = supervisor_ticks_ms64();
403-
}
404-
RUN_BACKGROUND_TASKS;
405-
} while (supervisor_ticks_ms64() - start_ticks < CIRCUITPY_AUTORELOAD_DELAY_MS);
406-
407-
// Restore request for use below.
408-
reload_requested = true;
396+
serial_write_compressed(translate("\nCode stopped by auto-reload. Reloading soon.\n"));
409397
} else {
410398
serial_write_compressed(translate("\nCode done running.\n"));
411399
}
@@ -425,8 +413,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
425413

426414
if (result.return_code & PYEXEC_RELOAD) {
427415
next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD;
428-
skip_repl = true;
429-
skip_wait = true;
430416
} else if (result.return_code == 0) {
431417
next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_SUCCESS;
432418
if (next_code_options & SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_SUCCESS) {
@@ -484,22 +470,27 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
484470
size_t total_time = blink_time + LED_SLEEP_TIME_MS;
485471
#endif
486472

473+
// This loop is waits after code completes. It waits for fake sleeps to
474+
// finish, user input or autoreloads.
487475
#if CIRCUITPY_ALARM
488476
bool fake_sleeping = false;
489477
#endif
490478
while (!skip_wait) {
491479
RUN_BACKGROUND_TASKS;
492480

493481
// If a reload was requested by the supervisor or autoreload, return.
494-
if (reload_requested) {
482+
if (autoreload_ready()) {
495483
next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD;
496484
// Should the STICKY_ON_SUCCESS and STICKY_ON_ERROR bits be cleared in
497485
// next_code_stickiness_situation? I can see arguments either way, but I'm deciding
498486
// "no" for now, mainly because it's a bit less code. At this point, we have both a
499487
// success or error and a reload, so let's have both of the respective options take
500488
// effect (in OR combination).
501-
reload_requested = false;
502489
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();
503494
break;
504495
}
505496

@@ -526,7 +517,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
526517
#endif
527518

528519
// If messages haven't been printed yet, print them
529-
if (!printed_press_any_key && serial_connected()) {
520+
if (!printed_press_any_key && serial_connected() && !autoreload_pending()) {
530521
if (!serial_connected_at_start) {
531522
print_code_py_status_message(safe_mode);
532523
}

ports/stm/supervisor/port.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,6 @@ void port_enable_tick(void) {
346346
stm32_peripherals_rtc_assign_wkup_callback(supervisor_tick);
347347
stm32_peripherals_rtc_enable_wakeup_timer();
348348
}
349-
// TODO: what is this? can I get rid of it?
350-
extern volatile uint32_t autoreload_delay_ms;
351349

352350
// Disable 1/1024 second tick.
353351
void port_disable_tick(void) {

shared-module/displayio/__init__.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ void displayio_background(void) {
8282
if (mp_hal_is_interrupted()) {
8383
return;
8484
}
85-
if (reload_requested) {
85+
if (autoreload_ready()) {
8686
// Reload is about to happen, so don't redisplay.
8787
return;
8888
}

supervisor/shared/bluetooth/file_transfer.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
325325
if (chunk_size == 0) {
326326
// Don't reload until everything is written out of the packet buffer.
327327
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
328-
// Trigger an autoreload
329-
autoreload_start();
328+
autoreload_trigger();
330329
return ANY_COMMAND;
331330
}
332331

@@ -383,8 +382,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
383382
#endif
384383
// Don't reload until everything is written out of the packet buffer.
385384
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
386-
// Trigger an autoreload
387-
autoreload_start();
385+
autoreload_trigger();
388386
return ANY_COMMAND;
389387
}
390388
return WRITE_DATA;
@@ -465,8 +463,7 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
465463
if (result == FR_OK) {
466464
// Don't reload until everything is written out of the packet buffer.
467465
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
468-
// Trigger an autoreload
469-
autoreload_start();
466+
autoreload_trigger();
470467
}
471468
return ANY_COMMAND;
472469
}
@@ -520,8 +517,7 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) {
520517
if (result == FR_OK) {
521518
// Don't reload until everything is written out of the packet buffer.
522519
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
523-
// Trigger an autoreload
524-
autoreload_start();
520+
autoreload_trigger();
525521
}
526522
return ANY_COMMAND;
527523
}
@@ -668,8 +664,7 @@ STATIC uint8_t _process_move(const uint8_t *raw_buf, size_t command_len) {
668664
if (result == FR_OK) {
669665
// Don't reload until everything is written out of the packet buffer.
670666
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
671-
// Trigger an autoreload
672-
autoreload_start();
667+
autoreload_trigger();
673668
}
674669
return ANY_COMMAND;
675670
}

supervisor/shared/reload.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,9 @@ static bool autoreload_enabled = false;
4040
// Non-zero if autoreload is temporarily off, due to an AUTORELOAD_SUSPEND_... reason.
4141
static uint32_t autoreload_suspended = 0;
4242

43-
// True if something has requested a reload/restart.
44-
volatile bool reload_requested = false;
43+
volatile uint32_t last_autoreload_trigger = 0;
4544

4645
void reload_initiate(supervisor_run_reason_t run_reason) {
47-
reload_requested = true;
4846
supervisor_set_run_reason(run_reason);
4947

5048
// Raise reload exception, in case code is running.
@@ -57,12 +55,12 @@ void reload_initiate(supervisor_run_reason_t run_reason) {
5755
}
5856

5957
void autoreload_reset() {
60-
reload_requested = false;
58+
last_autoreload_trigger = 0;
6159
}
6260

6361
void autoreload_enable() {
6462
autoreload_enabled = true;
65-
reload_requested = false;
63+
last_autoreload_trigger = 0;
6664
}
6765

6866
void autoreload_disable() {
@@ -81,8 +79,35 @@ inline bool autoreload_is_enabled() {
8179
return autoreload_enabled;
8280
}
8381

84-
void autoreload_start() {
85-
if (autoreload_enabled && autoreload_suspended == 0) {
82+
void autoreload_trigger() {
83+
if (autoreload_enabled) {
84+
last_autoreload_trigger = supervisor_ticks_ms32();
85+
// Guard against the rare time that ticks is 0;
86+
if (last_autoreload_trigger == 0) {
87+
last_autoreload_trigger += 1;
88+
}
89+
// Initiate a reload of the VM immediately. Later code will pause to
90+
// wait for the autoreload to become ready. Doing the VM exit
91+
// immediately is clearer for the user.
8692
reload_initiate(RUN_REASON_AUTO_RELOAD);
8793
}
8894
}
95+
96+
bool autoreload_ready() {
97+
if (last_autoreload_trigger == 0 || autoreload_suspended != 0) {
98+
return false;
99+
}
100+
// Wait for autoreload interval before reloading
101+
uint32_t now = supervisor_ticks_ms32();
102+
uint32_t diff;
103+
if (now >= last_autoreload_trigger) {
104+
diff = now - last_autoreload_trigger;
105+
} else {
106+
diff = now + (0xffffffff - last_autoreload_trigger);
107+
}
108+
return diff > CIRCUITPY_AUTORELOAD_DELAY_MS;
109+
}
110+
111+
bool autoreload_pending(void) {
112+
return last_autoreload_trigger != 0;
113+
}

supervisor/shared/reload.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ enum {
4242

4343
enum {
4444
AUTORELOAD_SUSPEND_REPL = 0x1,
45-
AUTORELOAD_SUSPEND_BLE = 0x2
45+
AUTORELOAD_SUSPEND_BLE = 0x2,
46+
AUTORELOAD_SUSPEND_USB = 0x4
4647
};
4748

4849
typedef struct {
@@ -52,17 +53,29 @@ typedef struct {
5253

5354
extern supervisor_allocation *next_code_allocation;
5455

55-
extern volatile bool reload_requested;
56-
56+
// Helper for exiting the VM and reloading immediately.
5757
void reload_initiate(supervisor_run_reason_t run_reason);
5858

59-
void autoreload_start(void);
60-
void autoreload_reset(void);
59+
// Enabled state is user controllable and very sticky. We don't reset it.
6160
void autoreload_enable(void);
6261
void autoreload_disable(void);
6362
bool autoreload_is_enabled(void);
6463

65-
// Temporarily turn autoreload off, for the given reason(s).
64+
// Start the autoreload process.
65+
void autoreload_trigger(void);
66+
// True when the autoreload should occur. (A trigger happened and the delay has
67+
// passed.)
68+
bool autoreload_ready(void);
69+
// Reset the autoreload timer in preparation for another trigger. Call when the
70+
// last trigger starts being executed.
71+
void autoreload_reset(void);
72+
// True when a trigger has occurred but we're still delaying in case another
73+
// trigger occurs.
74+
bool autoreload_pending(void);
75+
76+
// Temporarily turn autoreload off, for the given reason(s). Autoreload triggers
77+
// will still be tracked so resuming with autoreload ready with cause an
78+
// immediate reload.
6679
// Used during the REPL or during parts of BLE workflow.
6780
void autoreload_suspend(uint32_t suspend_reason_mask);
6881
// Allow autoreloads again, for the given reason(s).

supervisor/shared/usb/usb_msc_flash.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buff
185185
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) {
186186
(void)lun;
187187
(void)offset;
188+
autoreload_suspend(AUTORELOAD_SUSPEND_USB);
188189

189190
const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE;
190191

@@ -215,7 +216,8 @@ void tud_msc_write10_complete_cb(uint8_t lun) {
215216
(void)lun;
216217

217218
// This write is complete; initiate an autoreload.
218-
autoreload_start();
219+
autoreload_trigger();
220+
autoreload_resume(AUTORELOAD_SUSPEND_USB);
219221
}
220222

221223
// Invoked when received SCSI_CMD_INQUIRY

0 commit comments

Comments
 (0)