View this page on MeshCore Docs.
Other-board radio2 fast switching, 23 October 2026
Status: PARTIAL. Buffered SPI improved switching, but the 500 us maximum objective remains unmet. XIAO's witnessed RF test missed one packet. MeshTower and Tag passed their finite 200-packet RF tests. Final-source XIAO and Tag Companion command and Bluetooth tests passed while both receive profiles remained active. XIAO was restored to the final Repeater image. The RAK Full build correction and its capacity checks passed.
This campaign covers five baseline/DUT boards, additional fixed witnesses, and three explicitly enabled nRF52 fast-SPI candidates. It does not qualify all 13 radios, CPU sleep, electrical power consumption, or every firmware role. MeshPocket and SenseCAP Indicator are excluded. The new XIAO, Tag and MeshTower fast transports remain opt-in; these results do not promote them to production defaults.
Candidate transport scope
| Board | Tested role | Explicit candidate | Controller ownership |
|---|---|---|---|
| Seeed XIAO nRF52 | Repeater, then Full Companion | Buffered 8 MHz on SPIM2 | Global SPI remapped together with its driver; QSPI flash remains separate |
| RAK WisMesh Tag | Full Companion | Buffered 8 MHz on SPIM1 | Dedicated audited radio mapping |
| Heltec MeshTower V2 SD | Full Repeater with SD and no external sensors | Buffered 8 MHz radio on SPIM1 | SD remains on SPI1/SPIM2; SD features retained |
| RAK4631 | Existing Repeater baseline | Prior 2 MHz byte transfers retained | Other peripherals can own the proposed alternate controller |
| Heltec T096 | Existing Full Companion baseline | Prior 2 MHz byte transfers retained | Display/controller ownership still needs a separate safe mapping |
Retained ELF inspection verifies the actual SPI controller, buffered transfer, 8 MHz descriptor and absence of the global protected SPIM3 anomaly-198 workaround in the candidate images. These proofs establish linked behavior; they do not replace the physical tests below. See also the separate RAK3401 campaign.
Timing observations
Every short timing observation used these same two RX profiles:
| Profile | Frequency, MHz | BW, kHz | SF | CR | Preamble, symbols |
|---|---|---|---|---|---|
| Primary | 917 | 62.5 | 7 | 5 | 32 |
| Secondary | 918 | 500 | 5 | 5 | 200 |
The measurements cover the complete RX-to-RX switch path, including admission, standby, changed modem parameters and restarting receive. They are not bare PLL-lock measurements. Each short window lasted 20 seconds and reached four self-test samples in each direction; the firmware still labelled the timing self-test pending. The displayed guarded budgets below were provisional and include a rounded-up 10% margin. Larger samples occurred during longer RF campaigns, so the short maxima are not worst-case guarantees.
| Original installed board / role | Source | Maximum, us | Provisional budget, us |
|---|---|---|---|
| XIAO Repeater | 8b5660b0 |
916 | 1008 |
| RAK4631 Repeater | adb11e7b |
916 | 1008 |
| Tag Full Companion | 08650f64 |
947 | 1042 |
| T096 Full Companion | 4773ac42 |
947 | 1042 |
| MeshTower Full Repeater SD | ebb59d48 |
947 | 1042 |
RAK4631, Tag and T096 retained pre-existing core flags of 8 during those old baseline observations; MeshTower retained 2. No new flags appeared in those windows. The new XIAO, Tag and MeshTower candidate observations began and ended with core flags zero. Baseline timing completion is not a full health pass.
| Candidate observation | Source | Transport | Maximum, us | Provisional budget, us |
|---|---|---|---|---|
| XIAO matched baseline | 1b9fcf2a |
2 MHz byte transfers, SPIM3 | 855 | 941 |
| XIAO fast candidate | 1b9fcf2a |
Buffered 8 MHz, SPIM2 | 550 | 605 |
| Tag fast candidate | 61a536c6 |
Buffered 8 MHz, SPIM1 | 580 | 638 |
| MeshTower fast candidate | 61a536c6 |
Buffered 8 MHz, SPIM1 | 550 | 605 |
XIAO's 855-to-550 us comparison uses the same source checkpoint and isolates the transport/controller configuration change. Tag's 947-to-580 us and MeshTower's 947-to-550 us comparisons also cross older source checkpoints; their improvements cannot be attributed solely to SPI speed. None meets the requested 500 us sampled maximum.
Witnessed RF delivery
Each campaign sent 200 unique, one-shot physical test packets: 100 on each profile, with one sender and two fixed-profile witnesses. There was no retransmission of a test packet. The scanner and fixed witness were checked against the same packet ledger, and an offline audit reconstructed delivery and cleanup from retained receipts.
| Scanner / source | Primary received / sent | Secondary received / sent | Fixed primary witness | Fixed secondary witness | Delivery result |
|---|---|---|---|---|---|
XIAO Repeater, 1b9fcf2a |
99 / 100 | 100 / 100 | 100 / 100 | 100 / 100 | Failed |
MeshTower Full Repeater SD, 61a536c6 |
100 / 100 | 100 / 100 | 100 / 100 | 100 / 100 | Passed this finite run |
Tag Full Companion, 807343de |
100 / 100 | 100 / 100 | 100 / 100 | 100 / 100 | Passed this finite run |
All three runs recorded zero new scanner receive errors, core flags,
radio-driver recovery attempts, switch errors, duplicate test packets,
wrong-profile receipts or collector drops. Uptime progressed without a detected
reboot. The longer XIAO and MeshTower runs reported a 673 us guarded switch budget both before
and after RF, larger than their short-window budgets. Tag retained a 638 us
guarded budget before and after RF. Its pre-existing radio-driver attempt
counters remained soft=1,hard=0. Settings for all four participants and the
gateway service were restored.
The XIAO missing primary packet remains an unresolved failure despite its fixed witness receiving all 100. MeshTower's delivery pass does not satisfy the separate speed objective or prove loss-free operation beyond this finite run. These RF runs do not qualify CPU sleep or Bluetooth.
Bluetooth and SD compatibility
On Tag Full Companion from 61a536c6, all three bonded Bluetooth NUS sessions
passed, each held for at least 30 seconds with MTU 247. Public identity,
complete version, device information and the original Bluetooth getters
matched the USB peer. Dual-profile switching continued, core flags remained
zero, and the temporary leases and saved settings were restored. This receipt
precedes the new diagnostic getters in 807343de; final-source results are
recorded separately below.
MeshTower from 61a536c6 passed a separate SD compatibility test while radio2
remained enabled and its switch counter advanced. The existing archive-cache
command physically wrote a four-byte marker, acknowledged file and card
synchronization, and directory pagination verified the marker's path and size.
The original cache policy, other directory entries and radio settings were
restored. This is marker write/sync plus directory metadata verification;
it is not a byte-content readback or a full SD payload I/O qualification.
Enabling the original cache policy can emit normal OTA metadata queries; the
test did not stage, apply or reset firmware.
The final MeshTower 807343de image passed the same bounded marker/directory
check, plus the newly shared SD history, history selectors, alias and free-space
getters. Original cache policy and radio leases were restored. This adds
command coverage without extending the SD payload/readback claim.
Final diagnostics checkpoint
Source 807343de8d77adc4f61dbb260bdb499c04fa0211 adds the shared Companion
power, hardware-watchdog, RXPS-watchdog, RXEN, CAD and statistics diagnostics,
and shares the guarded SD command path. Focused native tests execute the real
helpers and relevant radio admission, rollback and reset paths, including
sanitizer checks. These tests cover nonzero statistics reset semantics that
were not observably exercised by zero counters on the physical XIAO.
The final XIAO Full Companion was installed through application-only DFU;
its body is 7EC2F4BF2A80CFC1, and no fallback was used. Its first radio setup
and post-preference-load setup are constrained to 917 MHz by a narrow,
default-off test-image guard. Its saved Companion frequency is then explicitly
written to 917 MHz. This prevents old role-specific preferences from briefly
returning the radio to an excluded frequency during the role change.
XIAO's source/body-bound new-command USB test passed, including RXEN changes
and restoration with one profile and with RXPS suspended by radio2. Cleanup
and gateway ownership checks passed. A physical nonzero
clear stats reset was not observed; native fault-injection coverage provides
that check. XIAO had one pre-existing soft RXPS-watchdog attempt and zero
hard attempts; all three USB reads retained soft=1,hard=0, including after
clear stats. No new attempt was observed in this command campaign. The
first new-source Bluetooth wrapper stopped in preflight because it incorrectly
required zero history. A later trial also established that the historical USB
reference was stale: XIAO's soft count had increased from 1 to 3 before the
measured Bluetooth window. The cause of that pretrial increase is unexplained.
The final controller preserved those receipts and bound an additional fresh,
hashed USB-before snapshot; it did not reset counters or the device.
Retained Full ELF SHA-256 values for the final checkpoint are:
| Artifact | ELF SHA-256 |
|---|---|
| XIAO Full Companion | 3324de701d8159bbf626e08ea1adfc91634db6191ace4d0898fc76e513884cb4 |
| XIAO Full Repeater | 2266a1d669e96c70f8e5dd695613a6eb621f80c3422d17da37801d62cb970786 |
| Tag Full Companion | be9c73e78b073b8942a0aa84b25dd08c49d6e6cf30fb606c0e18f12988d11a12 |
| MeshTower Full Repeater SD | 785ee10d5c6fd67a728fd3126c8daf03b435b0dfe2d383582d4aaa48d605bab0 |
Their memory-capacity and relevant controller proofs passed. Tag's
application-only final install passed with body 6115C6802E1AFC50 and no
fallback. Its USB command test passed, including the correct unsupported RXEN
capability response; nonzero physical statistics reset was not observed. The
final MeshTower install also passed without fallback, with body
E5324C388E987A8E. XIAO was restored by application-only DFU to the final
Repeater image with body 83C09F44589332D6, without fallback. Two fresh
checks confirmed its Repeater role, unchanged identity and retained 917 MHz
settings. Its original Repeater settings and gateway ownership were preserved.
Final XIAO and Tag Full Companion each passed three additional bonded NUS sessions of at least 30 seconds at MTU 247. Every session verified all original identity/version/Bluetooth checks and ten new read-only diagnostic getters. The latter covered bootloader metadata, RXEN capability, power-management support/source/boot voltage, actual system-watchdog state, power, both CAD aliases and radio-driver recovery attempts. Dual-profile switching continued, core flags stayed zero, and settings/leases were restored.
XIAO held its fresh soft=3,hard=0 baseline unchanged through arming, all
Bluetooth sessions and final USB cleanup. Tag held soft=1,hard=0; its earlier
USB diagnostic reference had been soft=0,hard=0, so it too had a pretrial
increase whose cause is not established. These counters include continuous-RX
and liveness recovery attempts. They do not count CPU watchdog resets or
necessarily successful recoveries. Passing the measured windows does not
explain or erase the earlier increases.
A separate RAK4631 Full Companion build initially exceeded the linker's text
region by 524 bytes. Once linking succeeded, the complete OTA image check also
counted initialized data and its trailer. Source 0cdf6f9a passes all build,
capability, RAM and OTA image gates: the application is 712,684 of 712,704 bytes,
leaving 20 bytes. Runtime capacity is 81,220 bytes against 72,528 required.
The tight flash margin remains specific to this exact build.
The size fix retains every help byte, feature, contact/channel limit and storage boundary. Compile-time LZSS stores 4,222 help bytes in 2,159 bytes; its streaming decoder uses a 2 KiB history and 64-byte output chunk without a heap allocation. Only the isolated packing source uses C++17; the application and framework keep C++11. Native checks cover byte-for-byte output across four profiles, mixed-language linkage, overlap, ring wrap, malformed references and short/zero writes. Extracting and decoding the actual linked ELF reproduces the retained original help exactly; the uncompressed copy is absent. This size-only follow-up was not flashed for another hardware campaign.
After merging remote fd47fe0b1, source 86ef1e89 passed the same canonical
build and linked-help proof with the same application size and RAM capacity.
The incoming display and dynamic-WiFi regression suites also passed. The
hardware receipts above remain bound to their explicitly recorded images.
Remaining work
- Resolve XIAO's witnessed missing packet and the unmet 500 us maximum goal.
- Investigate the unexplained pretrial radio-driver recovery attempts.
- Audit controller ownership before extending buffered SPI to RAK4631 or T096.
At this checkpoint, production-default promotion, all-board release qualification and CPU-sleep qualification remained open. The machine-readable sanitized results retain separate delivery, speed, compatibility and build states.
Saved controls follow-up
Code 4c0f2acf adds saved radio.fast controls across the shared CLI roles.
Supported features default on, including boards awaiting physical testing.
Individual controls cover SPI speed, buffered transfers, batched modulation,
warm receive ownership, FS, packet, IQ and modem reuse. Plain SX1262 board
transports now default to 8 MHz byte transfers. Compiled buffered transports
can select byte transfers without moving their SPI controller. Indicator keeps
its existing transport and compile-time exclusions.
The wired RAK3401 passed 19 control cases and two software-reboot persistence cases on the final Full repeater. Twenty-one read-only SWD samples confirmed the SPIM2 frequency register at 2, 4 and 8 MHz. Both profiles continued switching, core errors stayed zero, and no new RXPS-watchdog attempts were observed. Its original settings and gateway service were restored. The application update preserved its bootloader. These checks cover configuration, startup persistence and switching liveness; packet delivery, BLE, CPU sleep and the earlier XIAO loss remain separate qualifications.
Sequential builds passed for V4 Full Companion, RAK4631 Full Companion, RAK3401 Full and Reduced OTA repeaters, and the standard T1000 BLE Companion. The RAK4631 application including EndF is 711,400 of 712,704 bytes, leaving 1,304 bytes. Runtime RAM available is 81,140 bytes against 72,528 required.
To retain Full features, the offline Reader now uses a word dictionary before DEFLATE. All 879 verses retain their exact wording; its pinned source and 4 KiB scratch capacity are unchanged. Data and all dictionary/index tables total 33,399 bytes, saving 5,086 bytes. Corpus, malformed-token, C++11 compatibility, sanitizer and ARM stack checks passed. The merged Meshtext retry-limit and beacon tests also passed.
The saved-control results record the build sizes and physical test scope. Command details are in Saved switching controls.