rework auto-reload delay logic

This commit is contained in:
Dan Halbert 2022-03-11 13:29:20 -05:00
parent 0957c1546f
commit e4cd9690f1
19 changed files with 71 additions and 138 deletions

24
main.c
View File

@ -52,7 +52,7 @@
#include "supervisor/memory.h"
#include "supervisor/port.h"
#include "supervisor/serial.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/reload.h"
#include "supervisor/shared/safe_mode.h"
#include "supervisor/shared/stack.h"
#include "supervisor/shared/status_leds.h"
@ -389,12 +389,28 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
// Print done before resetting everything so that we get the message over
// BLE before it is reset and we have a delay before reconnect.
if (result.return_code == PYEXEC_RELOAD) {
if ((result.return_code & PYEXEC_RELOAD) && supervisor_get_run_reason() == RUN_REASON_AUTO_RELOAD) {
serial_write_compressed(translate("\nCode stopped by auto-reload.\n"));
// Wait for autoreload interval before reloading
uint64_t start_ticks = 0;
do {
// Start waiting, or restart interval if another reload request was initiated
// while we were waiting.
if (reload_requested) {
reload_requested = false;
start_ticks = supervisor_ticks_ms64();
}
RUN_BACKGROUND_TASKS;
} while (supervisor_ticks_ms64() - start_ticks < CIRCUITPY_AUTORELOAD_DELAY_MS);
// Restore request for use below.
reload_requested = true;
} else {
serial_write_compressed(translate("\nCode done running.\n"));
}
// Finished executing python code. Cleanup includes filesystem flush and a board reset.
cleanup_after_vm(heap, result.exception);
@ -474,8 +490,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
while (!skip_wait) {
RUN_BACKGROUND_TASKS;
// If a reload was requested by the supervisor or autoreload, return
if (result.return_code & PYEXEC_RELOAD) {
// If a reload was requested by the supervisor or autoreload, return.
if (reload_requested) {
next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD;
// Should the STICKY_ON_SUCCESS and STICKY_ON_ERROR bits be cleared in
// next_code_stickiness_situation? I can see arguments either way, but I'm deciding

View File

@ -34,7 +34,6 @@
#include "py/smallint.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/time/__init__.h"
#include "supervisor/shared/autoreload.h"
#include "hal/include/hal_atomic.h"
#include "hal/include/hal_delay.h"

View File

@ -34,7 +34,6 @@
#include "py/smallint.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/time/__init__.h"
#include "supervisor/shared/autoreload.h"
#include "mpconfigboard.h"
#include "mphalport.h"

View File

@ -436,7 +436,7 @@ void supervisor_run_background_tasks_if_tick(void);
// CIRCUITPY_AUTORELOAD_DELAY_MS = 0 will completely disable autoreload.
#ifndef CIRCUITPY_AUTORELOAD_DELAY_MS
#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
#define CIRCUITPY_AUTORELOAD_DELAY_MS 750
#endif
#ifndef CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS

View File

@ -159,7 +159,6 @@ PY_CORE_O_BASENAME = $(addprefix py/,\
objzip.o \
opmethods.o \
proto.o \
reload.o \
sequence.o \
stream.o \
binary.o \

View File

@ -1,32 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 by Roy Hooper
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "reload.h"
#include "py/mpstate.h"
void mp_raise_reload_exception(void) {
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception));
#if MICROPY_ENABLE_SCHEDULER
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
}
#endif
}

View File

@ -1,26 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 by Roy Hooper
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CIRCUITPYTHON_RELOAD_H
#define CIRCUITPYTHON_RELOAD_H
void mp_raise_reload_exception(void);
#endif // CIRCUITPYTHON_RELOAD_H

View File

@ -25,7 +25,6 @@
*/
#include "py/obj.h"
#include "py/reload.h"
#include "py/runtime.h"
#include "shared-bindings/alarm/__init__.h"
@ -35,7 +34,6 @@
#include "shared-bindings/alarm/touch/TouchAlarm.h"
#include "shared-bindings/supervisor/Runtime.h"
#include "shared-bindings/time/__init__.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/workflow.h"
//| """Alarms and sleep

View File

@ -108,6 +108,14 @@ const mp_obj_property_t supervisor_runtime_serial_bytes_available_obj = {
MP_ROM_NONE},
};
supervisor_run_reason_t supervisor_get_run_reason(void) {
return _run_reason;
}
void supervisor_set_run_reason(supervisor_run_reason_t run_reason) {
_run_reason = run_reason;
}
//| run_reason: RunReason
//| """Returns why CircuitPython started running this particular time."""
//|
@ -123,10 +131,6 @@ const mp_obj_property_t supervisor_runtime_run_reason_obj = {
MP_ROM_NONE},
};
void supervisor_set_run_reason(supervisor_run_reason_t run_reason) {
_run_reason = run_reason;
}
STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_usb_connected), MP_ROM_PTR(&supervisor_runtime_usb_connected_obj) },
{ MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_runtime_serial_connected_obj) },

View File

@ -34,6 +34,7 @@
extern const mp_obj_type_t supervisor_runtime_type;
supervisor_run_reason_t supervisor_get_run_reason(void);
void supervisor_set_run_reason(supervisor_run_reason_t run_reason);
bool common_hal_supervisor_runtime_get_serial_connected(void);

View File

@ -27,14 +27,13 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "py/reload.h"
#include "py/objstr.h"
#include "shared/runtime/interrupt_char.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/bluetooth/bluetooth.h"
#include "supervisor/shared/display.h"
#include "supervisor/shared/status_leds.h"
#include "supervisor/shared/reload.h"
#include "supervisor/shared/stack.h"
#include "supervisor/shared/traceback.h"
#include "supervisor/shared/translate.h"
@ -95,8 +94,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_s
//| ...
//|
STATIC mp_obj_t supervisor_reload(void) {
supervisor_set_run_reason(RUN_REASON_SUPERVISOR_RELOAD);
mp_raise_reload_exception();
reload_initiate(RUN_REASON_SUPERVISOR_RELOAD);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload);

View File

@ -29,7 +29,6 @@
#include "shared-module/displayio/__init__.h"
#include "shared/runtime/interrupt_char.h"
#include "py/reload.h"
#include "py/runtime.h"
#include "shared-bindings/board/__init__.h"
#include "shared-bindings/displayio/Bitmap.h"
@ -37,8 +36,8 @@
#include "shared-bindings/displayio/Group.h"
#include "shared-bindings/displayio/Palette.h"
#include "shared-module/displayio/area.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/display.h"
#include "supervisor/shared/reload.h"
#include "supervisor/memory.h"
#include "supervisor/spi_flash_api.h"

View File

@ -43,7 +43,7 @@
#include "common-hal/_bleio/__init__.h"
#include "supervisor/fatfs_port.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/reload.h"
#include "supervisor/shared/bluetooth/file_transfer.h"
#include "supervisor/shared/bluetooth/file_transfer_protocol.h"
#include "supervisor/shared/tick.h"
@ -326,7 +326,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) {
// Don't reload until everything is written out of the packet buffer.
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
// Trigger an autoreload
autoreload_start_countdown();
autoreload_start();
return ANY_COMMAND;
}
@ -384,7 +384,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) {
// Don't reload until everything is written out of the packet buffer.
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
// Trigger an autoreload
autoreload_start_countdown();
autoreload_start();
return ANY_COMMAND;
}
return WRITE_DATA;
@ -466,7 +466,7 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) {
// Don't reload until everything is written out of the packet buffer.
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
// Trigger an autoreload
autoreload_start_countdown();
autoreload_start();
}
return ANY_COMMAND;
}
@ -521,7 +521,7 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) {
// Don't reload until everything is written out of the packet buffer.
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
// Trigger an autoreload
autoreload_start_countdown();
autoreload_start();
}
return ANY_COMMAND;
}
@ -669,7 +669,7 @@ STATIC uint8_t _process_move(const uint8_t *raw_buf, size_t command_len) {
// Don't reload until everything is written out of the packet buffer.
common_hal_bleio_packet_buffer_flush(&_transfer_packet_buffer);
// Trigger an autoreload
autoreload_start_countdown();
autoreload_start();
}
return ANY_COMMAND;
}

View File

@ -24,65 +24,49 @@
* THE SOFTWARE.
*/
#include "autoreload.h"
#include "reload.h"
#include "py/mphal.h"
#include "py/reload.h"
#include "py/mpstate.h"
#include "supervisor/shared/reload.h"
#include "supervisor/shared/tick.h"
supervisor_allocation *next_code_allocation;
#include "shared-bindings/supervisor/Runtime.h"
static volatile uint32_t autoreload_countdown_ms = 0;
// True if user has disabled autoreload.
static bool autoreload_enabled = false;
// Non-zero if autoreload is temporarily off, due to an AUTORELOAD_SUSPEND_... reason.
static uint32_t autoreload_suspended = 0;
// True if autoreload has been triggered. Wait for CIRCUITPY_AUTORELOAD_DELAY_MS before doing the
// autoreload, in case further writes arrive.
static bool autoreload_countdown = false;
// True if something has requested a reload/restart.
volatile bool reload_requested = false;
void autoreload_reset() {
if (autoreload_countdown) {
supervisor_disable_tick();
autoreload_countdown = false;
void reload_initiate(supervisor_run_reason_t run_reason) {
reload_requested = true;
supervisor_set_run_reason(run_reason);
// Raise reload exception, in case code is running.
MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception));
#if MICROPY_ENABLE_SCHEDULER
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
}
autoreload_countdown_ms = 0;
reload_requested = false;
#endif
}
inline void autoreload_tick() {
if (!autoreload_countdown) {
return;
}
if (autoreload_countdown_ms > 0) {
autoreload_countdown_ms--;
}
if (autoreload_countdown_ms == 0 && autoreload_enabled &&
autoreload_suspended == 0 && !reload_requested) {
reload_requested = true;
autoreload_countdown = false;
supervisor_disable_tick();
supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD);
mp_raise_reload_exception();
}
void autoreload_reset() {
reload_requested = false;
}
void autoreload_enable() {
autoreload_enabled = true;
reload_requested = false;
autoreload_countdown = false;
}
void autoreload_disable() {
autoreload_enabled = false;
autoreload_countdown = false;
}
void autoreload_suspend(uint32_t suspend_reason_mask) {
@ -97,12 +81,8 @@ inline bool autoreload_is_enabled() {
return autoreload_enabled;
}
void autoreload_start_countdown() {
// Avoid multiple tick enables.
if (!autoreload_countdown) {
supervisor_enable_tick();
autoreload_countdown = true;
void autoreload_start() {
if (autoreload_enabled && autoreload_suspended == 0) {
reload_initiate(RUN_REASON_AUTO_RELOAD);
}
// Start or restart the countdown interval.
autoreload_countdown_ms = CIRCUITPY_AUTORELOAD_DELAY_MS;
}

View File

@ -27,9 +27,9 @@
#ifndef MICROPY_INCLUDED_SUPERVISOR_AUTORELOAD_H
#define MICROPY_INCLUDED_SUPERVISOR_AUTORELOAD_H
#include <stdbool.h>
#include "supervisor/memory.h"
#include "py/obj.h"
#include "shared-bindings/supervisor/RunReason.h"
enum {
SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_SUCCESS = 0x1,
@ -54,18 +54,18 @@ extern supervisor_allocation *next_code_allocation;
extern volatile bool reload_requested;
void autoreload_tick(void);
void reload_initiate(supervisor_run_reason_t run_reason);
void autoreload_start_countdown(void);
void autoreload_start(void);
void autoreload_reset(void);
void autoreload_enable(void);
void autoreload_disable(void);
bool autoreload_is_enabled(void);
// Temporarily turn autoreload off, for the given reason(s). Used during the REPL or during parts of BLE workflow.
// Temporarily turn autoreload off, for the given reason(s).
// Used during the REPL or during parts of BLE workflow.
void autoreload_suspend(uint32_t suspend_reason_mask);
// Allow autoreloads again, for the given reason(s).
void autoreload_resume(uint32_t suspend_reason_mask);
#endif // MICROPY_INCLUDED_SUPERVISOR_AUTORELOAD_H

View File

@ -34,7 +34,6 @@
#include "supervisor/filesystem.h"
#include "supervisor/background_callback.h"
#include "supervisor/port.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/stack.h"
#if CIRCUITPY_BLEIO_HCI
@ -103,10 +102,6 @@ void supervisor_tick(void) {
filesystem_tick();
#endif
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
#endif
#ifdef CIRCUITPY_GAMEPAD_TICKS
if (!(port_get_raw_ticks(NULL) & CIRCUITPY_GAMEPAD_TICKS)) {
#if CIRCUITPY_GAMEPADSHIFT

View File

@ -37,20 +37,23 @@
* interrupt context.
*/
extern void supervisor_tick(void);
/** @brief Get the lower 32 bits of the time in milliseconds
*
* This can be more efficient than supervisor_ticks_ms64, for sites where a wraparound
* of ~49.5 days is not harmful.
*/
extern uint32_t supervisor_ticks_ms32(void);
/** @brief Get the full time in milliseconds
*
* Because common ARM mcus cannot atomically work with 64-bit quantities, this
* function must briefly disable interrupts in order to return the value. If
* only relative durations of less than about ~49.5 days need to be considered,
* then it may be possible to use supervisor_ticks_ms64 instead.
* then it may be possible to use supervisor_ticks_ms32() instead.
*/
extern uint64_t supervisor_ticks_ms64(void);
/** @brief Run background ticks, but only about every millisecond.
*
* Normally, this is not called directly. Instead use the RUN_BACKGROUND_TASKS

View File

@ -36,7 +36,7 @@
#include "shared-module/storage/__init__.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/shared/reload.h"
#define MSC_FLASH_BLOCK_SIZE 512
@ -214,8 +214,8 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *
void tud_msc_write10_complete_cb(uint8_t lun) {
(void)lun;
// This write is complete, start the autoreload clock.
autoreload_start_countdown();
// This write is complete; initiate an autoreload.
autoreload_start();
}
// Invoked when received SCSI_CMD_INQUIRY

View File

@ -1,7 +1,6 @@
SRC_SUPERVISOR = \
main.c \
supervisor/port.c \
supervisor/shared/autoreload.c \
supervisor/shared/background_callback.c \
supervisor/shared/board.c \
supervisor/shared/cpu.c \
@ -9,6 +8,7 @@ SRC_SUPERVISOR = \
supervisor/shared/lock.c \
supervisor/shared/memory.c \
supervisor/shared/micropython.c \
supervisor/shared/reload.c \
supervisor/shared/safe_mode.c \
supervisor/shared/stack.c \
supervisor/shared/status_leds.c \