feat: add SMPSerialRawTransport for Zephyr raw UART SMP#106
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new raw (unencoded) SMP-over-UART transport for Zephyr’s CONFIG_MCUMGR_TRANSPORT_RAW_UART, while refactoring the existing base64/framed serial transport into a package with shared connection management.
Changes:
- Introduces
SMPSerialRawTransportimplementing Zephyr “raw UART” SMP message exchange ([8-byte header][payload]) with MTU-based send limiting. - Refactors existing
SMPSerialTransportto share connect/disconnect/TX drain/read helpers via a_SerialTransportBaseinserial/common.py. - Updates and expands the test suite, including a new end-to-end MTU-parametrized upload test for the raw transport.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_smp_serial_transport.py | Updates serial mocking target to the new serial.common.Serial location. |
| tests/test_smp_serial_raw_transport.py | Adds unit tests for the new raw serial transport behavior. |
| tests/test_smp_client.py | Adds an MTU-parametrized upload test exercising chunking with the raw transport. |
| tests/test_base64.py | Updates internal base64 helper imports to the new serial.encoded module. |
| src/smpclient/transport/serial/init.py | Re-exports SMPSerialTransport and SMPSerialRawTransport from the new package layout. |
| src/smpclient/transport/serial/common.py | Adds shared serial connection management and SerialException translation utilities. |
| src/smpclient/transport/serial/encoded.py | Moves encoded transport onto the shared serial base class; behavior largely preserved. |
| src/smpclient/transport/serial/unencoded.py | Implements the new raw SMP serial transport. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b0de5db to
d82c25f
Compare
Collaborator
Author
|
This needs rebase since a lot has changed with serial transport capabilities and integration tests. |
Collaborator
Author
|
After rebase, would be nice to add some integration tests for the MCUBoot raw transport: mcu-tools/mcuboot#2755 |
d82c25f to
19f474f
Compare
Zephyr 4.4 introduced CONFIG_MCUMGR_TRANSPORT_RAW_UART -- an SMP-over-UART
transport that sends each SMP message as raw [8-byte header][payload] bytes
with no framing, base64, or CRC. Smaller code size and faster transfers than
the historical "SMP over console" framing, at the cost of being unable to
share the UART with shell or log output.
Split the single transport/serial.py into a package so the encoded and raw
transports share connection management via a common base class:
serial/
__init__.py re-exports both transports and the fragmentation strategies
common.py _SerialTransportBase: the pyserial holder, the open/retry
connect loop (overridable for non-serial-port byte pipes),
disconnect, SerialException -> SMPTransportDisconnected
translation, TX drain, and the RX polling helper
encoded.py SMPSerialTransport: the base64 + CRC + delimiter framing, its
Auto/BufferSize/BufferParams sizing, and shell interleave
(read_serial), now on the shared base
unencoded.py SMPSerialRawTransport (new): writes bytes verbatim, reads the
SMP header then exactly its payload, and raises on overrun or
on a header length exceeding max_unencoded_size
The `from smpclient.transport.serial import SMPSerialTransport` path -- and the
Auto / BufferSize / BufferParams / FragmentationStrategy exports -- is
preserved, so existing users of the encoded transport need no changes.
Integration: the manifest-driven SMP-server suite already described a
native_sim serial_raw fixture and skipped it ("no raw-UART transport yet").
Vendor that fixture, drop the skip, and build SMPSerialRawTransport for it in
conftest, so the raw transport runs the generic echo / enumeration / params
suite. test_serial_raw.py adds a raw-specific check that the transport adopts
the server's buf_size as max_unencoded_size -- the chunk size SMPClient.upload
fills, with no on-wire frame to subtract (unlike the encoded transport's
buf_size - 4).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
19f474f to
999fcfc
Compare
Closed
This was referenced Jun 23, 2026
Collaborator
Author
|
Support for: zephyrproject-rtos/zephyr#101821 |
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.
Summary
Adds
SMPSerialRawTransportfor Zephyr 4.4'sCONFIG_MCUMGR_TRANSPORT_RAW_UART— the raw (unencoded) SMP-over-UART transport that sends each SMP message as[8-byte header][payload]bytes with no framing, base64, or CRC. Smaller code size and faster transfers than the historical "SMP over console" framing, at the cost of being unable to share the UART with shell or log output.The existing
serial.pyfile is split into a package so the two serial transports share connection management via a common base class:from smpclient.transport.serial import SMPSerialTransport(and the strategy exports) continues to work, so no migration is required for existing users of the encoded transport.Integration tests
The manifest-driven SMP-server suite already described a
native_simserial_rawfixture and skipped it ("smpclient has no raw-UART transport yet"). This PR makes it live:native_sim_serial_raw.exefrom the pinnedsmp-server-fixturesrelease (0eae053d, sha256-verified againstSHA256SUMS).client_supportedskip inservers.pyand buildsSMPSerialRawTransportforserial_rawfixtures inconftest._build_transport, so the raw transport runs the generic echo / enumeration / MCUmgr-params suite.test_serial_raw.pyadds a raw-specific check: after_initializereads the server's params, the transport adoptsbuf_sizeasmax_unencoded_size(the chunk sizeSMPClient.uploadfills) — with no on-wire frame to subtract, unlike the encoded transport'sbuf_size - 4.Related
UART_MCUMGR_RAW_PROTOCOLKconfig split that determines which transport appliessmpmgrwill need to expose the new transportTest plan
camas check(ruff + pydoclint + mypy + unit tests) — 363 passed, 14 skippedcamas test_integration— 207 passed, 91 skipped, incl. thenative_sim.serial_rawfixture across echo / enumeration / MCUmgr-params and the raw-specificbuf_sizetesttest_smp_serial_raw_transport.py) + an MTU-parametrizedSMPClient.upload()chunking test over the raw transportSMPSerialTransportsuite passes unchanged (behavior-preserving refactor onto the shared base)CONFIG_MCUMGR_TRANSPORT_RAW_UART=ytarget🤖 Generated with Claude Code