- LoRaRadioBase -> LoRaRadio (final); SX126x/SX127x/LR1110/LR2021Radio
replaced by const LoRaRadioOps tables (radio_ops_<family>.cpp), one
linked per build; mains construct the radio in one line
- lr20xx: vendored Semtech SDK + HAL moved beside the driver (no app-tree
sources), DIO1 handler split (CCN 52 -> 10), zc_lora_timing.h adopted,
dead exports removed, header rewritten, comment diet (image-identical)
- semtech,lr2021 uses the lr1110 property names (irq-gpios, tcxo-voltage,
rfsw-*), compiled config byte-identical
- correct the stale "LR2021 is not CAD-probed" claim
- compile Semtech lr11xx_driver v2.7.0 from modules/lib/lora-basics-modem
(driver layer only) instead of the vendored fork; HAL moves next to the
driver (+abort_blocking_cmd); driver no longer builds app-tree sources
- split lr11xx_dio1_work_handler into per-IRQ helpers (CCN 46 -> 12)
- zc_lora_timing.h: preamble grace, payload deadline, 24-bit saturation,
shared with sx126x (patch 0003) and host-tested; sx126x CAD_RX Rx bound
now saturates instead of wrapping (SF12/BW7.81)
- semtech,lr1110 binding includes upstream lr11xx-base; boards use
upstream property names (irq-gpios, tcxo-voltage, rfsw-*)
- drop dead lr11xx_get_random/get_chip_temp_c; correct the IRQ-clear
invariant wording; comment diet (image-identical)
- CadController (stats, window, re-anchor, visits, staircase, safety,
starvation relax) and NoiseFloorEstimator split out of LoRaRadioBase
behind a 4-call CadHw interface; Zephyr-free, host unit tests added
- prefs mandatory: setPrefs() before begin(), LoRaConfig fallbacks and the
companion/observer placeholder prefs removed; LoRaConfig is the one
defaults source (invalid-prefs fallback now uses the board TX default)
- TX-wait thread stack owned by the base; reconfigureWithParams removed
- driver extension headers on the public include path
(zephyr/drivers/lora/*.h); patch 0003 include updated
- comment diet (image-identical); rationale moved to devdocs LLD 03
- Mesh, Dispatcher, Packet, packet pool and the core headers rebuilt from
Arduino MeshCore's text; ZephCore changes re-applied, each fenced
`// ZEPHCORE:` (diff vs upstream: 4540 -> 1147 lines)
- upstream header layout; MainBoard gains handleCommand/loop and the other
upstream members; RNG::nextInt back in Utils.cpp
- packet logging moved to the roles' log hooks (helpers/PacketLog.h)
- zero-hop direct ACKs deduplicated and length-checked as upstream
- RadioIncludes.h -> src/, LoRaConfig.h -> helpers/
- .editorconfig: shared files keep upstream formatting
Verified: 10 role builds, per-function disassembly review, bench DM/ACK
regression (T1000-E, Wio L1, XIAO S3 on 1.17.4) incl. via live repeater.
TX_WAIT_THREAD_STACK_SIZE was 1024 bytes, shared by every radio
adapter. On Xtensa (all ESP32/S3 boards) the windowed ABI needs ~3x
the stack of Cortex-M for the same code — Zephyr's own Kconfig
defaults reflect this (IDLE_STACK_SIZE: 1024 if XTENSA vs 320 ARM).
Measured peak usage on Heltec V4 (immediate-mode logging, full TX
cycle including startReceive/lora_config): 1252 bytes — already past
the old 1024 limit. The overflow corrupts the exception frame and
parks CPU0 in _DoubleExceptionVector (LoadProhibited @0x2c), a silent
total freeze at boot. Confirmed via the S3 built-in USB-JTAG:
current thread at crash = lora_tx_wait.
2048 gives ~39% headroom over the measured worst case.