Add serial reset and bootloader commands, no more BOOT+RST

Two new debug commands:
- 'X' (reset): ESP.restart() for clean reboot
- 'Z' (bootloader): sets RTC_CNTL_FORCE_DOWNLOAD_BOOT and restarts,
  putting the ESP32-S3 directly into download mode for esptool

Workflow: screenshot.py z → esptool write_flash (no BOOT+RST)

Also adds reset/bootloader subcommands to screenshot.py.
This commit is contained in:
GlassOnTin 2026-03-31 14:06:47 +01:00
commit d1daf8ca3e
2 changed files with 44 additions and 0 deletions

20
Gui.h
View file

@ -8,6 +8,7 @@
#if BOARD_MODEL == BOARD_TWATCH_ULT
#include <lvgl.h>
#include "soc/rtc_cntl_reg.h"
// Custom fonts: generated with lv_font_conv --no-compress from Montserrat Bold
// IMPORTANT: must use --no-compress or set LV_USE_FONT_COMPRESSED=1 in lv_conf.h
@ -1335,6 +1336,25 @@ static void gui_cmd_execute() {
Serial.flush();
break;
}
case 'X': { // Hard reset
Serial.write(hdr, 4);
Serial.println("{\"reset\":true}");
Serial.flush();
delay(100);
ESP.restart();
break;
}
case 'Z': { // Reboot into download mode (no BOOT+RST needed)
Serial.write(hdr, 4);
Serial.println("{\"bootloader\":true}");
Serial.flush();
delay(100);
#if MCU_VARIANT == MCU_ESP32
REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
ESP.restart();
#endif
break;
}
}
}

View file

@ -241,6 +241,20 @@ def cmd_files(s):
print(f"Timeout ({len(buf)} bytes)")
def cmd_simple(s, cmd_char, label):
"""Send a command, print response, don't wait long"""
send_cmd(s, ord(cmd_char))
time.sleep(0.5)
data = s.read(s.in_waiting or 1)
if data:
magic = PREFIX + cmd_char.encode()
idx = data.find(magic)
if idx >= 0:
print(data[idx + 4:].decode('ascii', errors='replace').strip())
return
print(label)
def cmd_log(s):
send_cmd(s, ord('L'))
buf = b""
@ -295,6 +309,12 @@ def main():
sub.add_parser("files", aliases=["f"],
help="List files on SD card")
sub.add_parser("reset", aliases=["x"],
help="Hard reset the device")
sub.add_parser("bootloader", aliases=["z"],
help="Reboot into download mode (no BOOT+RST needed)")
args = parser.parse_args()
if not args.command:
parser.print_help()
@ -322,6 +342,10 @@ def main():
cmd_log(s)
elif args.command in ("files", "f"):
cmd_files(s)
elif args.command in ("reset", "x"):
cmd_simple(s, 'X', "Reset sent")
elif args.command in ("bootloader", "z"):
cmd_simple(s, 'Z', "Rebooting into download mode...")
finally:
s.close()