OTA tests + essential fixes for the key-store branch: devicetree-safe FlashWorker region, ComQueue arming fix, hardware-in-the-loop OTA CI - #498
Open
Mikefly123 wants to merge 5 commits into
Conversation
…a hardcoded ID Minimal port of PR #492's FlashWorker fix. This branch adds keystore_partition to the devicetree, and Zephyr assigns flash-area IDs by devicetree dependency ordinal -- the keystore node (referenced by the fstab) sorts first, renumbering every area: keystore=0, mcuboot=1, slot0=2, slot1=3 (verified in this branch's generated devicetree_generated.h). The old hardcoded REGION_NUMBER=2 therefore points at slot0 -- the RUNNING image -- and the first PREPARE_UPDATE would boot_erase_img_bank() the firmware out from under itself, bricking the board before any image is uplinked. Resolve via PARTITION_ID(slot1_partition) and add a static_assert that the staging region can never overlap the running code partition, so this class of renumbering can't be reintroduced silently. Bench-verified on 2026-08-03/04: PARTITION_ID resolves to 3 on this devicetree, static_assert passes, and the full OTA swap-and-revert cycle runs clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpBURCutAx8281i59nj6fo
…(issue #494) Picks up Open-Source-Space-Foundation/fprime branch fix/comqueue-blocking-comstatus-main (03c645123, one FPP change based directly on this branch's current pin 8a62e455a): async input port comStatusIn: Fw.SuccessCondition block Without it, the one-shot arming comStatus=SUCCESS emitted at startup by the ComAggregator preamble shares ComQueue's IPC message queue with the boot event burst; if the queue is momentarily full the message is silently dropped (the FW_ASSERT reports to a disabled console and execution continues) and ComQueue stays WAITING forever -- no telemetry, events, or command acks on any boot of that binary. This branch's littlefs mount shifts boot timing enough to lose that race deterministically: unfixed, this branch merged with an OTA-workload topology produced a 100%-reproducible mute board on two bench V5e units. Same fork commit as PCR PR #495 (the standalone fix against main); whichever merges first makes the other's pin bump trivial. Full analysis in issue #494. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpBURCutAx8281i59nj6fo
Adds ota_update_test.py: the full swap-and-revert lifecycle against real hardware (uplink signed image -> on-board CRC verify -> PREPARE/UPDATE/ CONFIGURE_NEXT_BOOT[TEST] -> reboot, assert new build-id -> reboot without CONFIRM, assert MCUBoot auto-revert) plus negative paths (UPDATE without PREPARE, wrong CRC), parametrized over uart (fast bench link) and lora (lossy radio, marked slow, CRC-driven re-uplink loop). Support plumbing, each piece earned on the bench: - make ota-test-image: builds a second signed image whose project version carries OTA_BUILD_ID via an ephemeral git tag (git-describe injection), so the swap test can prove WHICH image booted, with signing unchanged. - conftest: --ota-image/--ota-build-id options + ota_config fixture (skip when absent), and an autouse resync_sequence_number_after_reboot fixture -- the deframer's write-ahead seq persistence (issue #461) means every in-suite reboot desyncs ground, silently rejecting authenticated commands. - common.py: resync_sequence_number helper, also invoked from the command retry path so a mid-test reboot self-heals. - The test configures the downlink repeater itself for uart runs (CHANNEL_ENABLED = uart-only, re-applied after each reboot because the setting is RAM-only, each application followed by a seq resync -- an authenticated send between resync and COLD_RESET otherwise reliably desyncs the counter; found the hard way, 2/2 reproducible). - pytest.ini: ota marker; slow reworded for the LoRa uplink duration. Validated on a bench V5e on 2026-08-03/04 against this branch's content merged with the OTA topology: swap+revert+negatives green in under 5 minutes at --file-uplink-cooldown 0.05. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpBURCutAx8281i59nj6fo
…-loop - New ota-test-image job (parallel with build, no needs:) produces the uniquely-marked signed image via make ota-test-image, with OTA_BUILD_ID=<sha8>-<run_id> exported for the integration jobs. - integration-uart runs ota_update_test.py LAST in the GDS phase (it reboots the board twice, so it must not precede the other UART tests), FILTER 'not slow', wired to the artifact + build-id. - The radio job runs the slow LoRa OTA variant on the nightly schedule only (new cron 03:00 UTC); PR/push runs keep to the fast UART variant. With this, the FlashWorker region regression class (erasing the running slot after a devicetree change) is caught by CI on the first PREPARE_UPDATE instead of on a bricked bench board. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpBURCutAx8281i59nj6fo
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The previous pin bump recorded 03c645123ba8933e33e4c621bafd433d5c1a56de, which does not exist -- the true tip of fix/comqueue-blocking-comstatus-main on the OSSF fprime fork is 03c6451237d4442248703947693c1985a1948e88 (the coordinator supplied a full SHA hand-expanded from the short form, and the tooling recorded it unverified). CI's submodule fetch failed with 'not our ref', which is what broke the unit-test job on this PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpBURCutAx8281i59nj6fo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the OTA integration test suite and two essential fixes to
hmac-to-storage(PR #472), all bench-validated on 2026-08-03/04 against exactly this content merged with the OTA topology (two V5e units).Commits
fix(FlashWorker): resolve the update region from the devicetree — minimal port of PR OTA: fix the flash-area ID that bricks the board, add an integration test and a CI job #492's fix, and load-bearing on this branch specifically: addingkeystore_partitionrenumbers Zephyr's flash-area IDs (assigned by devicetree dependency ordinal; the keystore node sorts first via the fstab reference):Verified in this branch's generated
devicetree_generated.h. With the old hardcodedREGION_NUMBER = 2, the firstPREPARE_UPDATEerases the running firmware — an instant brick, before any image is uplinked. Now resolved viaPARTITION_ID(slot1_partition)plus astatic_assertthat the staging region can never overlap the running code partition.fix(comms): fprime pin bump — ComQueuecomStatusInbecomesblock— fixes issue ComQueue permanently wedges in WAITING when the one-shot arming comStatus is dropped at boot (silent total downlink loss; exposed by PR #472's littlefs Kconfig) #494: the one-shot armingcomStatus=SUCCESSshares ComQueue's IPC queue with the boot event burst; when dropped (invisibly — the FW_ASSERT reports to a disabled console and continues) the downlink wedges in WAITING forever, every boot, both UART and LoRa. This branch's littlefs mount shifts boot timing enough to lose that race deterministically — unfixed, this branch merged with an OTA-workload topology produced a 100%-reproducible mute board. Same fork commit (03c645123) as PR fix(comms): make ComQueue comStatusIn blocking so the one-shot arming status can't be dropped (#494) #495 (the standalone fix againstmain); whichever merges first makes the other's pin bump trivial.test(ota): the OTA image-swap suite — full swap-and-revert lifecycle (uplink → on-board CRC verify → PREPARE/UPDATE/CONFIGURE_NEXT_BOOT[TEST] → reboot, assert new build-id → reboot without CONFIRM, assert MCUBoot auto-revert) plus negative paths, parametrized uart/lora. Includesmake ota-test-image(unique build-id via ephemeral git tag, signing untouched), the--ota-image/--ota-build-idfixtures, an autouse post-reboot sequence-number resync (issue Svc::FileUplink emits FileReceived before the file is durably closed, causing spurious file-not-found #461 write-ahead persistence desyncs ground on every in-suite reboot), and UART-only downlink-repeater configuration inside the test (RAM-only setting, re-applied after each reboot, each application followed by a resync — an authenticated send between resync andCOLD_RESETreliably desyncs otherwise).ci: hardware-in-the-loop OTA — newota-test-imagejob (parallel withbuild);integration-uartruns the UART OTA test last in the GDS phase; the slow LoRa variant runs on a new nightly cron only. With this, the FlashWorker regression class is caught by CI on the firstPREPARE_UPDATEinstead of on a bricked bench board.Bench evidence
--file-uplink-cooldown 0.05(the 0.4 s default is LoRa pacing — pure dead air on USB CDC).Caveats for reviewers
SequenceNumberWriteFailed+PrmFileReadErrorand the board's sequence counter jumps ~3000 per reboot — the reason the resync choreography in the test is as careful as it is. Issue to be filed; it is pre-existing and not introduced by this PR.py_compile+ pytest collection); the identical file content and fprime pin content built and ran on the bench branch. CI on this PR provides the compile proof.🤖 Generated with Claude Code
https://claude.ai/code/session_01WpBURCutAx8281i59nj6fo