Files
ZephCore/zephcore/boards/common/esp32_common.conf
T
2026-10-06 15:57:52 +02:00

159 lines
8.8 KiB
Plaintext

# ESP32 Platform Configuration
# Included by all ESP32-based boards (XIAO ESP32-C3, XIAO ESP32-C6, etc.)
# Only contains ESP32-specific settings — common BLE/Storage/Input is in zephcore_common.conf
#
# Include order: prj.conf → zephcore_common.conf → esp32_common.conf → <board>/board.conf
# ========== BLE: ESP32-specific controller settings ==========
# DLE managed internally by Espressif blob — no CONFIG_BT_CTLR_DATA_LENGTH_MAX
# BLE TX power — +9 dBm, matching stock Arduino MeshCore.
#
# This was previously left unset, on the belief that the Espressif blob managed
# TX power internally. It does not. Zephyr's HCI driver initialises the
# controller with BT_CONTROLLER_INIT_CONFIG_DEFAULT() (hci_esp32.c), whose
# .txpwr_dft comes from CONFIG_ESP32_BT_CTLR_DFT_TX_POWER_LEVEL_EFF — and that
# macro is a #if chain over Zephyr's CONFIG_BT_CTLR_TX_PWR_* symbols with an
# #else /* use 0dB TX power as default */
# fallback. With none of them set the chain fell through and every ESP32 board
# advertised and connected at 0 dBm, while stock Arduino MeshCore inherits the
# Arduino-ESP32 sdkconfig (CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9=y) and runs at
# +9 dBm. That 9 dB deficit is the reported "ZephCore has worse BLE range than
# official firmware" on Heltec V4 — roughly 2.8x the free-space distance.
#
# The symbols ARE settable here: BT_ESP32 selects HAS_BT_CTLR, and upstream
# gates the +9/+12/+15/+18/+21 options on `depends on SOC_FAMILY_ESPRESSIF_ESP32`
# specifically so ESP32 boards can pick one.
#
# Why +9 and not the +20 dBm ceiling the S3/C3/C6 parts can reach: +9 is what
# stock MeshCore runs, it is comfortably inside the EU 2.4 GHz 100 mW (20 dBm)
# EIRP limit, and it is the ONLY level that appears in all three Espressif
# header families — so one line covers every board with no per-board override:
#
# include/esp32c3 (also S3) PLUS_9 -> ESP_PWR_LVL_P9 ceiling +20 dBm
# include/esp32c6 (c5/h2) PLUS_9 -> literal 9 ceiling +20 dBm
# include/esp32 (classic) PLUS_9 -> ESP_PWR_LVL_P9 ceiling +9 dBm
#
# That last row is the trap if anyone raises this later: the classic ESP32
# (ttgo_tbeam, ttgo_lora32) tops out at ESP_PWR_LVL_P9 and its chain has no
# PLUS_12/15/18/21 arm at all, so any higher setting matches nothing there and
# silently drops those two boards back to the 0 dBm `#else` — no warning, no
# build error. Raising this above +9 therefore requires a PLUS_9 override in
# both classic board.conf files.
#
# nRF/nRF54L use CONFIG_BT_CTLR_TX_PWR_PLUS_8 (their own ceiling); +8 is not
# selectable on ESP32 and the ESP32 power enum has no P8 — 3 dB steps only.
CONFIG_BT_CTLR_TX_PWR_PLUS_9=y
# Host privacy: ESP32-only override. Load-bearing for iOS on the Espressif
# controller (Zephyr #84182-class). nRF/MG24 keep privacy OFF.
#
# Root cause pinned 2026-06-15 by firmware BLE/SMP debug capture on shipping
# blob 19f979cfe6 (xiao_esp32s3, real iOS): with privacy OFF the SC pairing
# completes the full passkey + DHKey-check phase, the host hands the controller
# a valid LTK (HCI LTK Request Reply, status 0x00), then the controller fails
# to start link encryption — HCI Disconnect reason 0x3d (MIC failure), Encrypt
# Change status 0x1f. It is a bug in the Espressif controller's privacy-OFF
# Secure-Connections path (closed blob); the host did everything right (nRF runs
# the identical host SMP code and bonds with iOS privacy-OFF fine). Privacy ON
# keeps the controller on its working privacy-enabled SC path.
#
# Android "connect from app" is NOT sacrificed: ZephyrBLE advertises with
# BT_LE_ADV_OPT_USE_IDENTITY, so even with privacy ON we expose the stable
# identity address (no RPA) — the thing the Android companion needs. HW-
# confirmed: iOS pairs + syncs, normal disconnect 0x13.
CONFIG_BT_PRIVACY=y
# BLE thread stacks — ESP32 software BLE controller needs larger stacks.
# Zephyr 2026-Q1 added a synchronous sc_store() on the RX WQ in the
# identity-resolved path (commit 2c6c80ddf65) which pushes the LittleFS
# settings write onto the SMP callback chain. Default 2048 overflowed.
# The RX WQ keeps 4096: that path (a phone pairing with a resolvable private
# address) is not reproducible on the bench.
#
# TX processor: measured 2026-09-24 on a XIAO ESP32-S3 companion with WiFi
# (CONFIG_ZEPHCORE_MEM_STATS, devdocs/tools/mem_load.py: fresh pairing, bonded
# reconnects, protocol golden over BLE and TCP, bulk contact dump), peak 724 B,
# so 2048 (2.8x). Was 4096.
# The controller task (ESP32_BT_CONTROLLER_STACK_SIZE, default 4096) is not set
# here: classic ESP32 (BTDM) and the C6 controller were not measured and keep
# the default. S3 and C3 trim it in esp32c3s3_common.conf, where the symbol
# became the real stack size with hal_espressif b16851b3c2 (2026-10-06).
CONFIG_BT_TX_PROCESSOR_STACK_SIZE=2048
CONFIG_BT_RX_STACK_SIZE=4096
# Stack-overflow detection — xtensa has no MPU stack guard in Zephyr, so
# use the software sentinel. ARM boards rely on MPU_STACK_GUARD (already
# on via HW_STACK_PROTECTION) which is incompatible with this symbol.
CONFIG_STACK_SENTINEL=y
# BLE TX buffers — the Espressif BLE controller blob bursts more aggressively
# than the nRF softdevice and will deadlock the system workqueue if ACL TX
# buffers run dry (bt_hci_cmd_alloc(K_FOREVER) blocks the cooperative syswq).
# EVT_RX must strictly exceed ACL_TX (enforced by BUILD_ASSERT in buf.h).
CONFIG_BT_BUF_ACL_TX_COUNT=12
CONFIG_BT_L2CAP_TX_BUF_COUNT=12
# (BT_CONN_TX_MAX=12 was removed in Zephyr 4.5; pending TX with a callback now
# always follows BT_BUF_ACL_TX_COUNT, which is 12 above -- same limit.)
CONFIG_BT_BUF_EVT_RX_COUNT=14
# BLE controller link-layer encryption — Zephyr 4.4.1 (commit 7f01467, "align
# esp32 controller knobs") re-gated this vendor default from unconditional
# `default y` to `default y if BT_CTLR_LE_ENC`. ESP32 BLE uses the EXTERNAL
# Espressif controller over HCI (BT_ESP32=y, BT_CTLR unset), so that gate is
# never satisfied -> the controller's LE encryption gets compiled out while host
# BT_SMP stays on. The controller then asserts (ke_event.c) the moment a peer
# begins pairing: advertising works, connect never completes (GH #34). Restore
# the pre-4.4.1 default. (Classic ESP32 / S3 / C3 controller; the C2/C5/C6/H2
# controller uses ESP32_BT_LE_SECURITY_ENABLE instead — set in those board.conf.)
CONFIG_ESP32_BT_CTLR_LE_SECURITY_ENABLE=y
# ========== Heap ==========
# ESP32 BLE stack requires larger heap (override zephcore_common 2KB default).
#
# 32768 was NOT enough and failed non-obviously. The Espressif controller
# allocates its exchange memory through esp_bt_malloc_func(), which the Zephyr
# port maps to k_malloc() (esp_heap_adapter.h, CONFIG_ESP_BT_HEAP_SYSTEM=y) —
# i.e. straight out of this pool. esp_bt_controller_init() asks for 0x7800 =
# 30720 bytes in ONE allocation: 93.75% of a 32 KB pool, leaving 2 KB for block
# overhead and every other k_malloc user that ran before bt_enable(). Boards
# that allocated little before BLE init happened to fit; ThinkNode M9 (display +
# colour overlay, STC8H keypad, LR1110) did not, and the blob asserted inside
# its own allocator instead of returning ESP_ERR_NO_MEM:
#
# BLE assert emi.c 164, param 00000000 00007800 <- (NULL, requested size)
#
# Zephyr's own driver anticipates this and prints "Consider increasing
# CONFIG_HEAP_MEM_POOL_SIZE" (drivers/bluetooth/hci/hci_esp32.c) — but only on
# the graceful path the blob does not take. Every ESP32 board was one
# allocation away from the same failure, so this is raised platform-wide.
#
# Headroom verified by build on all 12 shipped ESP32 boards: the S3/C3/C6 boards
# have 66-135 KB free internal DRAM and absorb this easily. ttgo_tbeam is the
# sole exception (99.45% DRAM, 768 B free) and overrides it back in its
# board.conf — see the note there.
CONFIG_HEAP_MEM_POOL_SIZE=65536
# ========== Flash ==========
# 4MB is standard for XIAO/LilyGo RISC-V boards.
# Station G2 (16MB) overrides in board.conf.
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
# ========== BLE bonds: dedicated NVS partition (not /lfs) ==========
# Bonds live in their own `storage_partition` NVS region (defined per board in
# board.overlay), isolated from the /lfs LittleFS volume that holds identity/
# prefs/contacts. This overrides the file-backed default in zephcore_common.conf
# (loaded earlier): a busy bond store can no longer corrupt /lfs. Every ESP32
# board.overlay defines a storage_partition, so this is safe platform-wide.
CONFIG_SETTINGS_FILE=n
CONFIG_NVS=y
CONFIG_SETTINGS_NVS=y
# ========== Debug ==========
# CONFIG_ASSERT disabled for ESP32: Espressif's closed-source BLE controller
# blob leaves IRQs in a state that triggers false "Context switching while
# holding lock!" assertions in kswap.h. The BLE stack works correctly — the
# blob manages its own IRQ state internally. nRF52/nRF54L boards keep asserts
# via their platform configs; ESP32 relies on logging for debug.
# CONFIG_ASSERT=n (Zephyr default)