esp32/modmachine: Support bootloader on ESP32-S2/S3/C2/C3.

On these targets it's possible to enter the bootloader by setting a bit in
an RTC register before resetting.

Structure it in a way that a board can still provide a custom bootloader
handler.  The handler here will be the default if none is provided, for any
board based on the supported targets.

Signed-off-by: Trent Piepho <tpiepho@gmail.com>
diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c
index a61d381..759455a 100644
--- a/ports/esp32/modmachine.c
+++ b/ports/esp32/modmachine.c
@@ -220,6 +220,14 @@
     }
 }
 
+#if MICROPY_ESP32_USE_BOOTLOADER_RTC
+#include "soc/rtc_cntl_reg.h"
+NORETURN static void machine_bootloader_rtc(void) {
+    REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
+    esp_restart();
+}
+#endif
+
 #ifdef MICROPY_BOARD_ENTER_BOOTLOADER
 NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args) {
     MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h
index 0474b7e..f004c78 100644
--- a/ports/esp32/mpconfigport.h
+++ b/ports/esp32/mpconfigport.h
@@ -268,6 +268,14 @@
 #define MICROPY_HW_ENABLE_MDNS_RESPONDER    (1)
 #endif
 
+#ifndef MICROPY_BOARD_ENTER_BOOTLOADER
+// RTC has a register to trigger bootloader on these targets
+#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3
+#define MICROPY_ESP32_USE_BOOTLOADER_RTC    (1)
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) machine_bootloader_rtc()
+#endif
+#endif
+
 #ifdef MICROPY_BOARD_ENTER_BOOTLOADER
 #define MICROPY_PY_MACHINE_BOOTLOADER       (1)
 #else