diff --git a/ports/esp32s2/common-hal/microcontroller/__init__.c b/ports/esp32s2/common-hal/microcontroller/__init__.c index 85eb0b522b..d7b9041947 100644 --- a/ports/esp32s2/common-hal/microcontroller/__init__.c +++ b/ports/esp32s2/common-hal/microcontroller/__init__.c @@ -42,6 +42,13 @@ #include "freertos/FreeRTOS.h" +#include "soc/rtc_cntl_reg.h" +#include "esp_private/system_internal.h" + +#include "esp32s2/rom/rtc.h" +#include "esp32s2/rom/usb/usb_persist.h" +#include "esp32s2/rom/usb/chip_usb_dw_wrapper.h" + void common_hal_mcu_delay_us(uint32_t delay) { mp_hal_delay_us(delay); } @@ -68,12 +75,32 @@ void common_hal_mcu_enable_interrupts(void) { } void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { - if (runmode == RUNMODE_SAFE_MODE) { - safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE); + switch (runmode) { + case RUNMODE_UF2: + // 0x11F2 is APP_REQUEST_UF2_RESET_HINT & is defined by TinyUF2 + esp_reset_reason_set_hint(0x11F2); + break; + case RUNMODE_NORMAL: + // revert back to normal boot + REG_WRITE(RTC_RESET_CAUSE_REG, 0); // reset uf2 + REG_WRITE(RTC_CNTL_STORE0_REG, 0); // reset safe mode + REG_WRITE(RTC_CNTL_OPTION1_REG, 0); // reset bootloader + break; + case RUNMODE_SAFE_MODE: + // enter safe mode on next boot + safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE); + break; + case RUNMODE_BOOTLOADER: + // DFU download + chip_usb_set_persist_flags(USBDC_BOOT_DFU); + REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); + break; + default: + break; } } -void common_hal_mcu_reset(void) { +void NORETURN common_hal_mcu_reset(void) { filesystem_flush(); // TODO: implement as part of flash improvements esp_restart(); } diff --git a/ports/raspberrypi/common-hal/microcontroller/__init__.c b/ports/raspberrypi/common-hal/microcontroller/__init__.c index 6b5cb9b0d8..ed68835e71 100644 --- a/ports/raspberrypi/common-hal/microcontroller/__init__.c +++ b/ports/raspberrypi/common-hal/microcontroller/__init__.c @@ -73,12 +73,16 @@ void common_hal_mcu_enable_interrupts(void) { static bool next_reset_to_bootloader = false; void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { - if (runmode == RUNMODE_BOOTLOADER) { - next_reset_to_bootloader = true; - } else { - } - if (runmode == RUNMODE_SAFE_MODE) { - safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE); + switch (runmode) { + case RUNMODE_UF2: + case RUNMODE_BOOTLOADER: + next_reset_to_bootloader = true; + break; + case RUNMODE_SAFE_MODE: + safe_mode_on_next_reset(PROGRAMMATIC_SAFE_MODE); + break; + default: + break; } } diff --git a/shared-bindings/microcontroller/RunMode.c b/shared-bindings/microcontroller/RunMode.c index 789bb77c3b..e3743090ec 100644 --- a/shared-bindings/microcontroller/RunMode.c +++ b/shared-bindings/microcontroller/RunMode.c @@ -39,18 +39,27 @@ //| :type microcontroller.RunMode:""" //| //| SAFE_MODE: RunMode -//| """Run CircuitPython in safe mode. User code will not be run and the +//| """Run CircuitPython in safe mode. User code will not run and the //| file system will be writeable over USB. //| //| :type microcontroller.RunMode:""" //| +//| UF2: RunMode +//| """Run the uf2 bootloader. +//| +//| :type microcontroller.RunMode:""" +//| //| BOOTLOADER: RunMode -//| """Run the bootloader. +//| """Run the default bootloader. //| //| :type microcontroller.RunMode:""" //| const mp_obj_type_t mcu_runmode_type; +const mcu_runmode_obj_t mcu_runmode_uf2_obj = { + { &mcu_runmode_type }, +}; + const mcu_runmode_obj_t mcu_runmode_normal_obj = { { &mcu_runmode_type }, }; @@ -64,6 +73,7 @@ const mcu_runmode_obj_t mcu_runmode_bootloader_obj = { }; STATIC const mp_rom_map_elem_t mcu_runmode_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR_UF2), MP_ROM_PTR(&mcu_runmode_uf2_obj)}, {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_PTR(&mcu_runmode_normal_obj)}, {MP_ROM_QSTR(MP_QSTR_SAFE_MODE), MP_ROM_PTR(&mcu_runmode_safe_mode_obj)}, {MP_ROM_QSTR(MP_QSTR_BOOTLOADER), MP_ROM_PTR(&mcu_runmode_bootloader_obj)}, @@ -72,10 +82,11 @@ STATIC MP_DEFINE_CONST_DICT(mcu_runmode_locals_dict, mcu_runmode_locals_dict_tab STATIC void mcu_runmode_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { qstr runmode = MP_QSTR_NORMAL; - if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&mcu_runmode_safe_mode_obj)) { + if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&mcu_runmode_uf2_obj)) { + runmode = MP_QSTR_UF2; + } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&mcu_runmode_safe_mode_obj)) { runmode = MP_QSTR_SAFE_MODE; - } else if (MP_OBJ_TO_PTR(self_in) == - MP_ROM_PTR(&mcu_runmode_bootloader_obj)) { + } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&mcu_runmode_bootloader_obj)) { runmode = MP_QSTR_BOOTLOADER; } mp_printf(print, "%q.%q.%q", MP_QSTR_microcontroller, MP_QSTR_RunMode, diff --git a/shared-bindings/microcontroller/RunMode.h b/shared-bindings/microcontroller/RunMode.h index ce90ab93a7..172256d7b0 100644 --- a/shared-bindings/microcontroller/RunMode.h +++ b/shared-bindings/microcontroller/RunMode.h @@ -30,6 +30,7 @@ #include "py/obj.h" typedef enum { + RUNMODE_UF2, RUNMODE_NORMAL, RUNMODE_SAFE_MODE, RUNMODE_BOOTLOADER @@ -40,6 +41,8 @@ extern const mp_obj_type_t mcu_runmode_type; typedef struct { mp_obj_base_t base; } mcu_runmode_obj_t; + +extern const mcu_runmode_obj_t mcu_runmode_uf2_obj; extern const mcu_runmode_obj_t mcu_runmode_normal_obj; extern const mcu_runmode_obj_t mcu_runmode_safe_mode_obj; extern const mcu_runmode_obj_t mcu_runmode_bootloader_obj; diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index b8014ad76e..053958cca1 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -109,7 +109,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupt //| STATIC mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) { mcu_runmode_t run_mode; - if (run_mode_obj == &mcu_runmode_normal_obj) { + if (run_mode_obj == &mcu_runmode_uf2_obj) { + run_mode = RUNMODE_UF2; + } else if (run_mode_obj == &mcu_runmode_normal_obj) { run_mode = RUNMODE_NORMAL; } else if (run_mode_obj == &mcu_runmode_safe_mode_obj) { run_mode = RUNMODE_SAFE_MODE; @@ -118,9 +120,7 @@ STATIC mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) { } else { mp_raise_ValueError(translate("Invalid run mode.")); } - common_hal_mcu_on_next_reset(run_mode); - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_on_next_reset_obj, mcu_on_next_reset);