DRAFT: transport: rpmsg (OpenAMP) transport for MPU+MCU systems - #304
Draft
beriberikix wants to merge 11 commits into
Draft
DRAFT: transport: rpmsg (OpenAMP) transport for MPU+MCU systems#304beriberikix wants to merge 11 commits into
beriberikix wants to merge 11 commits into
Conversation
Add an rpmsg (OpenAMP) physical adapter for the Pouch Serial device transport. rpmsg is reliable, ordered and message-oriented, so each rpmsg message carries exactly one Pouch Serial frame (1-byte header + payload) with no extra framing or segmentation; the adapter feeds received messages straight into the serial device core and pulls frames to send when the core signals data is available. The adapter is a device-side driver only (the broker runs on the Linux application processor). It initializes from the ipc_service instance referenced by the "golioth,pouch-rpmsg-ipc" chosen node at APPLICATION init priority. This establishes the port/zephyr/transport/serial adapter directory that future bus adapters can share. Part of the rpmsg transport work for #274. Depends on the serial transport core (#232); do not merge until that lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an interrupt-driven UART device adapter on the serial transport core for development and native_sim end-to-end testing. rpmsg is not available on native_sim, so the same serial device core is exercised over a host pty (the native-tty UART driver) with the broker running as a host process. A minimal length-delimited framing (SOF + 2-byte length) recovers frame boundaries on the byte stream; the serial frame's own 1-byte header carries the channel. Also add the examples/zephyr/rpmsg_device sample: a Pouch device that reports telemetry and handles a setting over the serial transport. It builds for native_sim (build_only) so CI compiles the serial-core + adapter path. The same device code runs over the rpmsg adapter on real MPU+MCU hardware. Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The serial device wired the server-cert and device-cert channels unconditionally, but those endpoints are only compiled when SAEAD encryption is enabled, so a POUCH_ENCRYPTION_NONE build failed to link with undefined references to pouch_device_endpoint_server_cert/device_cert. Guard the two cert channels on CONFIG_POUCH_ENCRYPTION_SAEAD (mirroring the BLE GATT transport, which only exposes its cert characteristics under SAEAD), and defensively ignore frames that arrive for a channel with no endpoint. This lets the serial transport build without encryption, e.g. for the native_sim rpmsg_device example. Candidate to fold into the serial transport core (#232). Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract the UART adapter's length-delimited framing (SOF + 2-byte length) into a pure, dependency-free module (uart_framing.[ch]) with an encoder and a byte-at-a-time streaming decoder, and use it from uart_device.c. This makes the framing unit-testable and lets a host-side broker mirror the exact wire format. Add tests/pouch/rpmsg/exchange (native_sim ztest): - direct framing tests: encode/decode round-trip, resync after garbage, rejection of oversized and malformed frames; - an end-to-end test that runs a full broker <-> device serial exchange (reusing the serial exchange stub endpoints, so no gateway/cloud is needed) with every frame passed through encode + streaming decode, asserting all channel payloads survive the framing round-trip. Unlike the coap/http example pytests, this runs in the twister CI without any backend. Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ample
The earlier cert-channel SAEAD guard regressed the serial transport unit tests
(pouch.serial.exchange, pouch.serial.device): those tests build the serial
device core without CONFIG_POUCH_ENCRYPTION_SAEAD but still exercise the
certificate channels through stub endpoints, so guarding the channels on SAEAD
removed endpoints the tests rely on.
Revert src/transport/serial/{device,channel}.c to the #232 base so this PR no
longer modifies the serial core, and drop the native_sim rpmsg_device example
that depended on POUCH_ENCRYPTION_NONE. The serial device requires SAEAD in a
real build (its certificate endpoints are only compiled under SAEAD); a proper
SAEAD-based example (which also compiles the UART/rpmsg adapters) is a
follow-up.
The rpmsg framing + end-to-end exchange test (tests/pouch/rpmsg/exchange) is
unaffected: it drives the real broker/device serial cores with the shared stub
endpoints, so it needs no encryption and exercises the framing round-trip.
Part of #274. Do not merge until #232 lands.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a native_sim example that exercises the serial transport's UART device adapter with SAEAD end-to-end encryption (Pouch's default), so CI compiles the UART adapter and the serial device path. The device credentials are embedded self-signed placeholders (P-256), keeping the example self-contained with no provisioned filesystem; a real deployment provisions a CA-signed device certificate (see coap_client/ble_gatt for the filesystem pattern). The example reports telemetry over the serial transport; on native_sim the link is a host pty (native-tty UART) and on a real MPU+MCU part the same device code runs over the rpmsg adapter. Built build_only on native_sim in CI. Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Capture the work-in-progress harness for validating the Pouch rpmsg (OpenAMP) transport against a real Linux remoteproc + virtio-rpmsg stack in Renode, with no hardware. This complements the native_sim tests, which cannot exercise the ipc_service/OpenAMP adapter. Includes: - README documenting the validated approach: platform (AMD Kria KV260 / ZynqMP Cortex-R5, Zephyr board kv260_r5), the OpenAMP DDR carve-out addresses taken from the demo's Linux DTB (vrings @0x3ed40000/0x3ed44000, buffers @0x3ed48000), the IPI mailbox wiring, and how to build/run. - kv260_r5 openamp overlay + conf (zephyr,ipc_shm @0x3ed40000, zephyr,ipc = &rpu0_ipi) that lets zephyr/samples/subsys/ipc/openamp_rsc_table build for kv260_r5. - A robot smoke test that boots a kv260_r5 Zephyr image on the emulated R5. Validated so far: Renode's shipped ZynqMP OpenAMP echo test passes (real remoteproc + virtio-rpmsg round-trip); a kv260_r5 hello_world boots on the emulated R5; the openamp_rsc_table firmware builds for kv260_r5. Remaining: load the firmware via Linux remoteproc, swap in the Pouch device + mock broker, Ubuntu rootfs, and an end-to-end Robot test. Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Zephyr OpenAMP firmware built for kv260_r5 now loads and starts on the R5 via real Linux remoteproc in the Renode ZynqMP demo (remoteproc state -> running). Add the robot test that boots the demo Linux, injects the firmware into a copy of the rootfs (debugfs, no root), and drives the remoteproc load/start; document the debugfs injection flow. Fix firmware placement: device-address 0x0 maps to the 64K R5 TCM, which the ~155K openamp image overflows (remoteproc "bad phdr da 0x0"). Relocate &sram0 to the DDR rproc carve-out at 0x3ed00000 (256K), which the Xilinx R5 remoteproc driver maps. Remaining: confirm the rpmsg channel end to end, swap in the Pouch device + adapter firmware, an Ubuntu rootfs, and a mock broker. Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root-cause the R5-side bring-up: the ZynqMP R5 boots/executes from TCM (reset at 0x0), not DDR. A DDR-relinked firmware loads via remoteproc (state=running) but never runs. Switch the overlay back to the default TCM link address and keep only the vrings/buffers in DDR (zephyr,ipc_shm @ 0x3ed40000); route the R5 console to uart0 (Linux owns uart1). Trim the OpenAMP sample (no shell/log) to ~45 KiB so it fits ATCM. With that, the Linux side is fully up (virtio_rpmsg_bus online, /dev/rpmsg_ctrl0 + rpmsg_ctrl/rpmsg_ns devices) and the R5 now executes the firmware (prints on uart0). Remaining open blocker: the firmware faults in its IPM/IPI setup (ipm_set_enabled -> prefetch abort) before completing the rpmsg handshake; documented as the next step. Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document and capture the R5-side bring-up progress. Three real, sequential ZynqMP-R5-OpenAMP requirements the board lacked out of the box: 1. TCM-linked firmware (R5 boots from TCM, not DDR). 2. zephyr,ipc must point at the child mailbox (&rpu0_apu_mailbox); the ipm_xlnx_ipi driver leaves the parent rpu0_ipi device with a NULL api, so pointing at the parent faults in ipm_set_enabled. 3. An MPU region for the DDR OpenAMP carve-out: the ZynqMP SoC uses a static MPU table that doesn't map it, so the R5 data-aborts in virtqueue init. Captured as zynqmp-r5-openamp-mpu.patch. With all three the R5 runs the OpenAMP firmware without faulting. Remaining open blocker: after remoteproc start the emulation nearly stalls and no R5-announced rpmsg channel is observed yet (likely an IPI notify / interrupt-storm issue); documented for follow-up. Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rdware Frame the Renode Tier-2 outcome: the Linux remoteproc + virtio-rpmsg mechanism (the RFC's /dev/rpmsg_ctrl0 interface) and the full Zephyr R5 firmware bring-up (TCM link, child-mailbox IPM, MPU shared-memory region) are validated and documented. The final fault-free R5 rpmsg channel announcement is blocked by an emulator-model IPI interrupt-storm/stall after remoteproc start, so the end-to-end Pouch-over-rpmsg round-trip is deferred to real MPU+MCU hardware. Part of #274. Do not merge until #232 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Warning
Draft / do not merge. Stacked on #232 (serial transport core) — base is
transport/serial, notmain. Rebase ontomainonce #232 lands. Tracks the RFC in #274.What this is
An rpmsg (OpenAMP) transport for Pouch on heterogeneous MPU+MCU SoCs: the MCU runs Zephyr + the Pouch device stack and syncs to a Linux gateway over on-die OpenAMP/rpmsg, keeping its own cloud identity and end-to-end encryption while the Linux side forwards opaque pouches.
Per #274, this is an adapter on the serial transport core (#232), not a new transport — each rpmsg message carries one Pouch Serial frame, reusing the serial channel model, no SAR. This PR does not modify the serial core.
Status
port/zephyr/transport/serial/rpmsg_device.c):ipc_serviceendpoint ↔ serial device core +POUCH_RPMSG_DEVICEKconfig.port/zephyr/transport/serial/uart_device.c): interrupt-driven native-tty adapter for native_sim, sharing the framing module.uart_framing.[ch]): pure, testable length-delimited framing (encoder + streaming decoder).examples/zephyr/rpmsg_device): builds in nsim CI; compiles the UART adapter + serial device path with SAEAD.tests/pouch/rpmsg/exchange, native_sim, passing in twister CI): framing round-trip / resync / rejection, plus an end-to-end broker↔device serial exchange routed through the framing.doc/renode-tier2/. Real Linuxremoteproc+virtio-rpmsgin Renode brings up the RFC's exact interface (/dev/rpmsg_ctrl0), loads/starts the Zephyr R5 firmware, and the full R5 firmware bring-up is worked out and documented (TCM link;zephyr,ipc→ child mailbox; SoC MPU region for the DDR shared memory, incl. a patch). The final fault-free R5 channel announcement is blocked by an emulator-model IPI stall afterremoteproc start, so the end-to-end Pouch-over-rpmsg round-trip is deferred to real MPU+MCU hardware (details + remaining steps in the doc).Notes for reviewers
main).west-ncstwister job fails because this branch's base is behindmain; resolves on rebase after Add serial transport #232. Thensimexample job is red only from pre-existing backend-dependent coap/http pytests;sample.pouch.rpmsg_devicebuilds clean.🤖 Generated with Claude Code