mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-08-29 13:58:17 +00:00
detach USB device stack before reboot (esp_restart_noos leaves the PHY attached)
This commit is contained in:
@@ -61,6 +61,26 @@
|
||||
#define ESP32_FORCE_DOWNLOAD_BOOT 1
|
||||
#endif
|
||||
|
||||
/* Detach the USB device stack before a reset so the host sees a real unplug —
|
||||
* see zephcore_usbd_detach(). Matters most on the ESP32-S3 USB companion,
|
||||
* whose OTG PHY survives a soft reset with D+ still pulled up.
|
||||
*
|
||||
* The condition below must be EXACTLY the one CMakeLists.txt uses to compile
|
||||
* adapters/usb/ZephyrUSBCDC.cpp, or this call site compiles against an
|
||||
* implementation that is never linked (findings #22 — that failure mode has
|
||||
* already cost this repo four separate undefined-reference bugs). The
|
||||
* repeater/observer/room-server branches use the inner half alone; the
|
||||
* companion branch wraps it in (LOG || COMPANION_USB || COMPANION_SERIAL), and
|
||||
* ZEPHCORE_COMPANION is the compile definition that identifies that branch. */
|
||||
#if !defined(CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT) && \
|
||||
(defined(CONFIG_USB_CDC_ACM) || defined(CONFIG_USBD_CDC_ACM_CLASS))
|
||||
#if !defined(ZEPHCORE_COMPANION) || defined(CONFIG_LOG) || \
|
||||
defined(CONFIG_ZEPHCORE_COMPANION_USB) || defined(CONFIG_ZEPHCORE_COMPANION_SERIAL)
|
||||
#include <ZephyrUSBCDC.h>
|
||||
#define ZEPHCORE_USBD_DETACH 1
|
||||
#endif
|
||||
#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 =
|
||||
@@ -295,6 +315,11 @@ void ZephyrBoard::onAfterTransmit()
|
||||
void ZephyrBoard::reboot()
|
||||
{
|
||||
k_msleep(50); /* Let UART/USB flush */
|
||||
#ifdef ZEPHCORE_USBD_DETACH
|
||||
/* USB device stack (CDC ACM): detach so the host sees an unplug. */
|
||||
zephcore_usbd_detach();
|
||||
k_msleep(100); /* Hold SE0 long enough for host disconnect debounce */
|
||||
#endif
|
||||
#ifdef ESP32_USB_SERIAL_DETACH
|
||||
/* Drop the D+ pull-up so the host sees a clean USB disconnect before the
|
||||
* soft reset (GH #43 — wedged serial port on macOS). */
|
||||
@@ -317,6 +342,14 @@ void ZephyrBoard::rebootToBootloader()
|
||||
REG_SET_BIT(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
|
||||
#endif
|
||||
k_msleep(50); /* Let UART/USB flush */
|
||||
#ifdef ZEPHCORE_USBD_DETACH
|
||||
/* Detach the CDC ACM device — same reason as reboot(), and doubly so here:
|
||||
* the ESP32-S3 comes back in ROM download mode, where the port belongs to
|
||||
* USB-Serial-JTAG. The host must see the old device leave the bus first or
|
||||
* it will not enumerate the new one. */
|
||||
zephcore_usbd_detach();
|
||||
k_msleep(100);
|
||||
#endif
|
||||
#ifdef ESP32_USB_SERIAL_DETACH
|
||||
/* Clean USB disconnect before the soft reset — same reason as reboot(). */
|
||||
usb_serial_jtag_ll_phy_enable_pad(false);
|
||||
|
||||
@@ -267,3 +267,27 @@ extern "C" void zephcore_usbd_set_dtr_cb(zephcore_usbd_cdc_dtr_cb_t cb)
|
||||
{
|
||||
s_dtr_cb = cb;
|
||||
}
|
||||
|
||||
extern "C" void zephcore_usbd_detach(void)
|
||||
{
|
||||
if (!s_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* usbd_disable() -> udc_disable() drops the D+ pull-up, which is the only
|
||||
* thing that makes the host see an unplug. A soft reset does not: on the
|
||||
* ESP32-S3, esp_restart_noos() resets WiFi/BT, timers, SPI, UART, DMA and
|
||||
* crypto but nothing USB, so the PHY pad stays enabled across the reset
|
||||
* and the host keeps talking to an endpoint the firmware has abandoned.
|
||||
* (Same root cause as GH #43, which hit the USB-Serial-JTAG controller;
|
||||
* this covers the USB OTG one that the CDC companion transport uses.)
|
||||
*
|
||||
* Safe from the usbd message callback: CONFIG_USBD_MSG_DEFERRED_MODE is
|
||||
* on by default, so that callback runs on the system workqueue rather
|
||||
* than in the device stack context, and usbd_disable() is not re-entered
|
||||
* from the thread it stops.
|
||||
*/
|
||||
(void)usbd_disable(&zephcore_usbd);
|
||||
s_initialized = false;
|
||||
s_dtr_active = false;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,13 @@ bool zephcore_usbd_is_dtr_active(void);
|
||||
* Companion uses this to reset its RX state and flip active_iface on drop. */
|
||||
void zephcore_usbd_set_dtr_cb(zephcore_usbd_cdc_dtr_cb_t cb);
|
||||
|
||||
/* Detach from the USB bus (drop the D+ pull-up) so the host sees an unplug.
|
||||
* Call before a reset: a soft reset leaves the PHY attached on some SoCs, and
|
||||
* the host then keeps a stale endpoint open across the reboot. No-op if the
|
||||
* stack was never initialized; after this, zephcore_usbd_init() would have to
|
||||
* run again to come back. */
|
||||
void zephcore_usbd_detach(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user