espressif: force-link init_coexist after IDF v6.0-dev move
IDF commit ea84e9118d5 ("fix(esp_coex): move coex init from esp_system
to esp_coex component", 2026-03-10, between v6.0-dev-5454 and current
submodule HEAD v6.0-dev-5728) relocates the ESP_SYSTEM_INIT_FN entry
init_coexist out of components/esp_system/startup_funcs.c and into
components/esp_coex/src/coexist.c. It also adds an esp_coex_init_include_func
hook and `target_link_libraries(... INTERFACE "-u esp_coex_init_include_func")`
to esp_coex/CMakeLists.txt to force the linker to retain the new
compilation unit.
CircuitPython's ports/espressif/Makefile does its own final link
(--start-group ... --end-group around the expanded .a list) and never
consumes the INTERFACE link options that CMake emits for esp_coex, so
the hook is dropped. With coexist.c.obj absent from the link,
init_coexist never runs, esp_coex_adapter_register() and coex_pre_init()
are skipped, and the ROM-side coex_schm_env_ptr stays NULL. The first
wifi-init call to coex_schm_register_callback then dereferences
NULL+0x10, panicking with a Load access fault (MEPC in ROM, MCAUSE=5,
MTVAL=0x10, RA inside coex_schm_register_callback).
Observed on espressif_esp32c6_devkitm_1_n4 during boot, right after
`wifi:Init dynamic rx buffer num: 32`. Pre-IDF6 builds (e.g. the older
S3 build still on IDF5) link init_coexist transitively through
libesp_system.a and don't hit this.
Add `-u esp_coex_init_include_func` to REGISTRATION_FUNCTIONS so our
explicit -u list matches what esp_coex's CMakeLists.txt expects. Gate
on CIRCUITPY_WIFI and skip esp32s2/esp32p4 because IDF's Kconfig only
compiles coexist.c when ESP_COEX_SW_COEXIST_ENABLE is set
((WIFI && BT) || (WIFI && 802.15.4) || (BT && 802.15.4)); on those
targets the symbol does not exist and the -u would fail to resolve.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> S
Scott Shawcroft committed
17615f7c2c7c5b59f30452cf46e61e12acbce14c
Parent: d293209