mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 21:38:20 +00:00
auto-enable esp32s3 USB CDC companion in CMakeLists; board.overlay first in overlay order; esp32s3 download-mode reboot
This commit is contained in:
@@ -27,7 +27,7 @@ All commands are sent over USB serial (CDC-ACM). Commands sent remotely over the
|
||||
| `ver` | Firmware version and build date |
|
||||
| `board` | Board manufacturer name |
|
||||
| `reboot` | Reboot immediately |
|
||||
| `start dfu` | Reboot into UF2 bootloader for drag-and-drop firmware update |
|
||||
| `start dfu` | nRF52: reboot into the UF2 bootloader for drag-and-drop update. ESP32-S3: reboot into the ROM download mode so esptool can reach the chip |
|
||||
| `start ota` | ESP32: start WiFi AP + HTTP OTA server. nRF52: reboot into BLE OTA DFU mode |
|
||||
| `stop ota` | Stop WiFi OTA server (ESP32 only) |
|
||||
| `clkreboot` | Set clock to a fixed reference time (15 May 2024 8:50pm UTC) then reboot |
|
||||
|
||||
+95
-22
@@ -271,12 +271,21 @@ function(zephcore_auto_pair_overlay CONF_FILE)
|
||||
endif()
|
||||
string(REPLACE ".conf" ".overlay" OVERLAY_FILE "${CONF_FILE}")
|
||||
if(EXISTS "${OVERLAY_FILE}")
|
||||
# Append once, keeping the FIRST position. The user-extras pairing loop
|
||||
# below walks the whole combined EXTRA_CONF_FILE, so it re-pairs every
|
||||
# conf the auto chain already paired -- board.overlay used to land in
|
||||
# the list three times that way. Position is precedence in devicetree,
|
||||
# so silently re-appending an overlay also moved it later and let it
|
||||
# override things it was never meant to.
|
||||
if(EXTRA_DTC_OVERLAY_FILE)
|
||||
set(EXTRA_DTC_OVERLAY_FILE "${EXTRA_DTC_OVERLAY_FILE};${OVERLAY_FILE}" PARENT_SCOPE)
|
||||
if(NOT "${OVERLAY_FILE}" IN_LIST EXTRA_DTC_OVERLAY_FILE)
|
||||
set(EXTRA_DTC_OVERLAY_FILE "${EXTRA_DTC_OVERLAY_FILE};${OVERLAY_FILE}" PARENT_SCOPE)
|
||||
message(STATUS " [auto-pair] ${CONF_FILE} → ${OVERLAY_FILE}")
|
||||
endif()
|
||||
else()
|
||||
set(EXTRA_DTC_OVERLAY_FILE "${OVERLAY_FILE}" PARENT_SCOPE)
|
||||
message(STATUS " [auto-pair] ${CONF_FILE} → ${OVERLAY_FILE}")
|
||||
endif()
|
||||
message(STATUS " [auto-pair] ${CONF_FILE} → ${OVERLAY_FILE}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@@ -364,6 +373,45 @@ if(NOT ZEPHCORE_BOARD_CONF AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOAR
|
||||
set(ZEPHCORE_BOARD_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_BASE}/board.conf")
|
||||
endif()
|
||||
|
||||
# ========== DTC Overlay Precedence ==========
|
||||
# board.overlay goes in FIRST, so everything applied after it can override it.
|
||||
#
|
||||
# Devicetree is last-writer-wins per property, and this list is that order. The
|
||||
# board overlay is the board's *baseline*; the overlays paired with the confs
|
||||
# that follow (repeater/pm_esp32/esp32s3_usb/no_display/...) are deliberate
|
||||
# per-role deviations from it, and the conf chain already documents that same
|
||||
# precedence ("user extras last so they can override"). Until 2026-08-28 the
|
||||
# overlay order was the exact opposite of the conf order, with two live
|
||||
# consequences:
|
||||
# - esp32s3_usb.overlay could not move the console off USB Serial/JTAG on the
|
||||
# boards that pick a console in board.overlay (heltec V4/V43, wireless
|
||||
# tracker v2) -- the reroute was overridden and the console pointed at a
|
||||
# peripheral that no longer owned the pins.
|
||||
# - pm_esp32.overlay could not hold the SX1262 NSS across light sleep on
|
||||
# heltec_wireless_tracker, whose board.overlay re-declares spi2 cs-gpios
|
||||
# without ESP32_GPIO_SLEEP_HOLD_EN -- i.e. the exact floating-NSS failure
|
||||
# that overlay exists to prevent.
|
||||
# partitions.overlay is appended after everything (see below) and stays there:
|
||||
# it must also be fed verbatim to the MCUboot image.
|
||||
set(ZEPHCORE_BOARD_OVERLAY "")
|
||||
file(GLOB_RECURSE BOARD_OVERLAY_CANDIDATES "${CMAKE_CURRENT_SOURCE_DIR}/boards/*/${BOARD_BASE}/board.overlay")
|
||||
if(BOARD_OVERLAY_CANDIDATES)
|
||||
list(GET BOARD_OVERLAY_CANDIDATES 0 ZEPHCORE_BOARD_OVERLAY)
|
||||
endif()
|
||||
# Fallback: direct path without vendor subdirectory
|
||||
if(NOT ZEPHCORE_BOARD_OVERLAY AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_BASE}/board.overlay")
|
||||
set(ZEPHCORE_BOARD_OVERLAY "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_BASE}/board.overlay")
|
||||
endif()
|
||||
|
||||
# Append to EXTRA_DTC_OVERLAY_FILE (preserves any user-specified extras)
|
||||
if(ZEPHCORE_BOARD_OVERLAY AND EXISTS ${ZEPHCORE_BOARD_OVERLAY})
|
||||
if(EXTRA_DTC_OVERLAY_FILE)
|
||||
set(EXTRA_DTC_OVERLAY_FILE "${EXTRA_DTC_OVERLAY_FILE};${ZEPHCORE_BOARD_OVERLAY}" CACHE STRING "" FORCE)
|
||||
else()
|
||||
set(EXTRA_DTC_OVERLAY_FILE "${ZEPHCORE_BOARD_OVERLAY}" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Build the EXTRA_CONF_FILE list (append to any user-provided extras)
|
||||
# Auto-pair each .conf with a same-named .overlay if it exists.
|
||||
set(ZEPHCORE_CONF_FILES "")
|
||||
@@ -466,6 +514,51 @@ if(ZEPHCORE_PLATFORM_CONF MATCHES "esp32_common" AND EXTRA_CONF_FILE MATCHES "re
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Auto-include the ESP32-S3 USB CDC-ACM companion transport.
|
||||
#
|
||||
# The policy lives here rather than in build.sh so that a locally built
|
||||
# companion is the same firmware as the published release. The ESP32 release
|
||||
# flow already diverges from a plain build in its *layout* (sysbuild/MCUboot);
|
||||
# letting it diverge in which *transports* the app speaks as well would make
|
||||
# user bug reports unreproducible from source.
|
||||
#
|
||||
# Detection is the board's own devicetree, not a name list: a board that
|
||||
# includes esp32s3_usb_otg.dtsi has declared the cdc_acm_uart node, which is
|
||||
# exactly the precondition the USB companion call sites are compiled behind
|
||||
# (see ZEPHCORE_USB_STACK in src/main_companion.cpp). Boards without it are
|
||||
# skipped automatically -- Heltec V3 (USB-C via CP2102, uses
|
||||
# serial_companion.conf), Wireless Tracker V1, and every C3/C6/classic-ESP32
|
||||
# part, which has no DWC2 controller at all.
|
||||
#
|
||||
# COMPANION ROLE ONLY. esp32s3_usb.conf sets CONFIG_ZEPHCORE_COMPANION_USB=y,
|
||||
# which carries no role dependency of its own, and its paired overlay moves the
|
||||
# console to uart0. In a repeater/observer/room-server build that would both
|
||||
# compile the companion USB stack and strand the serial CLI on GPIO43/44.
|
||||
# serial_companion.conf is excluded for a different reason: COMPANION_SERIAL
|
||||
# `depends on !COMPANION_USB`, so adding this would silently disable it.
|
||||
#
|
||||
# DEBUG BUILDS ARE EXCLUDED. ESP32 has no RTT (debug_esp32.conf routes logs to
|
||||
# the console backend) and this conf hands that USB port to the binary
|
||||
# companion protocol, so an auto-enabled debug build would have nowhere to log.
|
||||
# Pass both confs explicitly to debug the USB transport itself; logs then need
|
||||
# a UART adapter on GPIO43/44.
|
||||
if(ZEPHCORE_PLATFORM_CONF MATCHES "esp32_common" AND ZEPHCORE_BOARD_CONF
|
||||
AND NOT EXTRA_CONF_FILE MATCHES "repeater|observer|room_server|serial_companion|esp32s3_usb|debug")
|
||||
get_filename_component(ZEPHCORE_BOARD_DIR "${ZEPHCORE_BOARD_CONF}" DIRECTORY)
|
||||
if(EXISTS "${ZEPHCORE_BOARD_DIR}/board.overlay")
|
||||
file(READ "${ZEPHCORE_BOARD_DIR}/board.overlay" ZEPHCORE_BOARD_OVERLAY_TEXT)
|
||||
if(ZEPHCORE_BOARD_OVERLAY_TEXT MATCHES "esp32s3_usb_otg\\.dtsi")
|
||||
set(ZEPHCORE_USB_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/esp32s3_usb.conf")
|
||||
if(EXISTS ${ZEPHCORE_USB_CONF})
|
||||
list(APPEND ZEPHCORE_CONF_FILES ${ZEPHCORE_USB_CONF})
|
||||
zephcore_auto_pair_overlay("${ZEPHCORE_USB_CONF}")
|
||||
message(STATUS " USB CDC companion: auto-enabled (board declares USB OTG CDC-ACM)")
|
||||
endif()
|
||||
endif()
|
||||
unset(ZEPHCORE_BOARD_OVERLAY_TEXT)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Append to EXTRA_CONF_FILE — auto-generated configs first, user extras last.
|
||||
# User-specified extras (repeater.conf, debug.conf) MUST come after the auto chain
|
||||
# so they can override settings (e.g. CONFIG_BT=n in repeater.conf).
|
||||
@@ -499,26 +592,6 @@ if(EXTRA_CONF_FILE)
|
||||
endif()
|
||||
|
||||
# ========== DTC Overlay Hierarchy ==========
|
||||
# Search for board.overlay in possible locations (same as board.conf)
|
||||
set(ZEPHCORE_BOARD_OVERLAY "")
|
||||
file(GLOB_RECURSE BOARD_OVERLAY_CANDIDATES "${CMAKE_CURRENT_SOURCE_DIR}/boards/*/${BOARD_BASE}/board.overlay")
|
||||
if(BOARD_OVERLAY_CANDIDATES)
|
||||
list(GET BOARD_OVERLAY_CANDIDATES 0 ZEPHCORE_BOARD_OVERLAY)
|
||||
endif()
|
||||
# Fallback: direct path without vendor subdirectory
|
||||
if(NOT ZEPHCORE_BOARD_OVERLAY AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_BASE}/board.overlay")
|
||||
set(ZEPHCORE_BOARD_OVERLAY "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_BASE}/board.overlay")
|
||||
endif()
|
||||
|
||||
# Append to EXTRA_DTC_OVERLAY_FILE (preserves any user-specified extras)
|
||||
if(ZEPHCORE_BOARD_OVERLAY AND EXISTS ${ZEPHCORE_BOARD_OVERLAY})
|
||||
if(EXTRA_DTC_OVERLAY_FILE)
|
||||
set(EXTRA_DTC_OVERLAY_FILE "${EXTRA_DTC_OVERLAY_FILE};${ZEPHCORE_BOARD_OVERLAY}" CACHE STRING "" FORCE)
|
||||
else()
|
||||
set(EXTRA_DTC_OVERLAY_FILE "${ZEPHCORE_BOARD_OVERLAY}" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Flash partition layout lives in a separate boards/<...>/<board>/partitions.overlay
|
||||
# so the SAME file can be fed to the MCUboot image too (see sysbuild/CMakeLists.txt).
|
||||
# The app and MCUboot MUST share one flash map — otherwise MCUboot stages/looks for
|
||||
|
||||
+5
-1
@@ -134,7 +134,11 @@ config ZEPHCORE_COMPANION_USB
|
||||
depends forces this to n automatically — no conf change needed.
|
||||
|
||||
For ESP32-S3 boards, USB_DEVICE_STACK_NEXT must be enabled first via
|
||||
boards/common/esp32s3_usb.conf before this becomes active.
|
||||
boards/common/esp32s3_usb.conf before this becomes active. CMakeLists.txt
|
||||
adds that conf automatically to companion builds on the S3 boards whose
|
||||
board.overlay declares the USB OTG CDC-ACM node, so it is on by default
|
||||
there too — but not on repeater/observer/room-server or debug builds,
|
||||
which keep the port for the console.
|
||||
|
||||
config ZEPHCORE_COMPANION_SERIAL
|
||||
bool "Enable plain-UART companion transport"
|
||||
|
||||
@@ -33,6 +33,34 @@
|
||||
#define ESP32_USB_SERIAL_DETACH 1
|
||||
#endif
|
||||
|
||||
/* ESP32-S3: reboot into the ROM download mode rather than back into the app.
|
||||
*
|
||||
* The USB CDC companion transport (boards/common/esp32s3_usb.conf) hands the
|
||||
* shared D+/D- pads to USB OTG and disables USB-Serial-JTAG. USJ is exactly
|
||||
* what esptool drives to put the chip into download mode, so once our CDC-ACM
|
||||
* device owns the port esptool's auto-reset is inert: DTR/RTS land on a Zephyr
|
||||
* CDC endpoint that is not wired to EN/BOOT, and the only way back into the
|
||||
* bootloader is the physical BOOT button.
|
||||
*
|
||||
* FORCE_DOWNLOAD_BOOT lives in the RTC domain, which a software system reset
|
||||
* does not clear (only a power-on reset does), so setting it and rebooting
|
||||
* brings the ROM up in download mode with USB-Serial-JTAG back on the pads.
|
||||
* That gives both `start dfu` and the Arduino-style 1200-baud touch a way to
|
||||
* hand the port back to esptool / esptool-js / the web configurator.
|
||||
*
|
||||
* Same register and sequence Arduino-ESP32 uses in usb_persist_restart()
|
||||
* (RESTART_BOOTLOADER). OPTION1 carries no other bits on this SoC, but set the
|
||||
* bit rather than writing the word so it stays correct if that changes. Scoped
|
||||
* to the S3 deliberately: it is the only part we ship whose USB port can be
|
||||
* taken away from the ROM this way (C3/C6 use a different LP_AON register, and
|
||||
* classic ESP32 has no native USB — it always flashes through its UART bridge).
|
||||
*/
|
||||
#if defined(CONFIG_SOC_SERIES_ESP32S3)
|
||||
#include <soc/rtc_cntl_reg.h>
|
||||
#include <soc/soc.h>
|
||||
#define ESP32_FORCE_DOWNLOAD_BOOT 1
|
||||
#endif
|
||||
|
||||
/* LoRa TX activity LED (optional — defined per-board via DT alias) */
|
||||
#if DT_NODE_EXISTS(DT_ALIAS(lora_tx_led))
|
||||
static const struct gpio_dt_spec tx_led =
|
||||
@@ -282,8 +310,18 @@ void ZephyrBoard::rebootToBootloader()
|
||||
/* Write magic value to GPREGRET0 - enter UF2 bootloader mode.
|
||||
* UF2 supports both drag-and-drop (.uf2) and serial DFU (nrfutil). */
|
||||
nrf_power_gpregret_set(NRF_POWER, 0, BOOTLOADER_DFU_UF2_MAGIC);
|
||||
#endif
|
||||
#ifdef ESP32_FORCE_DOWNLOAD_BOOT
|
||||
/* Come back up in the ROM download mode instead of the app, handing the
|
||||
* USB port back to USB-Serial-JTAG so esptool can reach it. */
|
||||
REG_SET_BIT(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
|
||||
#endif
|
||||
k_msleep(50); /* Let UART/USB flush */
|
||||
#ifdef ESP32_USB_SERIAL_DETACH
|
||||
/* Clean USB disconnect before the soft reset — same reason as reboot(). */
|
||||
usb_serial_jtag_ll_phy_enable_pad(false);
|
||||
k_msleep(100);
|
||||
#endif
|
||||
sys_reboot(SYS_REBOOT_COLD);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,17 @@
|
||||
* GPIO43/44. It is included from the auto-paired esp32s3_usb.overlay instead,
|
||||
* so it follows esp32s3_usb.conf.
|
||||
*
|
||||
* Boards whose console really is a physical uart0 — Heltec V3/V4/V43, and
|
||||
* ThinkNode M9 (USB-C via a CH9102-class bridge into UART0, native USB pads not
|
||||
* bonded) — do include it unconditionally, which is correct for them.
|
||||
* Boards whose console really is a physical uart0 — Heltec V3, and ThinkNode M9
|
||||
* (USB-C via a CH9102-class bridge into UART0, native USB pads not bonded) — do
|
||||
* include it unconditionally, which is correct for them.
|
||||
*
|
||||
* Heltec V4/V4.3 and Wireless Tracker V2 are NOT in that group even though
|
||||
* their board DTS names uart0: their board.overlay re-chooses usb_serial, so
|
||||
* they go through the conditional path above like every other native-USB board.
|
||||
* That did not work until 2026-08-28 — board.overlay was applied AFTER the
|
||||
* auto-paired overlays and simply won, leaving the console pointed at a USJ
|
||||
* peripheral that no longer owned the pins. See the DTC overlay precedence
|
||||
* block in CMakeLists.txt.
|
||||
*
|
||||
* uart0 is disabled by default in the ESP32-S3 SoC dtsi, so we enable it and
|
||||
* pin it to the chip's ROM-default UART0 pads (GPIO43 TX / GPIO44 RX) — the
|
||||
|
||||
@@ -5,9 +5,18 @@
|
||||
# USB transport on S3 boards. Do NOT use on ESP32 (original) or C3/C6 — those
|
||||
# chips have no DWC2 controller.
|
||||
#
|
||||
# Build with:
|
||||
# Applied AUTOMATICALLY to companion builds on every S3 board whose board.overlay
|
||||
# includes esp32s3_usb_otg.dtsi — see the "Auto-include the ESP32-S3 USB CDC-ACM
|
||||
# companion transport" block in CMakeLists.txt for the gate (companion role only,
|
||||
# and not on debug builds, which need that port for the console). Pass it by
|
||||
# hand only to override that policy:
|
||||
# -DEXTRA_CONF_FILE="boards/common/esp32s3_usb.conf"
|
||||
#
|
||||
# NOTE: this takes the USB port away from USB-Serial-JTAG, so esptool's
|
||||
# auto-reset into download mode stops working on boards flashed over native USB.
|
||||
# `start dfu` and the 1200-baud touch set FORCE_DOWNLOAD_BOOT to give it back
|
||||
# (ZephyrBoard::rebootToBootloader); otherwise it is the BOOT button.
|
||||
#
|
||||
# Also add the cdc_acm_uart DTS node to the board overlay (the overlays include
|
||||
# boards/common/esp32s3_usb_otg.dtsi). Without the DT node,
|
||||
# DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart) is false and
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
* CONFIG_ZEPHCORE_COMPANION_USB — the conf/overlay pairing is what makes this
|
||||
* conditional.
|
||||
*
|
||||
* Boards whose console is already a physical uart0 (Heltec V3/V4/V43, ThinkNode
|
||||
* M9) are unaffected: the include re-asserts the same uart0 + GPIO43/44 setup
|
||||
* they already have.
|
||||
* Boards whose console is already a physical uart0 (Heltec V3, ThinkNode M9) are
|
||||
* unaffected: the include re-asserts the same uart0 + GPIO43/44 setup they
|
||||
* already have. Heltec V4/V4.3 and Wireless Tracker V2 DO get moved — their
|
||||
* board.overlay chooses usb_serial — which is the point, and only actually
|
||||
* happens because board.overlay now goes into EXTRA_DTC_OVERLAY_FILE first
|
||||
* (see the DTC overlay precedence block in CMakeLists.txt).
|
||||
*/
|
||||
#include "esp32s3_console_uart0.dtsi"
|
||||
|
||||
@@ -90,6 +90,8 @@
|
||||
|
||||
/* LittleFS auto-mount — standard /lfs mount point */
|
||||
#include "../../common/filesystem.dtsi"
|
||||
/* USB CDC-ACM — companion USB transport (esp32s3_usb.conf). Heltec has a
|
||||
* dedicated UART console, so no console reroute is needed. */
|
||||
/* USB CDC-ACM — companion USB transport, auto-enabled for companion builds via
|
||||
* boards/common/esp32s3_usb.conf (see the auto-include block in CMakeLists.txt).
|
||||
* The chosen console above is usb_serial, i.e. the same D+/D- pins, so the conf's
|
||||
* paired overlay moves the console to uart0/GPIO43-44 for those builds. */
|
||||
#include "../../common/esp32s3_usb_otg.dtsi"
|
||||
|
||||
@@ -90,6 +90,8 @@
|
||||
|
||||
/* LittleFS auto-mount — standard /lfs mount point */
|
||||
#include "../../common/filesystem.dtsi"
|
||||
/* USB CDC-ACM — companion USB transport (esp32s3_usb.conf). Heltec has a
|
||||
* dedicated UART console, so no console reroute is needed. */
|
||||
/* USB CDC-ACM — companion USB transport, auto-enabled for companion builds via
|
||||
* boards/common/esp32s3_usb.conf (see the auto-include block in CMakeLists.txt).
|
||||
* The chosen console above is usb_serial, i.e. the same D+/D- pins, so the conf's
|
||||
* paired overlay moves the console to uart0/GPIO43-44 for those builds. */
|
||||
#include "../../common/esp32s3_usb_otg.dtsi"
|
||||
|
||||
@@ -141,8 +141,15 @@ void CommonCLI::scheduleReboot(uint8_t type)
|
||||
*/
|
||||
void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, char* reply) {
|
||||
if (strcmp(command, "start dfu") == 0) {
|
||||
/* Reboot into UF2 bootloader for firmware update */
|
||||
/* Reboot into the chip's own firmware-update mode. nRF52: the Adafruit
|
||||
* UF2 bootloader. ESP32-S3: the ROM download mode, which is the only
|
||||
* way to get the USB port back from the CDC companion transport for
|
||||
* esptool (see ZephyrBoard::rebootToBootloader). */
|
||||
#if defined(CONFIG_SOC_SERIES_ESP32S3)
|
||||
strcpy(reply, "OK - rebooting to ESP32 download mode");
|
||||
#else
|
||||
strcpy(reply, "OK - rebooting to UF2 DFU");
|
||||
#endif
|
||||
scheduleReboot(REBOOT_DFU);
|
||||
} else if (memcmp(command, "start ota", 9) == 0) {
|
||||
#if IS_ENABLED(CONFIG_ZEPHCORE_WIFI_OTA)
|
||||
|
||||
Reference in New Issue
Block a user