Make production the default build; decouple USB companion from CONFIG_LOG

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.
This commit is contained in:
liquidraver
2026-05-30 21:05:42 +02:00
parent 7d7a64ff5a
commit 553b71c44a
25 changed files with 332 additions and 126 deletions
+7 -7
View File
@@ -73,20 +73,20 @@ cd <cloned folder>
west init -l zephcore
west update
# Companion (with logging)
# Companion (production — default, no extra conf needed)
west build -b wio_tracker_l1 zephcore --pristine
# Companion (production, no logging, no USB)
# Companion (debug logging)
west build -b wio_tracker_l1 zephcore --pristine -- \
-DEXTRA_CONF_FILE="boards/common/prod.conf"
-DEXTRA_CONF_FILE="boards/common/debug.conf"
# Repeater (with logging)
# Repeater
west build -b rak4631 zephcore --pristine -- \
-DEXTRA_CONF_FILE="boards/common/repeater.conf"
# Repeater (production)
# Repeater (debug logging)
west build -b rak4631 zephcore --pristine -- \
-DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/prod.conf"
-DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/debug.conf"
# Repeater with packet logging (clean RAW/RX/TX lines only, no debug spam)
west build -b rak4631 zephcore --pristine -- \
@@ -175,7 +175,7 @@ The old `txdelay`, `rxdelay`, and `direct.txdelay` commands are still accepted f
- **LoRa RX duty cycle**: CAD-based receive windowing reduces LoRa RX current from ~10-15mA to ~3-5mA. Auto-enabled for SX1262 companion and repeater builds (toggleable at runtime via `set rxduty on/off`). Disabled for LR1110 (mid-preamble lock issue) and SX127x.
- **Adaptive Power Control (APC)**: compiled in by default but disabled at runtime. Enable per-node with `set tx apc` -- automatically reduces TX power when echo SNR shows excess margin, ramping back up if echoes drop. See [apc.md](zephcore/apc.md).
- **USB disabled in production**: Saves ~2-5mA and 62KB flash when logging is off
- **Production by default**: No logging, no asserts, reboot-on-fatal. Add `debug.conf` to enable logging.
- **GPIO-gated GPS**: Powered on only during fix acquisition
## Configuration
+10 -10
View File
@@ -37,19 +37,19 @@ if [[ $1 == "nrf" ]]; then
for board in "${nRF_boards[@]}"; do
board_clean_for_path=$(echo "$board" | sed -e 's/\//-/g')
# build nRF companions
# build nRF companions (production is the default — no extra conf needed)
echo "Now building $board companion"
if [[ $board == "wio_tracker_l1" ]]; then
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/prod.conf" -DCONFIG_ZEPHCORE_EASTER_EGG_DOOM=y
west build -b "$board" zephcore --pristine -- -DCONFIG_ZEPHCORE_EASTER_EGG_DOOM=y
else
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/prod.conf"
west build -b "$board" zephcore --pristine
fi
mv build/zephyr/zephyr.uf2 firmware/"$board"-companion-"$COMMIT_HASH".uf2
mv build/zephyr/zephyr.zip firmware/"$board"-companion-"$COMMIT_HASH".zip
# build nRF repeaters
echo "Now building $board repeater"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/prod.conf"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/repeater.conf"
mv build/zephyr/zephyr.uf2 firmware/"$board"-repeater-"$COMMIT_HASH".uf2
mv build/zephyr/zephyr.zip firmware/"$board"-repeater-"$COMMIT_HASH".zip
@@ -58,12 +58,12 @@ if [[ $1 == "nrf" ]]; then
# Heltec_t114_without_display_* PIO envs.
if [[ $board == "heltec_t114" ]]; then
echo "Now building $board companion (noscreen)"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/prod.conf;boards/nrf52840/heltec_t114/no_display.conf"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/nrf52840/heltec_t114/no_display.conf"
mv build/zephyr/zephyr.uf2 firmware/"$board"-companion-noscreen-"$COMMIT_HASH".uf2
mv build/zephyr/zephyr.zip firmware/"$board"-companion-noscreen-"$COMMIT_HASH".zip
echo "Now building $board repeater (noscreen)"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/prod.conf;boards/nrf52840/heltec_t114/no_display.conf"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/nrf52840/heltec_t114/no_display.conf"
mv build/zephyr/zephyr.uf2 firmware/"$board"-repeater-noscreen-"$COMMIT_HASH".uf2
mv build/zephyr/zephyr.zip firmware/"$board"-repeater-noscreen-"$COMMIT_HASH".zip
fi
@@ -82,9 +82,9 @@ if [[ $1 == "esp32" ]]; then
fi
if [[ $2 == "companions" ]]; then
# build ESP32 companions
# build ESP32 companions (production is the default)
echo "Now building $board companion"
west build -b "$board" zephcore --pristine --sysbuild -- -DEXTRA_CONF_FILE="boards/common/prod.conf"
west build -b "$board" zephcore --pristine --sysbuild
FLASH_SIZE=$(
python3 -c '
import re
@@ -127,7 +127,7 @@ print(str(size // 1048576) + "MB")
if [[ $2 == "repeaters" ]]; then
# build ESP32 repeaters
echo "Now building $board repeater"
west build -b "$board" zephcore --pristine --sysbuild -- -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/prod.conf"
west build -b "$board" zephcore --pristine --sysbuild -- -DEXTRA_CONF_FILE="boards/common/repeater.conf"
FLASH_SIZE=$(
python3 -c '
import re
+2 -2
View File
@@ -511,11 +511,11 @@ Wolf3D-style raycaster on OLED: textured walls, 2 enemy types, shooting, HUD. By
### 9.1 Config Layering
```
prj.conf (base: console, logging)
prj.conf (base: console; production defaults — LOG=n, ASSERT=n)
→ boards/common/zephcore_common.conf (ALL boards: BLE, crypto, FS, LoRa, sensors)
→ boards/common/<platform>_common.conf (nrf52/esp32/nrf54l/mg24 specifics)
→ boards/<mcu>/<board>/board.conf (board-specific pins, features)
→ [optional] repeater.conf, prod.conf (user extras, LAST = highest priority)
→ [optional] repeater.conf, debug.conf (user extras, LAST = highest priority)
```
### 9.2 Key Kconfig Choices
+1 -11
View File
@@ -306,17 +306,7 @@ if(ZEPHCORE_BOARD_CONF AND EXISTS ${ZEPHCORE_BOARD_CONF})
zephcore_auto_pair_overlay("${ZEPHCORE_BOARD_CONF}")
endif()
# Include logging tuning only for debug builds (when prod.conf is NOT active).
# This avoids Kconfig warnings from log settings that depend on CONFIG_LOG.
set(ZEPHCORE_LOGGING_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/logging.conf")
if(EXTRA_CONF_FILE MATCHES "prod\\.conf")
message(STATUS " Production build — skipping logging.conf")
else()
if(EXISTS ${ZEPHCORE_LOGGING_CONF})
list(APPEND ZEPHCORE_CONF_FILES ${ZEPHCORE_LOGGING_CONF})
zephcore_auto_pair_overlay("${ZEPHCORE_LOGGING_CONF}")
endif()
endif()
# Production is the default. Debug logging is opt-in via debug.conf.
# Auto-include WiFi OTA for ESP32 repeater builds.
# Enables WiFi AP + HTTP server + MCUboot image management.
+21
View File
@@ -66,6 +66,27 @@ config ZEPHCORE_ROLE_COMPANION
BLE companion device that connects to ZephCore mobile app.
Includes BLE stack, contact management, offline queue, channels.
config ZEPHCORE_COMPANION_USB
bool "Enable USB CDC companion transport"
depends on USB_DEVICE_STACK_NEXT
default y if ZEPHCORE_ROLE_COMPANION
help
Compile and init the USB CDC-ACM companion protocol stack
(ZephyrCompanionUSB / ZephyrUSBCDC) independently of CONFIG_LOG.
The full ~60-opcode binary protocol is available over USB even in
production builds (CONFIG_LOG=n). USB and BLE arbitrate the active
interface first-come-first-served: CMD_APP_START claims it for USB only
if no BLE session is already active (and is ignored while BLE is live);
on USB unplug the interface is handed back to BLE or released to idle.
Enabled by default for all companion builds on platforms that already
have CONFIG_USB_DEVICE_STACK_NEXT=y (all nRF52840 boards). On
platforms without USB hardware (MG24, ESP32 classic, C3/C6) the
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.
config ZEPHCORE_ROLE_REPEATER
bool "Repeater"
help
+72 -12
View File
@@ -122,6 +122,44 @@ static int64_t ble_tx_start_time = 0;
/* Active interface tracking */
static enum zephcore_iface active_iface = ZEPHCORE_IFACE_NONE;
/* active_iface is mutated from two threads — the Bluetooth callback thread
* (connect / security / pairing / disconnect) and the USB workqueue
* (CMD_APP_START / DTR drop). This mutex makes the check-then-act claim and
* release sequences atomic so the two transports can never both believe they
* own the interface (or lose a write to it). */
K_MUTEX_DEFINE(ble_iface_lock);
/* Atomically claim the interface for `who` iff it is currently idle.
* Returns true only if this call performed the NONE -> who transition. */
static bool iface_claim_if_idle(enum zephcore_iface who)
{
k_mutex_lock(&ble_iface_lock, K_FOREVER);
bool claimed = (active_iface == ZEPHCORE_IFACE_NONE);
if (claimed) {
active_iface = who;
}
k_mutex_unlock(&ble_iface_lock);
return claimed;
}
/* Atomically release the interface if `who` currently owns it. */
static void iface_release(enum zephcore_iface who)
{
k_mutex_lock(&ble_iface_lock, K_FOREVER);
if (active_iface == who) {
active_iface = ZEPHCORE_IFACE_NONE;
}
k_mutex_unlock(&ble_iface_lock);
}
/* Claim the active interface for BLE, but only if nothing else owns it.
* First-come-first-served: a live USB session must not be evicted by BLE
* connecting/pairing in the background. Returns true if BLE now owns it. */
static bool ble_claim_iface_if_idle(void)
{
return iface_claim_if_idle(ZEPHCORE_IFACE_BLE);
}
/* DLE tracking — set after successful DLE request to avoid double-request */
static bool dle_requested;
@@ -298,6 +336,16 @@ static void connected(struct bt_conn *conn, uint8_t err)
return;
}
LOG_INF("connected: %s", addr);
/* Reject BLE connections while USB is the active transport.
* The user connected via BLE expecting to exchange messages, but
* USB owns the interface they would get nothing and be confused. */
if (active_iface == ZEPHCORE_IFACE_USB) {
LOG_INF("connected: USB active — rejecting BLE connection from %s", addr);
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
return;
}
current_conn = bt_conn_ref(conn);
/* Zephyr stops advertising internally when the conn slot is consumed
@@ -349,9 +397,7 @@ static void disconnected(struct bt_conn *conn, uint8_t reason)
conn_params_pending = false;
/* Clear interface state if BLE was active */
if (active_iface == ZEPHCORE_IFACE_BLE) {
active_iface = ZEPHCORE_IFACE_NONE;
}
iface_release(ZEPHCORE_IFACE_BLE);
/* Clear queues, retry state, and congestion */
k_msgq_purge(&ble_send_queue);
@@ -397,7 +443,7 @@ static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_
if (level >= BT_SECURITY_L2 && !ble_tx_ready) {
LOG_INF("security established, enabling TX");
ble_tx_ready = true;
active_iface = ZEPHCORE_IFACE_BLE;
ble_claim_iface_if_idle();
/* If CCC was already subscribed (bonded reconnect — phone writes
* CCC before security_changed fires), kick TX now. On fresh
@@ -532,14 +578,12 @@ static void pairing_complete(struct bt_conn *conn, bool bonded)
ARG_UNUSED(conn);
LOG_INF("pairing complete: bonded=%d", bonded);
/* Switch to BLE interface (fresh pairing only).
* Conn params and TX enable are handled in security_changed(),
* which fires for both fresh pairing and bonded reconnects. */
if (active_iface == ZEPHCORE_IFACE_USB) {
LOG_INF("switching from USB to BLE");
/* Main handles USB state clearing via on_connected callback */
if (ble_claim_iface_if_idle()) {
LOG_INF("pairing complete, activating BLE interface");
} else {
LOG_INF("pairing complete, %s already active — BLE paired but not promoted",
active_iface == ZEPHCORE_IFACE_USB ? "USB" : "BLE");
}
active_iface = ZEPHCORE_IFACE_BLE;
}
static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
@@ -985,12 +1029,28 @@ uint32_t zephcore_ble_get_passkey(void)
enum zephcore_iface zephcore_ble_get_active_iface(void)
{
return active_iface;
k_mutex_lock(&ble_iface_lock, K_FOREVER);
enum zephcore_iface iface = active_iface;
k_mutex_unlock(&ble_iface_lock);
return iface;
}
void zephcore_ble_set_active_iface(enum zephcore_iface iface)
{
k_mutex_lock(&ble_iface_lock, K_FOREVER);
active_iface = iface;
k_mutex_unlock(&ble_iface_lock);
}
bool zephcore_ble_iface_try_claim(enum zephcore_iface who)
{
k_mutex_lock(&ble_iface_lock, K_FOREVER);
bool ok = (active_iface == ZEPHCORE_IFACE_NONE || active_iface == who);
if (ok) {
active_iface = who;
}
k_mutex_unlock(&ble_iface_lock);
return ok;
}
struct k_msgq *zephcore_ble_get_recv_queue(void)
+8 -1
View File
@@ -65,10 +65,17 @@ bool zephcore_ble_is_advertising(void);
void zephcore_ble_set_passkey(uint32_t passkey);
uint32_t zephcore_ble_get_passkey(void);
/** Get/set active interface (BLE/USB coexistence). */
/** Get/set active interface (BLE/USB coexistence). Both are thread-safe —
* active_iface is mutated from the BLE callback thread and the USB workqueue. */
enum zephcore_iface zephcore_ble_get_active_iface(void);
void zephcore_ble_set_active_iface(enum zephcore_iface iface);
/** Atomically claim the active interface for `who` unless the other transport
* already owns it. Succeeds (returns true) if the interface is idle or already
* held by `who`; fails if a different interface is active. Thread-safe use
* this instead of a get-then-set sequence to avoid a check-then-act race. */
bool zephcore_ble_iface_try_claim(enum zephcore_iface who);
/** Get recv/send queues for USB path sharing. */
struct k_msgq *zephcore_ble_get_recv_queue(void);
struct k_msgq *zephcore_ble_get_send_queue(void);
+24 -8
View File
@@ -115,13 +115,17 @@ static void usb_rx_work_fn(struct k_work *work)
* is actually CMD_SEND_CHANNEL_TXT_MSG and meant the USB
* handshake silently dropped the app's first frame.) */
if (payload_len >= 1 && payload[0] == 0x01 /* CMD_APP_START */) {
if (zephcore_ble_get_active_iface() == ZEPHCORE_IFACE_BLE &&
zephcore_ble_is_connected()) {
LOG_INF("usb_rx: CMD_APP_START, disconnecting BLE");
zephcore_ble_disconnect();
/* Atomically claim the interface for USB unless BLE
* already owns it. try_claim succeeds when idle or
* already USB (reconnect) and fails only while a BLE
* session is live, so USB can't steal it and the
* compare-and-set can't race a concurrent BLE claim. */
if (zephcore_ble_iface_try_claim(ZEPHCORE_IFACE_USB)) {
zephcore_ble_set_enabled(false);
LOG_INF("usb_rx: CMD_APP_START → IFACE_USB");
} else {
LOG_INF("usb_rx: CMD_APP_START ignored, BLE is active");
}
zephcore_ble_set_active_iface(ZEPHCORE_IFACE_USB);
LOG_INF("usb_rx: active_iface = IFACE_USB");
}
/* Only process if USB is active interface */
@@ -155,9 +159,21 @@ static void on_dtr_change(bool dtr_active)
return;
}
LOG_INF("usb_dtr: DTR dropped, USB disconnected");
/* While USB owns the interface, BLE claims are rejected (see connected()),
* so this thread is the only writer of active_iface here the get/set
* pair below needs no extra locking beyond the thread-safe accessors. */
if (zephcore_ble_get_active_iface() == ZEPHCORE_IFACE_USB) {
zephcore_ble_set_active_iface(ZEPHCORE_IFACE_NONE);
LOG_INF("usb_dtr: active_iface = IFACE_NONE");
if (zephcore_ble_is_connected()) {
/* BLE client is physically connected — hand off to it. */
zephcore_ble_set_active_iface(ZEPHCORE_IFACE_BLE);
LOG_INF("usb_dtr: → IFACE_BLE (BLE was connected)");
} else {
/* Nobody connected — go idle and restart advertising
* so the phone can find the companion again. */
zephcore_ble_set_active_iface(ZEPHCORE_IFACE_NONE);
zephcore_ble_set_enabled(true);
LOG_INF("usb_dtr: → IFACE_NONE, BLE advertising restarted");
}
}
ring_buf_reset(&usb_ring_buf);
usb_frame_len = 0;
+40
View File
@@ -0,0 +1,40 @@
# Debug Config — opt-in logging and diagnostics.
#
# Production is the default. Pass this conf to get the full debug experience:
#
# west build -b rak4631 zephcore --pristine -- \
# -DEXTRA_CONF_FILE="boards/common/debug.conf"
#
# # With repeater role:
# west build -b rak4631 zephcore --pristine -- \
# -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/debug.conf"
# ========== Core debug features ==========
CONFIG_LOG=y
CONFIG_ASSERT=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096
CONFIG_THREAD_NAME=y
# Halt-and-inspect on fatal faults instead of the production reboot-on-fatal
# (prj.conf sets CONFIG_RESET_ON_FATAL_ERROR=y). A debugger needs the core
# stopped at the fault with a stack dump, not rebooted out from under it.
CONFIG_RESET_ON_FATAL_ERROR=n
# ========== Log tuning ==========
# ZephCore BLE modules at INF level (connection lifecycle, pairing, TX/RX).
CONFIG_ZEPHCORE_BLE_LOG_LEVEL_INF=y
# Deferred logging — non-blocking so BLE/LoRa timing is not disturbed.
CONFIG_LOG_BUFFER_SIZE=8192
CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD=1
CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=2048
# RTT backend only — no UART backend on nRF52.
# UART backend stalls on uart_poll_out() when the USB host disconnects;
# RTT DROP mode discards messages without blocking.
CONFIG_LOG_BACKEND_RTT=y
CONFIG_LOG_BACKEND_RTT_MODE_DROP=y
# Silence noisy subsystems
CONFIG_CFB_LOG_LEVEL_ERR=y
@@ -0,0 +1,45 @@
/*
* Reroute console + shell off USB Serial/JTAG onto uart0 (physical TX/RX).
*
* ESP32-S3 USB Serial/JTAG shares the D+/D- pins with USB OTG and only one
* controller can own the port at a time. Boards that default their console to
* USB Serial/JTAG include this alongside esp32s3_usb_otg.dtsi so that, when
* esp32s3_usb.conf disables USB Serial/JTAG and hands the port to USB OTG, the
* console still has a home. Boards with a dedicated UART console (e.g. Heltec)
* do not need this.
*
* 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
* same pins Heltec uses. Without this the console would point at a disabled,
* un-pinned node and produce no output at all.
*/
#include <zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h>
#include <zephyr/dt-bindings/pinctrl/esp32s3-pinctrl.h>
#include <zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h>
&pinctrl {
uart0_default: uart0_default {
group1 {
pinmux = <UART0_TX_GPIO43>;
output-high;
};
group2 {
pinmux = <UART0_RX_GPIO44>;
bias-pull-up;
};
};
};
&uart0 {
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart0_default>;
pinctrl-names = "default";
};
/ {
chosen {
zephyr,console = &uart0;
zephyr,shell-uart = &uart0;
};
};
+24
View File
@@ -0,0 +1,24 @@
# ESP32-S3 USB CDC-ACM companion support
#
# ESP32-S3 has a DWC2 USB OTG peripheral (snps,dwc2 compatible) that supports
# the Zephyr USB NEXT stack. This conf enables it and turns on the companion
# USB transport on S3 boards. Do NOT use on ESP32 (original) or C3/C6 — those
# chips have no DWC2 controller.
#
# Build with:
# -DEXTRA_CONF_FILE="boards/common/esp32s3_usb.conf"
#
# 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
# zephcore_usbd_init() is compiled out at the #if check.
CONFIG_USB_DEVICE_STACK_NEXT=y
CONFIG_ZEPHCORE_COMPANION_USB=y
CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=n
CONFIG_UART_LINE_CTRL=y
# Disable USB Serial/JTAG so it doesn't fight USB OTG for the D+/D- pins.
# ESP32-S3 has an internal mux — only one controller can own the port at a time.
# With USB companion active, the port IS the companion protocol channel.
CONFIG_ESP_USB_SERIAL_JTAG_ENABLED=n
@@ -0,0 +1,21 @@
/*
* ESP32-S3 USB OTG (DWC2) companion USB transport.
*
* Enables the snps,dwc2 USB OTG controller and attaches a CDC-ACM UART node
* for the binary companion protocol. The DWC2 driver is only compiled when
* CONFIG_USB_DEVICE_STACK_NEXT=y (set by boards/common/esp32s3_usb.conf);
* without that conf this node is inert.
*
* Boards whose default console rides USB Serial/JTAG (shares D+/D- with USB
* OTG) must also reroute the console off the shared pins see
* esp32s3_console_uart0.dtsi.
*/
zephyr_udc0: &usb_otg {
status = "okay";
};
&zephyr_udc0 {
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
-23
View File
@@ -1,23 +0,0 @@
# Logging Tuning — included automatically for debug builds only.
# Prod builds (CONFIG_LOG=n via prod.conf) skip this file entirely,
# avoiding Kconfig warnings from log settings that depend on CONFIG_LOG.
# ZephCore BLE modules at INF level (connection lifecycle, pairing, TX/RX)
# Default level is WRN — this ensures our INF messages come through.
# Avoid DBG level — it causes system workqueue stack overflow.
CONFIG_ZEPHCORE_BLE_LOG_LEVEL_INF=y
# Deferred mode (non-blocking) — buffer/thread config
CONFIG_LOG_BUFFER_SIZE=8192
CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD=1
CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=2048
# Backends
# NOTE: UART backend on nRF52 routes through USB CDC ACM (zephyr,console = &cdc_acm_uart).
# There is no LOG_BACKEND_UART_MODE_DROP in Zephyr — if the USB host disconnects, the log
# processing thread stalls on uart_poll_out(). Disable UART backend on nRF52 to avoid this;
# RTT (below) is the reliable debug path and already configured with drop mode.
CONFIG_LOG_BACKEND_RTT=y
# Suppress noisy subsystem logs
CONFIG_CFB_LOG_LEVEL_ERR=y
+4 -1
View File
@@ -16,10 +16,13 @@ CONFIG_BT_TX_PROCESSOR_STACK_SIZE=2048
# Controller assert handler — without this, a controller assert silently
# freezes the CPU at highest IRQ priority with zero log output.
# Harmless when CONFIG_ASSERT=n, so it stays on for prod and debug.
CONFIG_BT_CTLR_ASSERT_HANDLER=y
# ========== Debug ==========
CONFIG_ASSERT=y
# CONFIG_ASSERT is debug-only (boards/common/debug.conf, opt-in). Setting it
# here would override the prj.conf production default (CONFIG_ASSERT=n) on every
# MG24 build, since this file loads after prj.conf.
# ========== Heap ==========
# Silabs BLE stack requires larger heap (override zephcore_common 2KB default)
+7 -6
View File
@@ -44,11 +44,12 @@ CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE=y
# Silently ignored when QSPI is not present (Kconfig guard: if NORDIC_QSPI_NOR).
CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
# ========== SEGGER RTT (J-Link debug) ==========
# RTT log backend is in boards/common/logging.conf (only included for debug builds).
CONFIG_USE_SEGGER_RTT=y
CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096
# ========== Debug ==========
CONFIG_ASSERT=y
# SEGGER RTT and CONFIG_ASSERT are debug-only and live in boards/common/debug.conf
# (opt-in). Keeping them here would override the production defaults from
# prj.conf (CONFIG_USE_SEGGER_RTT=n, CONFIG_ASSERT=n) on every nRF52 build,
# since this file loads after prj.conf.
#
# BT_CTLR_ASSERT_HANDLER is harmless when CONFIG_ASSERT=n (no RAM/flash cost,
# the handler is simply never invoked) so it stays on for both prod and debug.
CONFIG_BT_CTLR_ASSERT_HANDLER=y
+4 -6
View File
@@ -23,11 +23,9 @@ CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
# Coded PHY — enable in nRF LL controller (host auto-request in zephcore_common.conf)
CONFIG_BT_CTLR_PHY_CODED=y
# ========== SEGGER RTT (J-Link / CMSIS-DAP debug) ==========
CONFIG_LOG_BACKEND_RTT=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096
# ========== Debug ==========
CONFIG_ASSERT=y
# SEGGER RTT and CONFIG_ASSERT are debug-only and live in boards/common/debug.conf
# (opt-in). Keeping them here would override the production defaults from
# prj.conf on every nRF54L build, since this file loads after prj.conf.
# BT_CTLR_ASSERT_HANDLER is harmless when CONFIG_ASSERT=n, so it stays on.
CONFIG_BT_CTLR_ASSERT_HANDLER=y
-22
View File
@@ -1,22 +0,0 @@
# Production Config - Common to ALL boards (Companion & Repeater)
# Build: west build -b <board> zephcore --pristine -- \
# -DEXTRA_CONF_FILE="boards/common/prod.conf"
#
# Disables logging for smaller binary and lower power consumption.
# USB CDC still works for CLI commands on repeaters.
# Disable logging subsystem (saves ~62KB flash, ~2-5mA power)
CONFIG_LOG=n
# Disable asserts (saves flash, removes CMake warning)
CONFIG_ASSERT=n
# Disable SEGGER RTT (saves ~4KB RAM ring buffer + init code)
CONFIG_USE_SEGGER_RTT=n
# Disable thread name strings (saves flash — only useful for debug)
CONFIG_THREAD_NAME=n
# Max contacts: Kconfig default is 350 — fits nRF52840 RAM with ~10% headroom
# and is safe for 100KB ExtraFS. RAM-limited boards (xiao_nrf54l15=450,
# xiao_esp32c3=300) override in their own board.conf. Do not set here.
+1 -5
View File
@@ -29,7 +29,6 @@ CONFIG_PSA_WANT_KEY_TYPE_HMAC=y
# ========== Stack Protection ==========
CONFIG_HW_STACK_PROTECTION=y
CONFIG_THREAD_NAME=y
# ========== Hardware Basics ==========
CONFIG_ADC=y
@@ -195,10 +194,7 @@ CONFIG_INPUT_EVENT_DUMP=n
CONFIG_INPUT_MODE_SYNCHRONOUS=y
# ========== Logging ==========
# RTT log backend: DROP mode (not BLOCK) — when no RTT host is connected the
# buffer is always full; BLOCK mode sleeps 20ms per message with irq_lock held,
# disrupting BLE timing and cascading into buffer exhaustion deadlocks.
CONFIG_LOG_BACKEND_RTT_MODE_DROP=y
# Log backend tuning lives in boards/common/debug.conf (opt-in).
# Silence USB CH9 control-transfer spam (dozens of INF lines during enumeration).
# WRN keeps real USB errors visible.
@@ -101,3 +101,6 @@
/* 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. */
#include "../../common/esp32s3_usb_otg.dtsi"
@@ -101,3 +101,6 @@
/* 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. */
#include "../../common/esp32s3_usb_otg.dtsi"
@@ -109,3 +109,8 @@
/* LittleFS auto-mount — standard /lfs mount point */
#include "../../common/filesystem.dtsi"
/* USB OTG companion transport. station_g2 consoles over USB Serial/JTAG, which
* shares D+/D- with USB OTG, so the console is rerouted to uart0. */
#include "../../common/esp32s3_console_uart0.dtsi"
#include "../../common/esp32s3_usb_otg.dtsi"
@@ -86,3 +86,8 @@
/* LittleFS auto-mount — standard /lfs mount point */
#include "../../common/filesystem.dtsi"
/* USB OTG companion transport. Consoles over USB Serial/JTAG (shares D+/D-
* with USB OTG), so the console is rerouted to uart0. */
#include "../../common/esp32s3_console_uart0.dtsi"
#include "../../common/esp32s3_usb_otg.dtsi"
@@ -7,7 +7,7 @@ CONFIG_BT_DIS_MODEL_NUMBER_STR="Seeed XIAO nRF52840"
CONFIG_ZEPHCORE_SD_FWID=0x0123
# Default debug (logging.conf) sends LOG_* to RTT only. Plain XIAO is usually
# Default debug (debug.conf) sends LOG_* to RTT only. Plain XIAO is usually
# flashed/debugged over USB without an SWD J-Link — enable UART backend so
# LOG_* appears on the CDC ACM serial port (same as zephyr,console).
# RTT remains enabled for J-Link; use DROP mode (see zephcore_common.conf).
+10 -4
View File
@@ -16,10 +16,16 @@ CONFIG_UART_CONSOLE=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_RING_BUFFER=y
# Logging subsystem — enabled by default (prod.conf disables with CONFIG_LOG=n).
# Log tuning (buffer size, backends, etc.) is in boards/common/logging.conf,
# which CMake auto-includes only when prod.conf is NOT active.
CONFIG_LOG=y
# Production by default — add boards/common/debug.conf to enable logging.
CONFIG_LOG=n
CONFIG_ASSERT=n
CONFIG_USE_SEGGER_RTT=n
CONFIG_THREAD_NAME=n
# Reboot on any fatal error (stack overflow, hard fault, etc.) instead of
# spinning forever. Asserts are disabled so they won't reach here, but all
# other fatal paths (k_panic, CPU exceptions) still get a clean reboot.
CONFIG_RESET_ON_FATAL_ERROR=y
# ========== Power Management ==========
# Note: nRF52840 automatically uses WFI (Wait For Interrupt) in idle thread.
+14 -7
View File
@@ -34,7 +34,13 @@ LOG_MODULE_REGISTER(zephcore_main, CONFIG_ZEPHCORE_MAIN_LOG_LEVEL);
#include <ZephyrBLE.h>
#if IS_ENABLED(CONFIG_LOG)
/* The USB CDC companion stack is compiled when either logging needs the CDC
* console (debug builds) or the binary companion transport is explicitly
* enabled (CONFIG_ZEPHCORE_COMPANION_USB, default-y on USB-capable boards). */
#define ZEPHCORE_USB_STACK \
(IS_ENABLED(CONFIG_LOG) || IS_ENABLED(CONFIG_ZEPHCORE_COMPANION_USB))
#if ZEPHCORE_USB_STACK
#include <ZephyrCompanionUSB.h>
#include <ZephyrUSBCDC.h>
#endif
@@ -181,7 +187,7 @@ static void ble_on_connected(void)
/* BLE disconnected callback — clean up state and notify UI */
static void ble_on_disconnected(void)
{
#if IS_ENABLED(CONFIG_LOG)
#if ZEPHCORE_USB_STACK
zephcore_usb_companion_reset_rx();
#endif
#ifdef ZEPHCORE_LORA
@@ -562,8 +568,8 @@ int main(void)
/* USB CDC init up front so the host can enumerate, then block until the
* host opens the port (DTR-high) event-driven via the shared usbd
* message callback. Unplugged 1 s timeout, banner is buffered for any
* later attach. CONFIG_LOG=n prod builds skip the whole stack. */
#if IS_ENABLED(CONFIG_LOG) && DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart) && \
* later attach. */
#if ZEPHCORE_USB_STACK && DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart) && \
!IS_ENABLED(CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT)
zephcore_usbd_init();
zephcore_usbd_wait_dtr(1000);
@@ -780,10 +786,11 @@ int main(void)
zephcore_ble_init(&ble_cbs);
/*
* USB CDC ACM - only enabled when logging is enabled (debug builds).
* Production builds (CONFIG_LOG=n) skip USB entirely, saving ~2-5mA.
* USB CDC ACM companion transport.
* Enabled when logging is on (debug builds) OR when explicitly requested
* via CONFIG_ZEPHCORE_COMPANION_USB (e.g. prod builds on USB-capable boards).
*/
#if IS_ENABLED(CONFIG_LOG)
#if ZEPHCORE_USB_STACK
zephcore_usb_companion_init(&mesh_events, &rx_process_work, MESH_EVENT_BLE_RX,
&zephyr_board);
#endif