From d933f8ac50753237745402a9ee54e7a751367be0 Mon Sep 17 00:00:00 2001 From: Michael Himing Date: Tue, 8 Mar 2022 16:39:24 +1100 Subject: [PATCH 01/15] Espressif: Fix i2c pullup detection --- ports/espressif/common-hal/busio/I2C.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/espressif/common-hal/busio/I2C.c b/ports/espressif/common-hal/busio/I2C.c index 454432ab91..0706de1df5 100644 --- a/ports/espressif/common-hal/busio/I2C.c +++ b/ports/espressif/common-hal/busio/I2C.c @@ -50,6 +50,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, gpio_set_direction(sda->number, GPIO_MODE_DEF_INPUT); gpio_set_direction(scl->number, GPIO_MODE_DEF_INPUT); + gpio_pullup_dis(sda->number); + gpio_pullup_dis(scl->number); gpio_pulldown_en(sda->number); gpio_pulldown_en(scl->number); From 9b2e22a6df3bf66f3f23f6f237e227790c942a9d Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 4 Mar 2022 13:34:20 -0500 Subject: [PATCH 02/15] Make autoreload checking more robust - Add reset for autoreload. De-request ticks. - Separate state a little more in autoreload.c - Rename some routines. - Remove redundant settings of CIRCUITPY_AUTORELOAD_DELAY_MS. --- main.c | 23 +++--- ports/atmel-samd/supervisor/port.c | 22 ++++-- .../nrf/boards/aramcon2_badge/mpconfigboard.h | 2 - .../arduino_nano_33_ble/mpconfigboard.h | 2 - ports/nrf/boards/bastble/mpconfigboard.h | 2 - .../feather_bluefruit_sense/mpconfigboard.h | 2 - .../boards/ikigaisense_vita/mpconfigboard.h | 2 - .../mpconfigboard.h | 2 - .../boards/warmbit_bluepixel/mpconfigboard.h | 2 - ports/stm/boards/pyb_nano_v2/mpconfigboard.h | 2 - .../stm32f411ce_blackpill/mpconfigboard.h | 2 - .../mpconfigboard.h | 4 +- shared-bindings/supervisor/__init__.c | 1 - shared/runtime/pyexec.c | 7 +- shared/runtime/pyexec.h | 1 + supervisor/shared/autoreload.c | 79 +++++++++++-------- supervisor/shared/autoreload.h | 16 ++-- supervisor/shared/bluetooth/file_transfer.c | 18 ++--- supervisor/shared/flash.c | 2 +- supervisor/shared/tick.c | 9 ++- supervisor/shared/usb/usb_msc_flash.c | 3 +- 21 files changed, 101 insertions(+), 102 deletions(-) diff --git a/main.c b/main.c index 3e6a34843f..d1fbc257a9 100644 --- a/main.c +++ b/main.c @@ -124,7 +124,7 @@ static void reset_devices(void) { } STATIC void start_mp(supervisor_allocation *heap, bool first_run) { - autoreload_stop(); + autoreload_reset(); supervisor_workflow_reset(); // Stack limit should be less than real stack size, so we have a chance @@ -329,7 +329,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re result.exception = MP_OBJ_NULL; result.exception_line = 0; - bool skip_repl; + bool skip_repl = false; bool skip_wait = false; bool found_main = false; uint8_t next_code_options = 0; @@ -389,13 +389,13 @@ 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 (reload_requested && result.return_code == PYEXEC_EXCEPTION) { + if (result.return_code == PYEXEC_RELOAD) { serial_write_compressed(translate("\nCode stopped by auto-reload.\n")); } else { serial_write_compressed(translate("\nCode done running.\n")); } - // Finished executing python code. Cleanup includes a board reset. + // Finished executing python code. Cleanup includes filesystem flush and a board reset. cleanup_after_vm(heap, result.exception); // If a new next code file was set, that is a reason to keep it (obviously). Stuff this into @@ -407,8 +407,10 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re next_code_options |= SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET; } - if (reload_requested) { + if (result.return_code & PYEXEC_RELOAD) { next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD; + skip_repl = true; + skip_wait = true; } else if (result.return_code == 0) { next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_SUCCESS; if (next_code_options & SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_SUCCESS) { @@ -426,7 +428,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re } } if (result.return_code & PYEXEC_FORCED_EXIT) { - skip_repl = reload_requested; + skip_repl = false; skip_wait = true; } } @@ -473,7 +475,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re RUN_BACKGROUND_TASKS; // If a reload was requested by the supervisor or autoreload, return - if (reload_requested) { + if (result.return_code & PYEXEC_RELOAD) { 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 @@ -627,13 +629,14 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re } } + // Done waiting, start the board back up. + // free code allocation if unused if ((next_code_options & next_code_stickiness_situation) == 0) { free_memory(next_code_allocation); next_code_allocation = NULL; } - // Done waiting, start the board back up. #if CIRCUITPY_STATUS_LED if (led_active) { new_status_color(BLACK); @@ -757,7 +760,7 @@ STATIC int run_repl(bool first_run) { usb_setup_with_vm(); #endif - autoreload_suspend(AUTORELOAD_LOCK_REPL); + autoreload_suspend(AUTORELOAD_SUSPEND_REPL); // Set the status LED to the REPL color before running the REPL. For // NeoPixels and DotStars this will be sticky but for PWM or single LED it @@ -787,7 +790,7 @@ STATIC int run_repl(bool first_run) { status_led_deinit(); #endif - autoreload_resume(AUTORELOAD_LOCK_REPL); + autoreload_resume(AUTORELOAD_SUSPEND_REPL); return exit_code; } diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 7be1fdb535..cccef8be53 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -129,8 +129,9 @@ #include "common-hal/_pew/PewPew.h" #endif static volatile bool sleep_ok = true; + #ifdef SAMD21 -static uint8_t _tick_event_channel = 0; +uint8_t _tick_event_channel; // Sleeping requires a register write that can stall interrupt handling. Turning // off sleeps allows for more accurate interrupt timing. (Python still thinks @@ -142,7 +143,13 @@ void rtc_start_pulse(void) { void rtc_end_pulse(void) { sleep_ok = true; } -#endif +#endif // SAMD21 + +static void reset_ticks(void) { + #ifdef SAMD21 + _tick_event_channel = EVSYS_SYNCH_NUM; + #endif +} extern volatile bool mp_msc_enabled; @@ -426,9 +433,7 @@ void reset_port(void) { #endif reset_event_system(); - #ifdef SAMD21 - _tick_event_channel = EVSYS_SYNCH_NUM; - #endif + reset_ticks(); reset_all_pins(); @@ -498,7 +503,7 @@ uint32_t port_get_saved_word(void) { static volatile uint64_t overflowed_ticks = 0; static uint32_t _get_count(uint64_t *overflow_count) { - while(1) { + while (1) { // Disable interrupts so we can grab the count and the overflow atomically. common_hal_mcu_disable_interrupts(); @@ -521,7 +526,7 @@ static uint32_t _get_count(uint64_t *overflow_count) { return count; } - // Try again if overflow hasn't been processed yet. + // Try again if overflow hasn't been processed yet. } } @@ -620,7 +625,7 @@ void port_enable_tick(void) { RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_PER2; #endif #ifdef SAMD21 - // SAMD21 ticks won't survive port_reset(). This *should* be ok since it'll + // SAMD21 ticks won't survive reset_port(). This *should* be ok since it'll // be triggered by ticks and no Python will be running. if (_tick_event_channel >= EVSYS_SYNCH_NUM) { turn_on_event_system(); @@ -653,6 +658,7 @@ void port_disable_tick(void) { uint8_t value = 1 << _tick_event_channel; EVSYS->INTENCLR.reg = EVSYS_INTENSET_EVD(value); } + _tick_event_channel = EVSYS_SYNCH_NUM; #endif } diff --git a/ports/nrf/boards/aramcon2_badge/mpconfigboard.h b/ports/nrf/boards/aramcon2_badge/mpconfigboard.h index 7691d1e461..517ad7324b 100644 --- a/ports/nrf/boards/aramcon2_badge/mpconfigboard.h +++ b/ports/nrf/boards/aramcon2_badge/mpconfigboard.h @@ -54,8 +54,6 @@ #define BOARD_USER_SAFE_MODE_ACTION translate("pressing the left button at start up\n") -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 - #define CIRCUITPY_INTERNAL_NVM_SIZE (4096) #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) diff --git a/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.h b/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.h index d34a862439..851632f860 100644 --- a/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.h +++ b/ports/nrf/boards/arduino_nano_33_ble/mpconfigboard.h @@ -3,8 +3,6 @@ #define MICROPY_HW_BOARD_NAME "Arduino Nano 33 BLE" #define MICROPY_HW_MCU_NAME "nRF52840" -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 - #define DEFAULT_I2C_BUS_SCL (&pin_P0_02) #define DEFAULT_I2C_BUS_SDA (&pin_P0_31) diff --git a/ports/nrf/boards/bastble/mpconfigboard.h b/ports/nrf/boards/bastble/mpconfigboard.h index e36227c6bc..e97fa429ee 100644 --- a/ports/nrf/boards/bastble/mpconfigboard.h +++ b/ports/nrf/boards/bastble/mpconfigboard.h @@ -3,8 +3,6 @@ #define MICROPY_HW_BOARD_NAME "BastBLE" #define MICROPY_HW_MCU_NAME "nRF52840" -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 - #if QSPI_FLASH_FILESYSTEM #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 30) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 29) diff --git a/ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.h b/ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.h index 65d8a642e8..558f66bf7b 100644 --- a/ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.h +++ b/ports/nrf/boards/feather_bluefruit_sense/mpconfigboard.h @@ -53,8 +53,6 @@ #define SPI_FLASH_CS_PIN &pin_P0_20 #endif -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 - #define CIRCUITPY_INTERNAL_NVM_SIZE (4096) #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) diff --git a/ports/nrf/boards/ikigaisense_vita/mpconfigboard.h b/ports/nrf/boards/ikigaisense_vita/mpconfigboard.h index 14798aeee2..49ef2b93be 100644 --- a/ports/nrf/boards/ikigaisense_vita/mpconfigboard.h +++ b/ports/nrf/boards/ikigaisense_vita/mpconfigboard.h @@ -5,8 +5,6 @@ #define MICROPY_HW_LED_STATUS (&pin_P0_27) -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 - #define CIRCUITPY_INTERNAL_NVM_SIZE (4096) #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) diff --git a/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.h index 629463e4e2..47220bb474 100644 --- a/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/itsybitsy_nrf52840_express/mpconfigboard.h @@ -24,8 +24,6 @@ #define SPI_FLASH_CS_PIN &pin_P0_23 #endif -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 - #define CIRCUITPY_INTERNAL_NVM_SIZE (4096) #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) diff --git a/ports/nrf/boards/warmbit_bluepixel/mpconfigboard.h b/ports/nrf/boards/warmbit_bluepixel/mpconfigboard.h index 224bdd5e90..484032f9c3 100644 --- a/ports/nrf/boards/warmbit_bluepixel/mpconfigboard.h +++ b/ports/nrf/boards/warmbit_bluepixel/mpconfigboard.h @@ -5,8 +5,6 @@ #define MICROPY_HW_LED_STATUS (&pin_P0_12) -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 - #define CIRCUITPY_INTERNAL_NVM_SIZE (4096) #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) diff --git a/ports/stm/boards/pyb_nano_v2/mpconfigboard.h b/ports/stm/boards/pyb_nano_v2/mpconfigboard.h index f85d27d4b1..b476a668a9 100644 --- a/ports/stm/boards/pyb_nano_v2/mpconfigboard.h +++ b/ports/stm/boards/pyb_nano_v2/mpconfigboard.h @@ -42,8 +42,6 @@ #define SPI_FLASH_SCK_PIN (&pin_PB13) #define SPI_FLASH_CS_PIN (&pin_PB12) -#define CIRCUITPY_AUTORELOAD_DELAY_MS (500) - #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x2000 - 0xC000) #define AUTORESET_DELAY_MS (500) diff --git a/ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.h b/ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.h index 400e7bb2c1..aff15eba28 100644 --- a/ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.h +++ b/ports/stm/boards/stm32f411ce_blackpill/mpconfigboard.h @@ -45,8 +45,6 @@ #define DEFAULT_I2C_BUS_SCL (&pin_PB06) #define DEFAULT_I2C_BUS_SDA (&pin_PB07) -#define CIRCUITPY_AUTORELOAD_DELAY_MS (500) - #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x2000 - 0xC000) #define AUTORESET_DELAY_MS (500) diff --git a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h index b86bdc1ee7..c49c936a9b 100644 --- a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h +++ b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h @@ -1,4 +1,4 @@ -/* +`/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) @@ -49,6 +49,4 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x2000 - 0xC000) -#define AUTORESET_DELAY_MS (500) - #define MICROPY_FATFS_EXFAT 0 diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index c69f0e4174..0d99277ba7 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -95,7 +95,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_s //| ... //| STATIC mp_obj_t supervisor_reload(void) { - reload_requested = true; supervisor_set_run_reason(RUN_REASON_SUPERVISOR_RELOAD); mp_raise_reload_exception(); return mp_const_none; diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index 7b44bb15dc..c2bf2a1863 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -174,12 +174,13 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input } else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type((mp_obj_t)nlr.ret_val)), &mp_type_DeepSleepRequest)) { ret = PYEXEC_DEEP_SLEEP; #endif + } else if ((mp_obj_t)nlr.ret_val == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { + ret = PYEXEC_RELOAD; } else { - if ((mp_obj_t)nlr.ret_val != MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { - mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); - } + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); ret = PYEXEC_EXCEPTION; } + } if (result != NULL) { result->return_code = ret; diff --git a/shared/runtime/pyexec.h b/shared/runtime/pyexec.h index 3d3c2d6c53..d31a7fe816 100644 --- a/shared/runtime/pyexec.h +++ b/shared/runtime/pyexec.h @@ -49,6 +49,7 @@ extern int pyexec_system_exit; #define PYEXEC_FORCED_EXIT (0x100) #define PYEXEC_EXCEPTION (0x200) #define PYEXEC_DEEP_SLEEP (0x400) +#define PYEXEC_RELOAD (0x800) int pyexec_raw_repl(void); int pyexec_friendly_repl(void); diff --git a/supervisor/shared/autoreload.c b/supervisor/shared/autoreload.c index 5c66c44298..1c85ddc5c4 100644 --- a/supervisor/shared/autoreload.c +++ b/supervisor/shared/autoreload.c @@ -33,67 +33,76 @@ supervisor_allocation *next_code_allocation; #include "shared-bindings/supervisor/Runtime.h" -static volatile uint32_t autoreload_delay_ms = 0; -static bool autoreload_enabled = false; -static size_t autoreload_suspended = 0; +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; + } + autoreload_countdown_ms = 0; + reload_requested = false; +} + inline void autoreload_tick() { - if (autoreload_delay_ms == 0) { + if (!autoreload_countdown) { return; } - if (autoreload_delay_ms == 1 && autoreload_enabled && - autoreload_suspended == 0 && !reload_requested) { - mp_raise_reload_exception(); - reload_requested = true; - supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD); - supervisor_disable_tick(); + 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(); } - autoreload_delay_ms--; } void autoreload_enable() { autoreload_enabled = true; reload_requested = false; + autoreload_countdown = false; } void autoreload_disable() { autoreload_enabled = false; + autoreload_countdown = false; } -void autoreload_suspend(size_t lock_mask) { - autoreload_suspended |= lock_mask; +void autoreload_suspend(uint32_t suspend_reason_mask) { + autoreload_suspended |= suspend_reason_mask; } -void autoreload_resume(size_t lock_mask) { - autoreload_suspended &= ~lock_mask; +void autoreload_resume(uint32_t suspend_reason_mask) { + autoreload_suspended &= ~suspend_reason_mask; } inline bool autoreload_is_enabled() { return autoreload_enabled; } -void autoreload_start() { - // Enable ticks if we haven't been tracking an autoreload delay. We check - // our current state so that we only turn ticks on once. Multiple starts - // can occur before we reload and then turn ticks off. - if (autoreload_delay_ms == 0) { +void autoreload_start_countdown() { + // Avoid multiple tick enables. + if (!autoreload_countdown) { supervisor_enable_tick(); + autoreload_countdown = true; } - autoreload_delay_ms = CIRCUITPY_AUTORELOAD_DELAY_MS; -} - -void autoreload_stop() { - autoreload_delay_ms = 0; - reload_requested = false; -} - -void autoreload_now() { - if (!autoreload_enabled || autoreload_suspended || reload_requested) { - return; - } - mp_raise_reload_exception(); - reload_requested = true; - supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD); + // Start or restart the countdown interval. + autoreload_countdown_ms = CIRCUITPY_AUTORELOAD_DELAY_MS; } diff --git a/supervisor/shared/autoreload.h b/supervisor/shared/autoreload.h index 7282b11a69..2532965780 100644 --- a/supervisor/shared/autoreload.h +++ b/supervisor/shared/autoreload.h @@ -41,8 +41,8 @@ enum { }; enum { - AUTORELOAD_LOCK_REPL = 0x1, - AUTORELOAD_LOCK_BLE = 0x2 + AUTORELOAD_SUSPEND_REPL = 0x1, + AUTORELOAD_SUSPEND_BLE = 0x2 }; typedef struct { @@ -56,16 +56,16 @@ extern volatile bool reload_requested; void autoreload_tick(void); -void autoreload_start(void); -void autoreload_stop(void); +void autoreload_start_countdown(void); +void autoreload_reset(void); void autoreload_enable(void); void autoreload_disable(void); bool autoreload_is_enabled(void); -// Temporarily turn it off. Used during the REPL. -void autoreload_suspend(size_t lock_mask); -void autoreload_resume(size_t lock_mask); +// 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); -void autoreload_now(void); #endif // MICROPY_INCLUDED_SUPERVISOR_AUTORELOAD_H diff --git a/supervisor/shared/bluetooth/file_transfer.c b/supervisor/shared/bluetooth/file_transfer.c index bf42326275..9cbddc61ae 100644 --- a/supervisor/shared/bluetooth/file_transfer.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -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(); + autoreload_start_countdown(); 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(); + autoreload_start_countdown(); 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(); + autoreload_start_countdown(); } 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(); + autoreload_start_countdown(); } 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(); + autoreload_start_countdown(); } return ANY_COMMAND; } @@ -692,7 +692,7 @@ void supervisor_bluetooth_file_transfer_background(void) { if (size == 0) { break; } - autoreload_suspend(AUTORELOAD_LOCK_BLE); + autoreload_suspend(AUTORELOAD_SUSPEND_BLE); // TODO: If size < 0 return an error. current_offset += size; #if CIRCUITPY_VERBOSE_BLE @@ -710,7 +710,7 @@ void supervisor_bluetooth_file_transfer_background(void) { response[0] = next_command; response[1] = STATUS_ERROR_PROTOCOL; common_hal_bleio_packet_buffer_write(&_transfer_packet_buffer, response, 2, NULL, 0); - autoreload_resume(AUTORELOAD_LOCK_BLE); + autoreload_resume(AUTORELOAD_SUSPEND_BLE); break; } switch (current_state) { @@ -744,7 +744,7 @@ void supervisor_bluetooth_file_transfer_background(void) { current_offset = 0; } if (next_command == ANY_COMMAND) { - autoreload_resume(AUTORELOAD_LOCK_BLE); + autoreload_resume(AUTORELOAD_SUSPEND_BLE); } } running = false; @@ -754,5 +754,5 @@ void supervisor_bluetooth_file_transfer_disconnected(void) { next_command = ANY_COMMAND; current_offset = 0; f_close(&active_file); - autoreload_resume(AUTORELOAD_LOCK_BLE); + autoreload_resume(AUTORELOAD_SUSPEND_BLE); } diff --git a/supervisor/shared/flash.c b/supervisor/shared/flash.c index 333c6467d4..dfd7cf2050 100644 --- a/supervisor/shared/flash.c +++ b/supervisor/shared/flash.c @@ -113,7 +113,7 @@ static mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t n return supervisor_flash_read_blocks(dest, block_num - PART1_START_BLOCK, num_blocks); } -volatile bool filesystem_dirty = false; +static volatile bool filesystem_dirty = false; static mp_uint_t flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { if (block_num == 0) { diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index 94b9d4d15e..34b1897435 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -66,7 +66,9 @@ static volatile uint64_t PLACE_IN_DTCM_BSS(background_ticks); static background_callback_t tick_callback; -volatile uint64_t last_finished_tick = 0; +static volatile uint64_t last_finished_tick = 0; + +static volatile size_t tick_enable_count = 0; static void supervisor_background_tasks(void *unused) { port_start_background_task(); @@ -160,8 +162,7 @@ void mp_hal_delay_ms(mp_uint_t delay_ms) { } } -volatile size_t tick_enable_count = 0; -extern void supervisor_enable_tick(void) { +void supervisor_enable_tick(void) { common_hal_mcu_disable_interrupts(); if (tick_enable_count == 0) { port_enable_tick(); @@ -170,7 +171,7 @@ extern void supervisor_enable_tick(void) { common_hal_mcu_enable_interrupts(); } -extern void supervisor_disable_tick(void) { +void supervisor_disable_tick(void) { common_hal_mcu_disable_interrupts(); if (tick_enable_count > 0) { tick_enable_count--; diff --git a/supervisor/shared/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index fe88f8c831..e5bed8442b 100644 --- a/supervisor/shared/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -170,7 +170,6 @@ bool tud_msc_is_writable_cb(uint8_t lun) { // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) { - (void)lun; (void)offset; const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE; @@ -216,7 +215,7 @@ void tud_msc_write10_complete_cb(uint8_t lun) { (void)lun; // This write is complete, start the autoreload clock. - autoreload_start(); + autoreload_start_countdown(); } // Invoked when received SCSI_CMD_INQUIRY From 6465d81918eda03f46ef70c62aeb3499c0e7254c Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 9 Mar 2022 13:33:54 -0500 Subject: [PATCH 03/15] Update ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h whoopsies Co-authored-by: Scott Shawcroft --- .../stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h index c49c936a9b..874652cdc5 100644 --- a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h +++ b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.h @@ -1,4 +1,4 @@ -`/* +/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) From f59f8acf78e817d2ed16fb6d20930ff310674d27 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 4 Mar 2022 14:07:38 -0500 Subject: [PATCH 04/15] implement: from __future__ import annotations --- py/circuitpy_defns.mk | 5 +++ py/circuitpy_mpconfig.mk | 3 ++ shared-bindings/__future__/__init__.c | 53 +++++++++++++++++++++++++++ shared-bindings/__future__/__init__.h | 30 +++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 shared-bindings/__future__/__init__.c create mode 100644 shared-bindings/__future__/__init__.h diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 15828f6616..da7121eb66 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -174,6 +174,10 @@ ifeq ($(CIRCUITPY_FREQUENCYIO),1) SRC_PATTERNS += frequencyio/% endif +ifeq ($(CIRCUITPY_FUTURE),1) +SRC_PATTERNS += __future__/% +endif + ifeq ($(CIRCUITPY_GAMEPADSHIFT),1) SRC_PATTERNS += gamepadshift/% endif @@ -451,6 +455,7 @@ $(filter $(SRC_PATTERNS), \ _bleio/Attribute.c \ _bleio/ScanEntry.c \ _eve/__init__.c \ + __future__/__init__.c \ camera/ImageFormat.c \ canio/Match.c \ countio/Edge.c \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 14852580e5..945e6051cc 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -222,6 +222,9 @@ CFLAGS += -DCIRCUITPY__EVE=$(CIRCUITPY__EVE) CIRCUITPY_FREQUENCYIO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_FREQUENCYIO=$(CIRCUITPY_FREQUENCYIO) +CIRCUITPY_FUTURE ?= 1 +CFLAGS += -DCIRCUITPY_FUTURE=$(CIRCUITPY_FUTURE) + CIRCUITPY_GAMEPADSHIFT ?= 0 CFLAGS += -DCIRCUITPY_GAMEPADSHIFT=$(CIRCUITPY_GAMEPADSHIFT) diff --git a/shared-bindings/__future__/__init__.c b/shared-bindings/__future__/__init__.c new file mode 100644 index 0000000000..76072e4b4a --- /dev/null +++ b/shared-bindings/__future__/__init__.c @@ -0,0 +1,53 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * 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 "extmod/vfs.h" +#include "py/mpstate.h" +#include "py/obj.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/__future__/__init__.h" + +//| """Language features module +//| +//| The `__future__` module is used by other Python implementations to +//| enable forward compatibility for features enabled by default in an upcoming version. +//| """ + +STATIC const mp_rom_map_elem_t future_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR___future__) }, + + { MP_ROM_QSTR(MP_QSTR_annotations), mp_const_true }, +}; + +STATIC MP_DEFINE_CONST_DICT(future_module_globals, future_module_globals_table); + +const mp_obj_module_t future_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&future_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR___future__, future_module, CIRCUITPY_FUTURE); diff --git a/shared-bindings/__future__/__init__.h b/shared-bindings/__future__/__init__.h new file mode 100644 index 0000000000..c1dd0e192e --- /dev/null +++ b/shared-bindings/__future__/__init__.h @@ -0,0 +1,30 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * 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 MICROPY_INCLUDED_SHARED_BINDINGS___FUTURE_____INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS___FUTURE_____INIT___H + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS___FUTURE_____INIT___H From c70425ab6b7c21996809ed9a6cc23593c42d800d Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 7 Mar 2022 17:43:15 -0500 Subject: [PATCH 05/15] add annotations to __future__; don't generate __future__ stubs --- shared-bindings/__future__/__init__.c | 7 +++++++ tools/extract_pyi.py | 9 +++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/shared-bindings/__future__/__init__.c b/shared-bindings/__future__/__init__.c index 76072e4b4a..ad1bb3b283 100644 --- a/shared-bindings/__future__/__init__.c +++ b/shared-bindings/__future__/__init__.c @@ -36,6 +36,13 @@ //| The `__future__` module is used by other Python implementations to //| enable forward compatibility for features enabled by default in an upcoming version. //| """ +//| +//| annotations: Any +//| """In CPython, ``from __future import annotations`` +//| indicates that evaluation of annotations is postponed, as described in PEP 563. +//| CircuitPython (and MicroPython) ignore annotations entirely, whether or not this feature is imported. +//| This is a limitation of CircuitPython and MicroPython for efficiency reasons. +//| """ STATIC const mp_rom_map_elem_t future_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR___future__) }, diff --git a/tools/extract_pyi.py b/tools/extract_pyi.py index d35e09a2e0..da46394330 100644 --- a/tools/extract_pyi.py +++ b/tools/extract_pyi.py @@ -16,7 +16,9 @@ import isort import black -IMPORTS_IGNORE = frozenset( +PATHS_IGNORE = frozenset({"shared-bindings/__future__"}) + +TYPE_MODULE_IMPORTS_IGNORE = frozenset( { "int", "float", @@ -125,7 +127,7 @@ def extract_imports(tree): return for node in ast.walk(anno_tree): if isinstance(node, ast.Name): - if node.id in IMPORTS_IGNORE: + if node.id in TYPE_MODULE_IMPORTS_IGNORE: continue elif node.id in IMPORTS_TYPING: typing.add(node.id) @@ -174,6 +176,9 @@ def convert_folder(top_level, stub_directory): for filename in filenames: full_path = os.path.join(top_level, filename) + if full_path in PATHS_IGNORE: + continue + file_lines = [] if os.path.isdir(full_path): (mok, mtotal) = convert_folder(full_path, os.path.join(stub_directory, filename)) From 6ddab0f3c88ed962dfca6ca0e18399d150607978 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 7 Mar 2022 21:37:28 -0500 Subject: [PATCH 06/15] shrink matrixportal_m4 --- .../boards/matrixportal_m4/mpconfigboard.mk | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk index 81e1cd00cd..94beaaadfd 100644 --- a/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk @@ -10,13 +10,15 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ +CIRCUITPY_BLEIO = 0 +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_ONEWIREIO = 0 +CIRCUITPY_PARALLELDISPLAY = 0 +CIRCUITPY_SDCARDIO = 0 +CIRCUITPY_SHARPDISPLAY = 0 + # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_PortalBase FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ESP32SPI FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel - -CIRCUITPY_SHARPDISPLAY=0 -CIRCUITPY_SDCARDIO=0 -CIRCUITPY_BLEIO_HCI=0 -CIRCUITPY_BLEIO=0 From a165bdf583a3d20874708a3710210f099ef54d4e Mon Sep 17 00:00:00 2001 From: root Date: Wed, 2 Mar 2022 12:07:54 -0600 Subject: [PATCH 07/15] Make countio object long-lived --- shared-bindings/countio/Counter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/countio/Counter.c b/shared-bindings/countio/Counter.c index 8582f4497e..e495ecd1d5 100644 --- a/shared-bindings/countio/Counter.c +++ b/shared-bindings/countio/Counter.c @@ -53,7 +53,7 @@ STATIC mp_obj_t countio_counter_make_new(const mp_obj_type_t *type, size_t n_arg const countio_edge_t edge = validate_edge(args[ARG_edge].u_obj, MP_QSTR_edge); const digitalio_pull_t pull = validate_pull(args[ARG_pull].u_obj, MP_QSTR_pull); - countio_counter_obj_t *self = m_new_obj(countio_counter_obj_t); + countio_counter_obj_t *self = m_new_ll_obj(countio_counter_obj_t); self->base.type = &countio_counter_type; common_hal_countio_counter_construct(self, pin, edge, pull); From d365d1b2a06749c6728db9e904aadf26ac31b11f Mon Sep 17 00:00:00 2001 From: DavePutz Date: Wed, 2 Mar 2022 12:21:13 -0600 Subject: [PATCH 08/15] Update Counter.c Add a comment as to why the countio object needs to be long-lived. --- shared-bindings/countio/Counter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-bindings/countio/Counter.c b/shared-bindings/countio/Counter.c index e495ecd1d5..077cfd8c97 100644 --- a/shared-bindings/countio/Counter.c +++ b/shared-bindings/countio/Counter.c @@ -52,7 +52,7 @@ STATIC mp_obj_t countio_counter_make_new(const mp_obj_type_t *type, size_t n_arg const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); const countio_edge_t edge = validate_edge(args[ARG_edge].u_obj, MP_QSTR_edge); const digitalio_pull_t pull = validate_pull(args[ARG_pull].u_obj, MP_QSTR_pull); - + // Make long-lived because some implementations use a pointer to the object as interrupt-handler data. countio_counter_obj_t *self = m_new_ll_obj(countio_counter_obj_t); self->base.type = &countio_counter_type; From 2f83264f09476a90e4d8dc879a6913c504c4eb2a Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 27 Feb 2022 16:15:57 -0600 Subject: [PATCH 09/15] update nina-fw submodule --- ports/espressif/certificates/nina-fw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/espressif/certificates/nina-fw b/ports/espressif/certificates/nina-fw index f2a0e601b2..d73fe315cc 160000 --- a/ports/espressif/certificates/nina-fw +++ b/ports/espressif/certificates/nina-fw @@ -1 +1 @@ -Subproject commit f2a0e601b23212dda4fe305eab30af49a7c7fb41 +Subproject commit d73fe315cc7f9148a0918490d3b75430c8444bf7 From c5947fd6de3420eab811227e8587bcdf0dec06f2 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 10 Mar 2022 12:46:08 -0500 Subject: [PATCH 10/15] squeeze arduino_zero and sensebox_mcu --- ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk | 2 ++ ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk | 1 + 2 files changed, 3 insertions(+) diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk index 5ee22c59ad..f1c3631dcb 100644 --- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk +++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk @@ -9,3 +9,5 @@ CHIP_FAMILY = samd21 INTERNAL_FLASH_FILESYSTEM = 1 LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 + +CIRCUITPY_ONEWIREIO = 0 diff --git a/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk b/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk index 568503afe9..397a89cb60 100644 --- a/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk +++ b/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk @@ -11,4 +11,5 @@ LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 # There are many pin definitions on this board; it doesn't quite fit on very large translations. +CIRCUITPY_ONEWIREIO = 0 CIRCUITPY_RAINBOWIO = 0 From a7260a8b61b61435eaafa90bb869e999cbca628a Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 10 Mar 2022 15:56:51 -0500 Subject: [PATCH 11/15] squeeze arduino_zero further --- ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk index f1c3631dcb..5d0734f69d 100644 --- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk +++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk @@ -11,3 +11,4 @@ LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 CIRCUITPY_ONEWIREIO = 0 +CIRCUITPY_RAINBOWIO = 0 From 19e7647f3d2a168da9e311c11ad5ee3d3aabac80 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 10 Mar 2022 18:20:04 -0500 Subject: [PATCH 12/15] turn off MIDI on sensebox_mcu for sapce --- ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk b/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk index 397a89cb60..ea14f63ad9 100644 --- a/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk +++ b/ports/atmel-samd/boards/sensebox_mcu/mpconfigboard.mk @@ -13,3 +13,4 @@ CIRCUITPY_FULL_BUILD = 0 # There are many pin definitions on this board; it doesn't quite fit on very large translations. CIRCUITPY_ONEWIREIO = 0 CIRCUITPY_RAINBOWIO = 0 +CIRCUITPY_USB_MIDI = 0 From e4cd9690f12e9f81eb2c6350dd5ed6609f924e17 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 11 Mar 2022 13:29:20 -0500 Subject: [PATCH 13/15] rework auto-reload delay logic --- main.c | 24 +++++++-- ports/atmel-samd/mphalport.c | 1 - ports/raspberrypi/mphalport.c | 1 - py/circuitpy_mpconfig.h | 2 +- py/py.mk | 1 - py/reload.c | 32 ----------- py/reload.h | 26 --------- shared-bindings/alarm/__init__.c | 2 - shared-bindings/supervisor/Runtime.c | 12 +++-- shared-bindings/supervisor/Runtime.h | 1 + shared-bindings/supervisor/__init__.c | 6 +-- shared-module/displayio/__init__.c | 3 +- supervisor/shared/bluetooth/file_transfer.c | 12 ++--- supervisor/shared/{autoreload.c => reload.c} | 56 +++++++------------- supervisor/shared/{autoreload.h => reload.h} | 12 ++--- supervisor/shared/tick.c | 5 -- supervisor/shared/tick.h | 5 +- supervisor/shared/usb/usb_msc_flash.c | 6 +-- supervisor/supervisor.mk | 2 +- 19 files changed, 71 insertions(+), 138 deletions(-) delete mode 100644 py/reload.c delete mode 100644 py/reload.h rename supervisor/shared/{autoreload.c => reload.c} (63%) rename supervisor/shared/{autoreload.h => reload.h} (89%) diff --git a/main.c b/main.c index d1fbc257a9..9f31153877 100644 --- a/main.c +++ b/main.c @@ -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 diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c index e196312ca3..a039b5d258 100644 --- a/ports/atmel-samd/mphalport.c +++ b/ports/atmel-samd/mphalport.c @@ -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" diff --git a/ports/raspberrypi/mphalport.c b/ports/raspberrypi/mphalport.c index 51d82a0514..b4ecbca49d 100644 --- a/ports/raspberrypi/mphalport.c +++ b/ports/raspberrypi/mphalport.c @@ -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" diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 070403877f..aa60be693f 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -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 diff --git a/py/py.mk b/py/py.mk index db92ef3c02..f13a9d3786 100644 --- a/py/py.mk +++ b/py/py.mk @@ -159,7 +159,6 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ objzip.o \ opmethods.o \ proto.o \ - reload.o \ sequence.o \ stream.o \ binary.o \ diff --git a/py/reload.c b/py/reload.c deleted file mode 100644 index 996826b930..0000000000 --- a/py/reload.c +++ /dev/null @@ -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 - -} diff --git a/py/reload.h b/py/reload.h deleted file mode 100644 index 8e68ea3253..0000000000 --- a/py/reload.h +++ /dev/null @@ -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 diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 340a4ea679..9de8c294e9 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -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 diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index 1ed11a2ec5..08d68ec93f 100644 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -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) }, diff --git a/shared-bindings/supervisor/Runtime.h b/shared-bindings/supervisor/Runtime.h index 3a94a8fd5d..debc5ec79c 100644 --- a/shared-bindings/supervisor/Runtime.h +++ b/shared-bindings/supervisor/Runtime.h @@ -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); diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index 0d99277ba7..0b86b7b2a6 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -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); diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index d026d9f766..04171198cf 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -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" diff --git a/supervisor/shared/bluetooth/file_transfer.c b/supervisor/shared/bluetooth/file_transfer.c index 9cbddc61ae..6715ee961b 100644 --- a/supervisor/shared/bluetooth/file_transfer.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -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; } diff --git a/supervisor/shared/autoreload.c b/supervisor/shared/reload.c similarity index 63% rename from supervisor/shared/autoreload.c rename to supervisor/shared/reload.c index 1c85ddc5c4..b774074df6 100644 --- a/supervisor/shared/autoreload.c +++ b/supervisor/shared/reload.c @@ -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; } diff --git a/supervisor/shared/autoreload.h b/supervisor/shared/reload.h similarity index 89% rename from supervisor/shared/autoreload.h rename to supervisor/shared/reload.h index 2532965780..10b4bea00c 100644 --- a/supervisor/shared/autoreload.h +++ b/supervisor/shared/reload.h @@ -27,9 +27,9 @@ #ifndef MICROPY_INCLUDED_SUPERVISOR_AUTORELOAD_H #define MICROPY_INCLUDED_SUPERVISOR_AUTORELOAD_H -#include - #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 diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index 34b1897435..104083fb20 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -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 diff --git a/supervisor/shared/tick.h b/supervisor/shared/tick.h index 3a01bd6222..d805aeb099 100644 --- a/supervisor/shared/tick.h +++ b/supervisor/shared/tick.h @@ -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 diff --git a/supervisor/shared/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index e5bed8442b..fbc9c2a1b4 100644 --- a/supervisor/shared/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -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 diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index eed9f4dc47..8aaec79d92 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -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 \ From 32ac396a41223c99e2c3c71429a1d6c920ad138a Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 14 Mar 2022 16:49:30 -0700 Subject: [PATCH 14/15] Further refine autoreload This unifies the delay into the post-run delay that also waits for user input and fake sleep. This ensures we always delay. Previous code would only delay if the code.py was running when autoreload was triggered. Now it will always delay. We also now suspend autoreload when a USB write starts and then resume on completion. This should prevent reloading in between sectors of a single write. --- locale/circuitpython.pot | 13 +++---- main.c | 39 ++++++++------------- ports/stm/supervisor/port.c | 2 -- shared-module/displayio/__init__.c | 2 +- supervisor/shared/bluetooth/file_transfer.c | 15 +++----- supervisor/shared/reload.c | 39 +++++++++++++++++---- supervisor/shared/reload.h | 25 +++++++++---- supervisor/shared/usb/usb_msc_flash.c | 4 ++- 8 files changed, 82 insertions(+), 57 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 336dd49daf..886edad28d 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -25,7 +25,7 @@ msgstr "" #: main.c msgid "" "\n" -"Code stopped by auto-reload.\n" +"Code stopped by auto-reload. Reloading soon.\n" msgstr "" #: supervisor/shared/safe_mode.c @@ -584,10 +584,6 @@ msgstr "" msgid "Brightness must be 0-1.0" msgstr "" -#: shared-bindings/supervisor/__init__.c -msgid "Brightness must be between 0 and 255" -msgstr "" - #: shared-bindings/displayio/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" @@ -688,6 +684,7 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nrf/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" msgstr "" @@ -1605,6 +1602,7 @@ msgstr "" msgid "Nimble out of memory" msgstr "" +#: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nrf/common-hal/_bleio/Characteristic.c msgid "No CCCD for this Characteristic" msgstr "" @@ -3642,7 +3640,7 @@ msgstr "" msgid "matrix is not positive definite" msgstr "" -#: shared-bindings/wifi/Radio.c +#: ports/espressif/common-hal/wifi/Radio.c msgid "max_connections must be between 0 and 10" msgstr "" @@ -4061,6 +4059,7 @@ msgstr "" #: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h #: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h #: ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h +#: ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.h #: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h #: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h #: ports/espressif/boards/artisense_rd00/mpconfigboard.h @@ -4068,6 +4067,7 @@ msgstr "" #: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h #: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h #: ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/mpconfigboard.h +#: ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/mpconfigboard.h #: ports/espressif/boards/espressif_esp32s3_box/mpconfigboard.h #: ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/mpconfigboard.h #: ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2/mpconfigboard.h @@ -4083,6 +4083,7 @@ msgstr "" #: ports/espressif/boards/gravitech_cucumber_ms/mpconfigboard.h #: ports/espressif/boards/gravitech_cucumber_r/mpconfigboard.h #: ports/espressif/boards/gravitech_cucumber_rs/mpconfigboard.h +#: ports/espressif/boards/hiibot_iots2/mpconfigboard.h #: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h #: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h #: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h diff --git a/main.c b/main.c index 9f31153877..070fb211d8 100644 --- a/main.c +++ b/main.c @@ -124,7 +124,6 @@ static void reset_devices(void) { } STATIC void start_mp(supervisor_allocation *heap, bool first_run) { - autoreload_reset(); supervisor_workflow_reset(); // 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 // Collects stickiness bits that apply in the current situation. uint8_t next_code_stickiness_situation = SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET; + // Do the filesystem flush check before reload in case another write comes + // in while we're doing the flush. if (safe_mode == NO_SAFE_MODE) { + stack_resize(); + filesystem_flush(); + } + if (safe_mode == NO_SAFE_MODE && !autoreload_pending()) { static const char *const supported_filenames[] = STRING_LIST( "code.txt", "code.py", "main.py", "main.txt"); #if CIRCUITPY_FULL_BUILD @@ -345,8 +350,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re "main.txt.py", "main.py.txt", "main.txt.txt","main.py.py"); #endif - stack_resize(); - filesystem_flush(); supervisor_allocation *heap = allocate_remaining_memory(); // 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 // 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) && 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; + serial_write_compressed(translate("\nCode stopped by auto-reload. Reloading soon.\n")); } else { serial_write_compressed(translate("\nCode done running.\n")); } @@ -425,8 +413,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re if (result.return_code & PYEXEC_RELOAD) { next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_RELOAD; - skip_repl = true; - skip_wait = true; } else if (result.return_code == 0) { next_code_stickiness_situation |= SUPERVISOR_NEXT_CODE_OPT_STICKY_ON_SUCCESS; if (next_code_options & SUPERVISOR_NEXT_CODE_OPT_RELOAD_ON_SUCCESS) { @@ -484,6 +470,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re size_t total_time = blink_time + LED_SLEEP_TIME_MS; #endif + // This loop is waits after code completes. It waits for fake sleeps to + // finish, user input or autoreloads. #if CIRCUITPY_ALARM bool fake_sleeping = false; #endif @@ -491,15 +479,18 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re RUN_BACKGROUND_TASKS; // If a reload was requested by the supervisor or autoreload, return. - if (reload_requested) { + if (autoreload_ready()) { 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 // "no" for now, mainly because it's a bit less code. At this point, we have both a // success or error and a reload, so let's have both of the respective options take // effect (in OR combination). - reload_requested = false; skip_repl = true; + // We're kicking off the autoreload process so reset now. If any + // other reloads trigger after this, then we'll want another wait + // period. + autoreload_reset(); break; } @@ -526,7 +517,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re #endif // If messages haven't been printed yet, print them - if (!printed_press_any_key && serial_connected()) { + if (!printed_press_any_key && serial_connected() && !autoreload_pending()) { if (!serial_connected_at_start) { print_code_py_status_message(safe_mode); } diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index a158ade6eb..e4cce571ea 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -346,8 +346,6 @@ void port_enable_tick(void) { stm32_peripherals_rtc_assign_wkup_callback(supervisor_tick); stm32_peripherals_rtc_enable_wakeup_timer(); } -// TODO: what is this? can I get rid of it? -extern volatile uint32_t autoreload_delay_ms; // Disable 1/1024 second tick. void port_disable_tick(void) { diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 04171198cf..87962dfc60 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -82,7 +82,7 @@ void displayio_background(void) { if (mp_hal_is_interrupted()) { return; } - if (reload_requested) { + if (autoreload_ready()) { // Reload is about to happen, so don't redisplay. return; } diff --git a/supervisor/shared/bluetooth/file_transfer.c b/supervisor/shared/bluetooth/file_transfer.c index 6715ee961b..6c206f35c0 100644 --- a/supervisor/shared/bluetooth/file_transfer.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -325,8 +325,7 @@ STATIC uint8_t _process_write(const uint8_t *raw_buf, size_t command_len) { if (chunk_size == 0) { // 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(); + autoreload_trigger(); return ANY_COMMAND; } @@ -383,8 +382,7 @@ STATIC uint8_t _process_write_data(const uint8_t *raw_buf, size_t command_len) { #endif // 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(); + autoreload_trigger(); return ANY_COMMAND; } return WRITE_DATA; @@ -465,8 +463,7 @@ STATIC uint8_t _process_delete(const uint8_t *raw_buf, size_t command_len) { if (result == FR_OK) { // 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(); + autoreload_trigger(); } return ANY_COMMAND; } @@ -520,8 +517,7 @@ STATIC uint8_t _process_mkdir(const uint8_t *raw_buf, size_t command_len) { if (result == FR_OK) { // 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(); + autoreload_trigger(); } return ANY_COMMAND; } @@ -668,8 +664,7 @@ STATIC uint8_t _process_move(const uint8_t *raw_buf, size_t command_len) { if (result == FR_OK) { // 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(); + autoreload_trigger(); } return ANY_COMMAND; } diff --git a/supervisor/shared/reload.c b/supervisor/shared/reload.c index b774074df6..f30d4249e2 100644 --- a/supervisor/shared/reload.c +++ b/supervisor/shared/reload.c @@ -40,11 +40,9 @@ 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 something has requested a reload/restart. -volatile bool reload_requested = false; +volatile uint32_t last_autoreload_trigger = 0; 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. @@ -57,12 +55,12 @@ void reload_initiate(supervisor_run_reason_t run_reason) { } void autoreload_reset() { - reload_requested = false; + last_autoreload_trigger = 0; } void autoreload_enable() { autoreload_enabled = true; - reload_requested = false; + last_autoreload_trigger = 0; } void autoreload_disable() { @@ -81,8 +79,35 @@ inline bool autoreload_is_enabled() { return autoreload_enabled; } -void autoreload_start() { - if (autoreload_enabled && autoreload_suspended == 0) { +void autoreload_trigger() { + if (autoreload_enabled) { + last_autoreload_trigger = supervisor_ticks_ms32(); + // Guard against the rare time that ticks is 0; + if (last_autoreload_trigger == 0) { + last_autoreload_trigger += 1; + } + // Initiate a reload of the VM immediately. Later code will pause to + // wait for the autoreload to become ready. Doing the VM exit + // immediately is clearer for the user. reload_initiate(RUN_REASON_AUTO_RELOAD); } } + +bool autoreload_ready() { + if (last_autoreload_trigger == 0 || autoreload_suspended != 0) { + return false; + } + // Wait for autoreload interval before reloading + uint32_t now = supervisor_ticks_ms32(); + uint32_t diff; + if (now >= last_autoreload_trigger) { + diff = now - last_autoreload_trigger; + } else { + diff = now + (0xffffffff - last_autoreload_trigger); + } + return diff > CIRCUITPY_AUTORELOAD_DELAY_MS; +} + +bool autoreload_pending(void) { + return last_autoreload_trigger != 0; +} diff --git a/supervisor/shared/reload.h b/supervisor/shared/reload.h index 10b4bea00c..cb3385e7ca 100644 --- a/supervisor/shared/reload.h +++ b/supervisor/shared/reload.h @@ -42,7 +42,8 @@ enum { enum { AUTORELOAD_SUSPEND_REPL = 0x1, - AUTORELOAD_SUSPEND_BLE = 0x2 + AUTORELOAD_SUSPEND_BLE = 0x2, + AUTORELOAD_SUSPEND_USB = 0x4 }; typedef struct { @@ -52,17 +53,29 @@ typedef struct { extern supervisor_allocation *next_code_allocation; -extern volatile bool reload_requested; - +// Helper for exiting the VM and reloading immediately. void reload_initiate(supervisor_run_reason_t run_reason); -void autoreload_start(void); -void autoreload_reset(void); +// Enabled state is user controllable and very sticky. We don't reset it. void autoreload_enable(void); void autoreload_disable(void); bool autoreload_is_enabled(void); -// Temporarily turn autoreload off, for the given reason(s). +// Start the autoreload process. +void autoreload_trigger(void); +// True when the autoreload should occur. (A trigger happened and the delay has +// passed.) +bool autoreload_ready(void); +// Reset the autoreload timer in preparation for another trigger. Call when the +// last trigger starts being executed. +void autoreload_reset(void); +// True when a trigger has occurred but we're still delaying in case another +// trigger occurs. +bool autoreload_pending(void); + +// Temporarily turn autoreload off, for the given reason(s). Autoreload triggers +// will still be tracked so resuming with autoreload ready with cause an +// immediate reload. // 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). diff --git a/supervisor/shared/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index fbc9c2a1b4..67d57bceb5 100644 --- a/supervisor/shared/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -185,6 +185,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buff int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) { (void)lun; (void)offset; + autoreload_suspend(AUTORELOAD_SUSPEND_USB); const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE; @@ -215,7 +216,8 @@ void tud_msc_write10_complete_cb(uint8_t lun) { (void)lun; // This write is complete; initiate an autoreload. - autoreload_start(); + autoreload_trigger(); + autoreload_resume(AUTORELOAD_SUSPEND_USB); } // Invoked when received SCSI_CMD_INQUIRY From f602296e590aad749d8e03a9d2b83ac7ca43a917 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 14 Mar 2022 17:02:22 -0700 Subject: [PATCH 15/15] Re-enable BLE on MatrixPortal. Remove PortalBase We have a guide that uses it. It was removed in #6043 without realizing that. Fixes #6152 --- ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk | 3 --- 1 file changed, 3 deletions(-) diff --git a/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk index 94beaaadfd..63e8f06e2b 100644 --- a/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/matrixportal_m4/mpconfigboard.mk @@ -10,15 +10,12 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ -CIRCUITPY_BLEIO = 0 -CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_ONEWIREIO = 0 CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_SDCARDIO = 0 CIRCUITPY_SHARPDISPLAY = 0 # Include these Python libraries in firmware. -FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_PortalBase FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ESP32SPI FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel