Record fast-switch measurements and remaining RAK3401 delivery failures

This commit is contained in:
mikecarper committed 2026-10-23 04:30:58 -07:00
1 parent aa480ae79e
commit 9d02b74e29
3 files changed
+353

No files matched your search

@@ -0,0 +1,166 @@
<!-- meshcore-hosted-doc-link:start -->
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/test-results/rak3401_radio2_fast_switch_2026-10-23/">View this page on MeshCore Docs</a>.</p>
<!-- meshcore-hosted-doc-link:end -->
# RAK3401 radio2 fast switching, 23 October 2026
Status: **PARTIAL. Switching improved; the 500 us maximum goal is not met.**
The production candidate retains buffered 8 MHz SPI on SPI1/SPIM2. Private
16 MHz experiments failed radio initialization or returned incorrect radio
readback. They are not production defaults. **Fresh witnessed RF delivery
qualification failed: the scanner received 195 of 200 test packets.**
## Timing checkpoints
These are hardware measurements of the RX-to-RX profile-switch path, including
admission, standby, changed radio parameters and restarting receive. They are
not bare PLL-lock times. The production budget uses the sampled maximum plus
a rounded-up 10% margin; it is not a guarantee against a larger future sample.
| Source | Change | Sampled maximum, us | Guarded budget, us |
| --- | --- | ---: | ---: |
| `adb11e7b` | Original 2 MHz, byte-at-a-time SPI | 1069 | 1176 |
| `99979655` | Buffered 2 MHz SPI | 855 | 941 |
| `258b37df` | Buffered 2 MHz plus modem/IQ caches | 702 | 773 |
| `b8b7880a` | Buffered 8 MHz plus caches | 550 | 605 |
| `1b97c089a` | Normal 8 MHz production image, longer RF campaign | 611 | 673 |
The ordinary nRF52 switch budget uses the 32,768 Hz RTC2 clock, approximately
30.52 us per tick. A separate 64 MHz DWT instrumentation build from
`2629c158` captured 586 successful switches in each direction:
| Direction | Minimum, us | Mean, us | Maximum, us |
| --- | ---: | ---: | ---: |
| Primary to secondary | 410 | 415.643 | 555 |
| Secondary to primary | 409 | 414.614 | 550 |
Both directions recorded zero busy admissions and zero failed switches in
that capture. DWT stage counters, later interrupt observers and experimental
guards add work. Times from differently instrumented builds are not directly
comparable with each other or with production timing. A mean below 500 us
does not satisfy the requested maximum.
## Why 16 MHz is not enabled
The pure Repeater failed startup at 16 MHz on SPIM3 with RXDELAY settings
0, 1 and 2. Read-only SWD captures showed completed SPI frames, SoftDevice
disabled, and no observed fault-register evidence in those snapshots. This
does not support blaming those particular failures on Bluetooth or USB
enumeration. It also does not establish a hard clock limit for the pins.
A narrower diagnostic initialized the radio successfully at 8 MHz, then
issued 16 read-only GetPacketType commands at each of 8, 16 and 8 MHz. No
radio writes or resets occurred between phases. The controller, pins and
explicit anomaly-198 workaround remained the same; the per-frame SoftDevice
safety check remained active.
| RXDELAY | Initial 8 MHz correct / 16 | 16 MHz correct / 16 | Restored 8 MHz correct / 16 |
| ---: | ---: | ---: | ---: |
| 2 | 16 | 4 | 16 |
| 1 | 16 | 3 | 16 |
| 0 | 16 | 2 | 16 |
The first two raw response bytes, `A2,A2`, are normal for these reads. The
failure is the final packet-type byte differing from the expected LoRa value
`01`. Restoring 8 MHz restored all 16 correct reads in every trial. This
isolates a reproducible fast-read problem after successful initialization;
it does not identify whether its cause is signal timing, the controller or
another part of the SPI path. No 16 MHz shipping claim is made.
## Experimental scheduling and interrupt controls
Task-priority elevation, bounded USB interrupt deferral and their explicitly
enabled combination were slower in the measured builds. All remain private,
default-off HIL options. The combined experiment did not achieve the 500 us
maximum goal.
One combined worst-hop capture reported zero activity for all seven observed
interrupt/scheduler sources. Shared TWI0/SPIM0 coverage was then added in
`aa480ae79`; the exact linked vectors and scheduler call were verified before
the physical test. Both directions completed 591 successful switches with no
failed switches; the reverse direction also recorded 12 busy admissions.
The slowest forward switch took 659.109 us and
again recorded zero activity, now across all eight observed sources. The
reverse maximum was 575.234 us. SysTick ENABLE and TICKINT were both off when
read after stopping the test. These observations rule out attribution to
the recorded sources for that forward hop, without proving a particular
memory, peripheral or CPU-stall cause. Observer overhead and inclusive handler
timing also prevent treating these counters as a complete or additive
explanation of elapsed time.
The observer excludes architectural exception paths and the experiment's
RTC2 deadline handler; the USB guard recorded no deadline expiry. The retained
worst sample is selected by integer microseconds, so equal-microsecond ties
can differ in raw cycles.
## Production scope and validation
The RAK3401 production path uses buffered SPI1/SPIM2 at 8 MHz. It does not
enable the global nrfx SPIM3 anomaly-198 workaround, which is unsafe with an
enabled SoftDevice. The newly buffered, unqualified nRF default-SPI/SPIM3
constructor rollout was restored to its prior defaults in `4e513b19d`.
Previously buffered LR1110 targets retain their prior constructors. Shared
cache improvements and the ESP32/RP2040 improvements remain. SenseCAP
Indicator is excluded, and MeshPocket has not been physically tested in this
campaign.
Focused native checks passed for buffered transfers and constructor/bus
selection, cache invalidation, CPU-clock policy transitions, timing captures,
SoftDevice refusal, read-probe timeout/restoration/recovery decisions, and
default-off experiment gates. Relevant native fixtures execute the actual
helpers; sanitizer checks cover the diagnostic paths. These checks do not
replace hardware qualification.
Cross-architecture build receipts include RAK3401, RAK4631, ThinkNode M4,
Heltec V2/V3, ESP32-C6 and Pico W targets. They cover campaign checkpoints,
not every board, firmware role or final-source image. The raw
`Station_G2_repeater` PlatformIO target exceeded its default 1,310,720-byte
application limit both at the baseline and after the changes; that
pre-existing overflow remains a separate build limitation. No all-builds or
all-boards release qualification is claimed here.
## Fresh witnessed RF test
The normal production image from `1b97c089a` was installed and its running
body hash matched the retained Full ELF/package. Two fixed receivers witnessed
the same 200 fresh, one-shot test packets, with no test-packet retransmission.
The settled recommendation was 32/192 symbols; the test selected 32/200.
| Receiver | Primary received / sent | Secondary received / sent |
| --- | ---: | ---: |
| RAK3401 scanning both profiles | 96 / 100 | 99 / 100 |
| Fixed primary witness | 100 / 100 | - |
| Fixed secondary witness | - | 100 / 100 |
There were no duplicate test packets, wrong-profile receipts, collector drops,
new core error flags, watchdog recoveries or switch-command errors. The RAK
recorded one additional receive error. The five-minute nonhalting CPU-status
capture passed its integrity gates: 27,134 samples, maximum gap 17 ms, no CPU
halt/debug enable, reset or lockup in the observation window. USB was active,
so this does not qualify CPU sleep or electrical power consumption.
The gateway and RAK settings were restored. The sender's original transmit
power restoration initially returned a radio-busy error; a separate settings-
only cleanup continuation was required. The original failed receipt was
preserved. Packet delivery qualification and the 500 us goal both remain
failed; an offline audit independently reproduced the same five missing
packets.
## Remaining work
The [earlier witnessed RF run](rak3401_radio2_sf5_bw500_p384_2026-10-23.md)
lost three primary packets while its fixed witness received all 100. A
[recommended-preamble run](rak3401_radio2_recommended_preamble_2026-10-23.md)
also had scanner losses. The new test confirms that scanner packet loss
remains after these speed improvements. Faster switching alone has not fixed
delivery.
The additional interrupt observer has completed its physical test. The normal
production image was built separately from `1b97c089a`, with all HIL helpers
absent and SPI1/SPIM2 selected; the later observer change affects HIL only.
Fresh witnessed RF testing of that production image is complete and failed.
The remaining work is to fix packet loss, explain and reduce the remaining
long switching intervals, and requalify the changed implementation. The
500 us maximum remains unmet.
Machine-readable [sanitized results](rak3401_radio2_fast_switch_2026-10-23.safe.json)
record the same scope and failures.
@@ -0,0 +1,183 @@
{
"schema": 1,
"date": "2026-10-23",
"board": "RAK3401 with external SX1262",
"role": "repeater",
"status": "partial",
"maximum_switch_goal_us": 500,
"performance_goal_passed": false,
"production_source": "1b97c089a735ebe5ddb2f39937c685994f85850e",
"production": {
"spi_controller": "SPI1/SPIM2",
"spi_hz": 8000000,
"buffered_transfers": true,
"iq_modem_cache": true,
"experimental_priority_guard": false,
"experimental_usb_irq_guard": false,
"global_spim3_anomaly198_workaround": false,
"hil_symbols_present": false
},
"profiles": {
"primary": {
"frequency_mhz": 917,
"bandwidth_khz": 62.5,
"sf": 7,
"cr": 5,
"preamble": 32
},
"secondary": {
"frequency_mhz": 918,
"bandwidth_khz": 500,
"sf": 5,
"cr": 5,
"preamble": 200
}
},
"timing_checkpoints": [
{
"source": "adb11e7b",
"sampled_maximum_us": 1069,
"guarded_budget_us": 1176
},
{
"source": "99979655",
"sampled_maximum_us": 855,
"guarded_budget_us": 941
},
{
"source": "258b37df",
"sampled_maximum_us": 702,
"guarded_budget_us": 773
},
{
"source": "b8b7880a",
"sampled_maximum_us": 550,
"guarded_budget_us": 605
},
{
"source": "1b97c089a",
"sampled_maximum_us": 611,
"guarded_budget_us": 673,
"scope": "longer normal production RF campaign"
}
],
"spi16_read_probe": {
"softdevice_enabled": false,
"reads_per_phase": 16,
"phase_hz": [
8000000,
16000000,
8000000
],
"correct_packet_types_by_rxdelay": {
"2": [
16,
4,
16
],
"1": [
16,
3,
16
],
"0": [
16,
2,
16
]
},
"radio_writes_or_resets_between_phases": false,
"qualified": false
},
"combined_irq_experiment": {
"source": "aa480ae79e46bf63e10927de0327df0271b89505",
"abi": 2,
"enabled_in_production": false,
"successful_switches_per_direction": [
591,
591
],
"busy_admissions_per_direction": [
0,
12
],
"failed_switches_per_direction": [
0,
0
],
"worst_forward_us": 659.109375,
"worst_forward_observed_irq_or_scheduler_calls": 0,
"observed_sources": [
"rtc1",
"gpiote",
"uart0",
"uart1",
"power_clock",
"usb",
"scheduler",
"twim0_spim0"
],
"cause_established": false,
"systick_enabled_after_stop": false,
"systick_interrupt_enabled_after_stop": false
},
"witnessed_rf": {
"status": "failed",
"qualification_passed": false,
"source": "1b97c089a735ebe5ddb2f39937c685994f85850e",
"test_packets_sent": 200,
"test_packet_retries": 0,
"scanner": {
"primary_received": 96,
"primary_sent": 100,
"secondary_received": 99,
"secondary_sent": 100
},
"fixed_primary_witness": {
"received": 100,
"sent": 100
},
"fixed_secondary_witness": {
"received": 100,
"sent": 100
},
"duplicates": 0,
"wrong_profile_receipts": 0,
"collector_drops": 0,
"new_core_error_flags": 0,
"new_receive_errors": 1,
"watchdog_recoveries": 0,
"switch_command_errors": 0,
"guarded_budget_before_rf_us": 673,
"guarded_budget_after_rf_us": 673,
"selected_preambles": [
32,
200
],
"settled_recommended_preambles": [
32,
192
],
"cpu_capture": {
"duration_ms": 300004,
"samples": 27134,
"integrity_passed": true,
"maximum_gap_ms": 17.0,
"halt_debug_reset_lockup_observed": false,
"sleep_qualified": false
},
"gateway_restored": true,
"sender_cleanup_initially_failed": true,
"sender_cleanup_continuation_passed": true,
"original_failed_receipt_preserved": true,
"report_sha256": "cb7bd8c44a9e26cb131c2c4f123cd323163d7504f7f4cbfd3ed63f0fb5d87b89",
"swd_log_sha256": "e78301c78fda379e6f4b11f6095c4b969e4a7a1e81e25a1d34147f0c99b08e5d",
"cleanup_continuation_sha256": "b1929df2d2c6bc31b966773aa357f63778647c8ee67718a88204cbb031a3666d"
},
"scope_limits": [
"No all-board or release qualification",
"No MeshPocket physical testing",
"Indicator excluded",
"New unqualified nRF SPIM3 constructor rollout restored to prior defaults"
]
}
@@ -114,3 +114,7 @@ were removed, RAK live radio2 status returned to off, original TX power and
USB logging were restored, and the gateway service reacquired its radio with
its configuration unchanged. The independent offline audit reproduced the
three missing primary packets and reported no measurement confounds.
See the [fast-switch follow-up](rak3401_radio2_fast_switch_2026-10-23.md)
for buffered SPI measurements, the 16 MHz readback failure and subsequent
qualification results.