diff --git a/docs/companion_radio_diagnostics.md b/docs/companion_radio_diagnostics.md index 3e3638379..6d7619ff4 100644 --- a/docs/companion_radio_diagnostics.md +++ b/docs/companion_radio_diagnostics.md @@ -5,7 +5,7 @@ Companion exposes these commands through USB terminal, the app's framed CLI | Command | Result | | --- | --- | -| `get rxps.wd` | RX power-saving recovery history: `soft=,hard=`. | +| `get rxps.wd` | Radio-driver recovery attempts: `soft=,hard=`. | | `get radio.rxps.rfrx_disabled` | Whether duty-cycle receive suppresses the radio's external RXEN output. Unsupported radios report an error. | | `set radio.rxps.rfrx_disabled on` / `off` | Changes that RXEN policy for this boot. The radio must have a supported RXEN pin and admit a safe reconfiguration. | | `get cad` / `get radio.cad` | Existing CAD scan/retry/deadline information, followed by `busy=` for busy-channel observations. | @@ -17,6 +17,15 @@ packet can reject the change. If receive restoration fails, the old RXEN policy is restored for the normal bounded receive-retry path and the command reports an error. The setting is not saved across reboot. +Radio2 scanning suspends RX duty cycling while preserving the saved RXPS +policy. Scanning can therefore run with a saved RXPS setting of `on`; the +policy resumes after radio2 stops. CPU power saving is a separate control. + +The recovery counters also include continuous-receive and liveness recovery +paths. They count attempts, not confirmed successful recoveries or CPU watchdog +resets. Compare fresh before/after readings and capture debug messages to +identify the reason for an increase. + `clear stats` retains watchdog recovery counts, airtime totals, receive activity timestamps, queued packets, duplicate-detection history, and all saved settings. Record a failure's statistics before clearing them; the command deliberately diff --git a/docs/test-results/other_board_radio2_fast_switch_2026-10-23.md b/docs/test-results/other_board_radio2_fast_switch_2026-10-23.md new file mode 100644 index 000000000..ee2391e19 --- /dev/null +++ b/docs/test-results/other_board_radio2_fast_switch_2026-10-23.md @@ -0,0 +1,223 @@ + + + + +# 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 +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](rak3401_radio2_fast_switch_2026-10-23.md). + +## 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. + +## 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. + +No production-default promotion, all-board release qualification or CPU-sleep +qualification is implied by the completed subsets. The machine-readable +[sanitized results](other_board_radio2_fast_switch_2026-10-23.safe.json) retain +separate delivery, speed, compatibility and build states. diff --git a/docs/test-results/other_board_radio2_fast_switch_2026-10-23.safe.json b/docs/test-results/other_board_radio2_fast_switch_2026-10-23.safe.json new file mode 100644 index 000000000..dbc328bfb --- /dev/null +++ b/docs/test-results/other_board_radio2_fast_switch_2026-10-23.safe.json @@ -0,0 +1,624 @@ +{ + "schema": 1, + "date": "2026-10-23", + "status": "partial", + "scope": "Finite opt-in nRF52 buffered-SPI campaign and completed Companion diagnostics checks; remaining RF/speed/driver-recovery failures explicit", + "maximum_switch_goal_us": 500, + "performance_goal_passed": false, + "all_boards_or_release_qualified": false, + "production_fast_default_promoted": false, + "cpu_sleep_qualified": false, + "electrical_power_measured": 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 + } + }, + "original_installed_timing": [ + { + "board": "Seeed XIAO nRF52", + "role": "repeater", + "source": "8b5660b00b88d8abaae094859bc1232f7ce886fd", + "sample_window_seconds": 20, + "sampled_maximum_us": 916, + "provisional_guarded_budget_us": 1008, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 0, + "core_flags_after": 0, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "ea8c237cc4a0a45a8a5d40956b0a1bfaddd29262216b1d7913bd654ffa398a0a" + }, + { + "board": "RAK4631", + "role": "repeater", + "source": "adb11e7b41f2d3c561bc6aba4ebf6c92a45623bd", + "sample_window_seconds": 20, + "sampled_maximum_us": 916, + "provisional_guarded_budget_us": 1008, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 8, + "core_flags_after": 8, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "4e4d6153cff78713919ab7ce1bbe5c27922d7f1c4c57e34d65983db31147cf9e" + }, + { + "board": "RAK WisMesh Tag", + "role": "full_companion", + "source": "08650f644b680a5dfaacb95142e3cef8529da9d2", + "sample_window_seconds": 20, + "sampled_maximum_us": 947, + "provisional_guarded_budget_us": 1042, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 8, + "core_flags_after": 8, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "41c7cd4d2f083a8fc6e69949a449d58ee54616456b3faa31697f08a0c7828a0d" + }, + { + "board": "Heltec T096", + "role": "full_companion", + "source": "4773ac4219666d0f5b4c2bff5eb72aa053014662", + "sample_window_seconds": 20, + "sampled_maximum_us": 947, + "provisional_guarded_budget_us": 1042, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 8, + "core_flags_after": 8, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "8216ae44390b07af6f3df296fe555b3996ded6eda1592c61048df3dfd2604c31" + }, + { + "board": "Heltec MeshTower V2 SD", + "role": "full_repeater_no_external_sensors", + "source": "ebb59d48292de4a573250cf4c6a2ed7cf5f7ef69", + "sample_window_seconds": 20, + "sampled_maximum_us": 947, + "provisional_guarded_budget_us": 1042, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 2, + "core_flags_after": 2, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "9bdc2fe932920738bfbec05310ddf12a3feca6a03de10827c68a1d53e25b7414" + } + ], + "candidate_timing": [ + { + "board": "Seeed XIAO nRF52", + "role": "repeater", + "source": "1b9fcf2af5a3191549baf69757aa158f836bf624", + "sample_window_seconds": 20, + "sampled_maximum_us": 855, + "provisional_guarded_budget_us": 941, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 0, + "core_flags_after": 0, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "140d8507a3d4744970af338414cc212013efa2de64e0da784ee83b42e320156c", + "spi_controller": "SPIM3", + "spi_hz": 2000000, + "buffered": false, + "performance_goal_passed": false + }, + { + "board": "Seeed XIAO nRF52", + "role": "repeater", + "source": "1b9fcf2af5a3191549baf69757aa158f836bf624", + "sample_window_seconds": 20, + "sampled_maximum_us": 550, + "provisional_guarded_budget_us": 605, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 0, + "core_flags_after": 0, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "9a505a9b4c7eee409c30663a1bdd1c836e894cda5b4761321684e9e731724295", + "spi_controller": "SPIM2", + "spi_hz": 8000000, + "buffered": true, + "performance_goal_passed": false + }, + { + "board": "RAK WisMesh Tag", + "role": "full_companion", + "source": "61a536c686ad2436132668bc18f0f8e5b0b04383", + "sample_window_seconds": 20, + "sampled_maximum_us": 580, + "provisional_guarded_budget_us": 638, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 0, + "core_flags_after": 0, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "fef7432785adcb14e8f36c99c2b3754ad305c2818454bd778deee021cbfe6384", + "spi_controller": "SPIM1", + "spi_hz": 8000000, + "buffered": true, + "performance_goal_passed": false + }, + { + "board": "Heltec MeshTower V2 SD", + "role": "full_repeater_no_external_sensors", + "source": "61a536c686ad2436132668bc18f0f8e5b0b04383", + "sample_window_seconds": 20, + "sampled_maximum_us": 550, + "provisional_guarded_budget_us": 605, + "directional_self_test_samples": [ + 4, + 4 + ], + "timing_self_test_still_pending": true, + "core_flags_before": 0, + "core_flags_after": 0, + "new_switch_errors": 0, + "cleanup_passed": true, + "report_sha256": "486eb2b5dd6705ddd292ac9e36556da7315b288e6ba1819f5dca3be5e678746c", + "spi_controller": "SPIM1", + "spi_hz": 8000000, + "buffered": true, + "performance_goal_passed": false + } + ], + "comparison_limits": { + "xiao_same_source_transport_comparison": true, + "tag_and_tower_old_vs_candidate_sources_differ": true, + "short_window_budgets_are_provisional": true, + "longer_rf_budgets_larger_than_short_window": true + }, + "witnessed_rf": [ + { + "board": "Seeed XIAO nRF52", + "role": "repeater", + "source": "1b9fcf2af5a3191549baf69757aa158f836bf624", + "delivery_qualification_passed": false, + "test_packets_sent": 200, + "test_packet_retries": 0, + "primary_received": 99, + "primary_sent": 100, + "secondary_received": 100, + "secondary_sent": 100, + "fixed_primary_witness_received": 100, + "fixed_secondary_witness_received": 100, + "duplicates": 0, + "wrong_profile_receipts": 0, + "collector_drops": 0, + "collector_errors": 0, + "new_dut_receive_errors": 0, + "dut_core_flags_before": 0, + "dut_core_flags_after": 0, + "reboot_observed": false, + "guarded_budget_before_us": 673, + "guarded_budget_after_us": 673, + "settings_restoration_passed": true, + "gateway_service_restored": true, + "offline_audit_passed": false, + "performance_goal_passed": false, + "all_goals_passed": false, + "report_sha256": "e5c4fe9ab79ce3500918e7fdb41cb57d33ac2015826d3eca18facbbca0d2849a", + "audit_sha256": "cc97d1e00359935fad64033d65ba05de9ac60d165b60624fb815f87465af01f4", + "dut_rxps_watchdog_attempts_before": "soft=0,hard=0", + "dut_rxps_watchdog_attempts_after": "soft=0,hard=0" + }, + { + "board": "Heltec MeshTower V2 SD", + "role": "full_repeater_no_external_sensors", + "source": "61a536c686ad2436132668bc18f0f8e5b0b04383", + "delivery_qualification_passed": true, + "test_packets_sent": 200, + "test_packet_retries": 0, + "primary_received": 100, + "primary_sent": 100, + "secondary_received": 100, + "secondary_sent": 100, + "fixed_primary_witness_received": 100, + "fixed_secondary_witness_received": 100, + "duplicates": 0, + "wrong_profile_receipts": 0, + "collector_drops": 0, + "collector_errors": 0, + "new_dut_receive_errors": 0, + "dut_core_flags_before": 0, + "dut_core_flags_after": 0, + "reboot_observed": false, + "guarded_budget_before_us": 673, + "guarded_budget_after_us": 673, + "settings_restoration_passed": true, + "gateway_service_restored": true, + "offline_audit_passed": true, + "performance_goal_passed": false, + "all_goals_passed": false, + "report_sha256": "c4ddcde41f2ace60fe6de32896e370af11f422ca8a0d6ab5bb10f2b78f152cad", + "audit_sha256": "81873da8b01cb05c11a913639aef2943262cfd5587dfe8580d5b7e5028ff06e5", + "dut_rxps_watchdog_attempts_before": "soft=0,hard=0", + "dut_rxps_watchdog_attempts_after": "soft=0,hard=0" + }, + { + "board": "RAK WisMesh Tag", + "role": "full_companion", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "delivery_qualification_passed": true, + "test_packets_sent": 200, + "test_packet_retries": 0, + "primary_received": 100, + "primary_sent": 100, + "secondary_received": 100, + "secondary_sent": 100, + "fixed_primary_witness_received": 100, + "fixed_secondary_witness_received": 100, + "duplicates": 0, + "wrong_profile_receipts": 0, + "collector_drops": 0, + "collector_errors": 0, + "new_dut_receive_errors": 0, + "dut_core_flags_before": 0, + "dut_core_flags_after": 0, + "reboot_observed": false, + "guarded_budget_before_us": 638, + "guarded_budget_after_us": 638, + "settings_restoration_passed": true, + "gateway_service_restored": true, + "offline_audit_passed": true, + "performance_goal_passed": false, + "all_goals_passed": false, + "report_sha256": "148ca58743d585020533ae91b3cc256bb168ca84d6e769f80efc1067542223d3", + "audit_sha256": "7601809a852bee159c437378c9e5a8f8b7ce64ea9f5054effd87d4997d23c038", + "dut_rxps_watchdog_attempts_before": "soft=1,hard=0", + "dut_rxps_watchdog_attempts_after": "soft=1,hard=0" + } + ], + "ble": [ + { + "board": "RAK WisMesh Tag", + "role": "full_companion", + "source": "61a536c686ad2436132668bc18f0f8e5b0b04383", + "passed": true, + "sessions_completed": 3, + "hold_seconds_per_session": 30, + "mtu": [ + 247, + 247, + 247 + ], + "dual_profile_switching_continued": true, + "new_core_flags": 0, + "cleanup_passed": true, + "scope": "Original identity/version/Bluetooth getters at61a checkpoint; final807 results recorded separately", + "report_sha256": "bf0adea9ce7b068ca29aeee1fdd625731b5357d84eca1f7793cdcaf39f73c5b2", + "child_report_sha256": "c750d69b0cf0ffe8d90e204789792ee55352895857bc37898910973ec0d5c223" + }, + { + "board": "Seeed XIAO nRF52", + "role": "full_companion", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "passed": true, + "sessions_completed": 3, + "hold_seconds_per_session": 30, + "mtu": [ + 247, + 247, + 247 + ], + "diagnostic_getters_verified_per_session": 10, + "original_identity_version_and_bluetooth_getters_retained": true, + "dual_profile_switching_continued": true, + "new_core_flags": 0, + "cleanup_passed": true, + "historical_usb_rxps_watchdog_attempts": "soft=1,hard=0", + "current_before_rxps_watchdog_attempts": "soft=3,hard=0", + "same_current_counter_baseline_through_arming_ble_and_cleanup": true, + "pretrial_attempt_increase_cause_established": false, + "no_cpu_reset_inferred_from_recovery_attempt_counters": true, + "report_sha256": "bc9d4ac76b642791b8be0930e949daf4db06dea24bd25f94feafddef81cf1d21", + "child_report_sha256": "3efbb1342e5f49bc04e25ee7dee05be548697bdc7dd750f50dbca3c53b4ac87d" + }, + { + "board": "RAK WisMesh Tag", + "role": "full_companion", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "passed": true, + "sessions_completed": 3, + "hold_seconds_per_session": 30, + "mtu": [ + 247, + 247, + 247 + ], + "diagnostic_getters_verified_per_session": 10, + "original_identity_version_and_bluetooth_getters_retained": true, + "dual_profile_switching_continued": true, + "new_core_flags": 0, + "cleanup_passed": true, + "historical_usb_rxps_watchdog_attempts": "soft=0,hard=0", + "current_before_rxps_watchdog_attempts": "soft=1,hard=0", + "same_current_counter_baseline_through_arming_ble_and_cleanup": true, + "pretrial_attempt_increase_cause_established": false, + "no_cpu_reset_inferred_from_recovery_attempt_counters": true, + "report_sha256": "fdc85363f2728368c21003faffbd4e39db8bae993e950a024761d40f781d7b05", + "child_report_sha256": "f9efb9cdfd5a86f9e4752f00ae3d3b5a58df7a67ca32b4218d26b6752a1df657" + } + ], + "sd_compatibility": { + "board": "Heltec MeshTower V2 SD", + "role": "full_repeater_no_external_sensors", + "source": "61a536c686ad2436132668bc18f0f8e5b0b04383", + "passed": true, + "physical_marker_bytes_written": 4, + "file_and_card_sync_acknowledged": true, + "directory_path_and_size_verified": true, + "dual_profile_switch_counter_advanced": true, + "original_cache_policy_and_radio_leases_restored": true, + "marker_byte_content_readback_qualified": false, + "full_sd_payload_io_qualified": false, + "report_sha256": "6568b15f71e7e10afa92bab51b8385334a8e533230f68e8d69b870dd63a1af61" + }, + "final_diagnostics": { + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "xiao_full_companion": { + "application_install_passed": true, + "fallback_used": false, + "body_hash": "7EC2F4BF2A80CFC1", + "application_bytes": 581508, + "rxen_single_profile_and_radio2_suspended_policy_tested": true, + "new_diagnostics_getters_tested": true, + "clear_stats_nonzero_hardware_observation": false, + "clear_stats_nonzero_native_coverage": true, + "ble_new_getters_status": "passed", + "transition_report_sha256": "6812a0d75b69dff68a0e9ee0d17f91a0b9b5b07d2e0f4e6b87ad8dceec7ac672", + "usb_cli_passed": true, + "usb_cli_cleanup_passed": true, + "usb_cli_report_sha256": "c6915df1c455f1ca5816a795f4011be0c753b8e76030f6cca4256059aa05f7a0", + "rxps_watchdog_history": { + "soft": 1, + "hard": 0, + "same_values_in_three_usb_reads": true, + "history_cleared": false, + "historical_usb_soft": 1, + "current_before_ble_soft": 3, + "current_before_ble_hard": 0, + "exact_current_baseline_unchanged_through_ble": true, + "pretrial_increase_cause_established": false, + "new_attempts_during_usb_check": 0 + } + }, + "tag_full_companion": { + "install_status": "passed", + "usb_cli_status": "passed", + "ble_new_getters_status": "passed", + "witnessed_rf_status": "passed", + "fallback_used": false, + "body_hash": "6115C6802E1AFC50", + "install_report_sha256": "f03016b6c8ba5ca44e6361d2126d31ecc6141bb5da26e2db6ad332759365b333", + "usb_cli_report_sha256": "eea2da1a4d7e2f71611f2d989320051066143d391133785262ff421950185c55", + "rxen_negative_capability_verified": true, + "clear_stats_nonzero_hardware_observation": false, + "clear_stats_nonzero_native_coverage": true, + "rxps_watchdog_attempts_rf_before": "soft=1,hard=0", + "rxps_watchdog_attempts_rf_after": "soft=1,hard=0" + }, + "tower_full_repeater_sd": { + "install_status": "passed", + "shared_sd_command_hardware_status": "passed", + "fallback_used": false, + "body_hash": "E5324C388E987A8E", + "install_report_sha256": "6e065a89fd5d55a5acd89ae6d3ec6ad207a9d2fe44e536358519cc163760d638" + }, + "xiao_repeater_restore": { + "status": "passed", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "body_hash": "83C09F44589332D6", + "application_only": true, + "fallback_used": false, + "two_identity_bound_postchecks_passed": true, + "original_repeater_settings_preserved": true, + "saved_primary_frequency_mhz": 917, + "gateway_untouched": true, + "report_sha256": "b9f60585fcab74d4055693a56d1fdab8a28890ef4b2af325a5c9fe578068e8c8" + } + }, + "linked_artifacts": [ + { + "label": "xiao_repeater_matched2", + "target": "Xiao_nrf52_repeater-full-ota", + "source": "1b9fcf2af5a3191549baf69757aa158f836bf624", + "elf_sha256": "6f222f9ba99448edf8f347f5dba835b57a0e6bbf01e9554f70f8fcc0e238dd77", + "memory_capacity_gate_passed": true, + "spi_controller": "SPIM3" + }, + { + "label": "xiao_repeater_fast8", + "target": "Xiao_nrf52_repeater-full-ota", + "source": "1b9fcf2af5a3191549baf69757aa158f836bf624", + "elf_sha256": "f65f85e389ff8af8fc30a9be1bf430334e569ee5456b0b16e6dab348557015e8", + "memory_capacity_gate_passed": true, + "spi_controller": "SPIM2" + }, + { + "label": "tag_companion_fast8", + "target": "RAK_WisMesh_Tag_companion_radio_full", + "source": "61a536c686ad2436132668bc18f0f8e5b0b04383", + "elf_sha256": "94bdf7385b7a3da18f3ac7f1656eec0c638f2417b9d8ca2d974bc683184b3e09", + "memory_capacity_gate_passed": true, + "spi_controller": "SPIM1" + }, + { + "label": "tower_repeater_fast8", + "target": "Heltec_tower_v2_sdcard_repeater_lora_ota_no_external_sensors-full-ota", + "source": "61a536c686ad2436132668bc18f0f8e5b0b04383", + "elf_sha256": "e38bfdb5059e3227d5685cdc0e114121045439f9263ea4ed473686c5947d74fb", + "memory_capacity_gate_passed": true, + "spi_controller": "SPIM1" + }, + { + "label": "final_xiao_companion", + "target": "Xiao_nrf52_companion_radio_full", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "elf_sha256": "3324de701d8159bbf626e08ea1adfc91634db6191ace4d0898fc76e513884cb4", + "memory_capacity_gate_passed": true, + "spi_controller": "SPIM2" + }, + { + "label": "final_xiao_repeater", + "target": "Xiao_nrf52_repeater-full-ota", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "elf_sha256": "2266a1d669e96c70f8e5dd695613a6eb621f80c3422d17da37801d62cb970786", + "memory_capacity_gate_passed": true, + "spi_controller": "SPIM2" + }, + { + "label": "final_tag_companion", + "target": "RAK_WisMesh_Tag_companion_radio_full", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "elf_sha256": "be9c73e78b073b8942a0aa84b25dd08c49d6e6cf30fb606c0e18f12988d11a12", + "memory_capacity_gate_passed": true, + "spi_controller": "SPIM1" + }, + { + "label": "final_tower_repeater", + "target": "Heltec_tower_v2_sdcard_repeater_lora_ota_no_external_sensors-full-ota", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "elf_sha256": "785ee10d5c6fd67a728fd3126c8daf03b435b0dfe2d383582d4aaa48d605bab0", + "memory_capacity_gate_passed": true, + "spi_controller": "SPIM1" + } + ], + "build_limitations": [ + { + "target": "RAK_4631_companion_radio_full", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "status": "failed", + "flash_overflow_bytes": 524, + "followup_status": "resolved_by_exact_full_build", + "followup_flash_overflow_bytes": 168, + "packed_help_native_byte_equivalence_passed": true, + "packed_help_canonical_compile_failures": [ + "Producer initially compiled as C++11", + "Early middleware gate missed the environment Full flag" + ], + "corrected_isolated_source_build_status": "passed", + "initial_failure_scope": "linker text region only; not complete OTA application size", + "resolved_source": "0cdf6f9aa651278858f859ac72e2367a09c96f20", + "resolved_application_bytes": 712684, + "application_limit_bytes": 712704, + "application_margin_bytes": 20, + "memory_capacity_passed": true + } + ], + "not_new_fast_qualified": [ + { + "board": "RAK4631", + "transport_retained": "2MHz byte transfers", + "reason": "Peripheral controller ownership requires a separate safe mapping" + }, + { + "board": "Heltec T096", + "transport_retained": "2MHz byte transfers", + "reason": "Existing display/controller ownership requires a separate safe mapping" + } + ], + "excluded_or_unqualified": [ + "MeshPocket excluded from physical testing", + "SenseCAP Indicator excluded", + "No all 13 radios qualification claim", + "No CPU-sleep or current measurement", + "XIAO scanner RF missing packet unresolved", + "500 us maximum goal unmet", + "Unexplained pretrial radio-driver recovery attempts on XIAO and Tag" + ], + "final_sd_compatibility": { + "board": "Heltec MeshTower V2 SD", + "role": "full_repeater_no_external_sensors", + "source": "807343de8d77adc4f61dbb260bdb499c04fa0211", + "passed": true, + "physical_marker_bytes_written": 4, + "file_and_card_sync_acknowledged": true, + "directory_path_and_size_verified": true, + "dual_profile_switch_counter_advanced": true, + "original_cache_policy_and_radio_leases_restored": true, + "marker_byte_content_readback_qualified": false, + "full_sd_payload_io_qualified": false, + "report_sha256": "64c0bb02bc9cb7f4882299940ce5bbb9321c06de18f87158deada8eeb55b2a8e", + "body_hash": "E5324C388E987A8E", + "shared_sd_readonly_getters_passed": true, + "shared_sd_readonly_getters": [ + "get sdcard", + "get sdcard *", + "get sdcard format", + "get sdcard erase", + "get sdcard free" + ] + }, + "build_validations": [ + { + "target": "RAK_4631_companion_radio_full", + "source": "0cdf6f9aa651278858f859ac72e2367a09c96f20", + "passed": true, + "elf_sha256": "1c6e6f8089e1bdea20aba7eb11823c0900fd435630b500801ee15b6d5e0d0be3", + "application_bytes": 712684, + "application_limit_bytes": 712704, + "application_margin_bytes": 20, + "available_internal_bytes": 81220, + "required_heap_bytes": 72528, + "full_companion": true, + "features_or_contact_channel_limits_removed": false, + "storage_layout_changed": false, + "decoded_help_bytes": 4222, + "packed_help_bytes": 2159, + "exact_legacy_help_preserved": true, + "raw_help_absent_from_elf": true, + "decoder_history_bytes": 2048, + "decoder_chunk_bytes": 64, + "decoder_heap_allocation": false, + "memory_report_sha256": "602186647d1f257dc8cd08f4dc5c37772d1a10b03ffe85e607153b7a31302fb2", + "help_proof_sha256": "af07b666ef0d7906468cd01507d2f72ce8681b5c75b77d6b56525e23fa76ff97", + "hardware_flashed": false + } + ] +}