Fix Heltec V4 display (Vext PMOS polarity) and Xtensa TX-wait stack overflow.
Conflict in heltec_wifi_lora32_v4_procpu.dts resolved: kept the corrected
BatADC header line from 247ca65 (GPIO1 = ADC1_CH0 / &adc0, GPIO37 active-HIGH)
and took the PR Vext change (GPIO36 active-LOW PMOS rail switch).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The V4's Vext rail switch is a PMOS: GPIO36 LOW turns the rail ON.
The DTS drove it ACTIVE_HIGH, leaving the OLED (and its I2C pull-ups)
unpowered — the rail floats at ~1.6V and SSD1306 init always fails
with -ETIMEDOUT.
Verified on hardware with a multimeter: GPIO36 high = 1.6V on Vext,
GPIO36 low = 3.3V, display works.
This matches what the working Arduino MeshCore firmware actually does
with the pin, despite its PIN_VEXT_EN_ACTIVE=HIGH define:
RefCountedDigitalPin::begin() initialises the pin to its *inactive*
level (LOW), and the V4 OLED build constructs the display with a NULL
periph_power (variants/heltec_v4/target.cpp) so nothing ever claims
it HIGH. GPIO36 is therefore driven LOW continuously under Arduino —
the exact state this fix reproduces via an ACTIVE_LOW boot-on
regulator.
New companion variant for the Heltec Wireless Tracker V1.1 (ESP32-S3-FN8 +
SX1262 + ST7735R 160x80 TFT + UC6580 GPS). Overlay + conf only; no driver,
CMake, or patch changes.
Board-specific fixes worth calling out:
- Battery ADC on &adc0 (ADC unit 1 -> GPIO1), NOT &adc1. In the upstream
esp32s3 DTS the node *labelled* adc1 is unit 2, whose channel 0 is GPIO11 =
the SX1262 MISO. adc_esp32_channel_setup() drives the channel pad to
GPIO_DISCONNECTED, clearing GPIO11's input buffer — which silently broke ALL
LoRa SPI reads (reads returned 0x00 -> every LBT CAD timed out) and also
sampled the wrong pin (battery read 0%). Removed the upstream 'vbatt'
voltage-divider (also on &adc1) and disabled adc1 so nothing claims GPIO11.
- Battery divider enable on GPIO2 active-HIGH (v1.1 ADC_CTRL), not the V3's
GPIO37/active-LOW (which never powered this board's divider).
- SX1262 on SPI2 with driver GPIO CS; DIO1 pull-down + rx-boosted.
- GPS run line (GPIO35) exposed via the gps-enable alias; GPS is powered from
the always-on Vext rail. GPIO36 (GPS PPS, an output) left unconfigured.
- Status LED on GPIO18 exposed as led0 (ZephCore heartbeat). UART1 — which the
upstream DTS parks on GPIO17/18 — disabled so the LED isn't stuck on.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Production (LOG=n, ASSERT=n, RTT=n, reboot-on-fatal) is now the prj.conf
default; debug.conf is the opt-in bundle. Removed prod.conf and the
logging.conf auto-include; relocated RTT/ASSERT out of the always-on
platform confs so they no longer override the prod defaults.
Add CONFIG_ZEPHCORE_COMPANION_USB so the USB CDC companion transport
compiles independently of logging (default-y on USB-capable companions,
opt-in on ESP32-S3 via esp32s3_usb.conf). Gate all USB sites behind one
ZEPHCORE_USB_STACK macro.
Rework BLE/USB interface arbitration to first-come-first-served: neither
transport evicts a live session. Make active_iface mutation thread-safe
(mutex + atomic claim) across the BLE callback thread and USB workqueue.
Share the ESP32-S3 USB OTG / console DTS via common dtsi includes; enable
uart0 (GPIO43/44) on station_g2 and xiao so the console reroute works.