-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Fix MSPv2 over SmartPort: repeated START frames after header-only first chunk #14749
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Do you want to test this code? You can flash it directly from the Betaflight App:
WARNING: It may be unstable. Use only for testing! |
WalkthroughModifies Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/main/telemetry/msp_shared.c (1)
327-327: Consider resettingheaderSentinprocessMspPacketandsendMspErrorResponsefor robustness.The flag is correctly reset here after completing a response. However, both
processMspPacket()(line 144) andsendMspErrorResponse()(line 162) reset the response buffer pointer without resettingheaderSent. While the protocol assumes sequential request-response cycles, defensively resetting the flag when initializing a new response would prevent potential state corruption if a new request arrives unexpectedly.Add the reset at the beginning of
processMspPacket:static void processMspPacket(void) { responsePacket.cmd = 0; responsePacket.result = 0; responsePacket.buf.ptr = responseBuffer; responsePacket.buf.end = ARRAYEND(responseBuffer); + headerSent = false; // Reset header state for new responseAnd similarly in
sendMspErrorResponse:static void sendMspErrorResponse(uint8_t error, int16_t cmd) { responsePacket.cmd = cmd; responsePacket.result = 0; responsePacket.buf.ptr = responseBuffer; + headerSent = false; // Reset header state for new responseNote:
headerSentwould need to be moved outsidesendMspReply()or declared at file scope for these functions to access it.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/main/telemetry/msp_shared.c(3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: ledvinap
Repo: betaflight/betaflight PR: 14578
File: src/main/telemetry/jetiexbus.c:547-556
Timestamp: 2025-08-12T18:26:17.016Z
Learning: For Betaflight Jeti ExBus backport PR #14578: ledvinap prefers to keep the PR focused on backporting fixes from iNavFlight rather than expanding into broader architectural improvements. Additional improvements to TX/RX state machine should be handled in separate PRs.
🧬 Code graph analysis (1)
src/main/telemetry/msp_shared.c (1)
src/main/common/streambuf.c (2)
sbufInit(29-34)sbufSwitchToReader(153-157)
🔇 Additional comments (5)
src/main/telemetry/msp_shared.c (5)
274-274: LGTM: Static flag appropriately tracks header state.The static boolean flag correctly maintains state across chunks and is properly initialized to
false.
281-281: Core fix correctly addresses the root cause.Replacing the pointer-based detection with an explicit
headerSentflag properly handles the case where the first SmartPort chunk contains only the 6-byte header and no payload. The previous pointer comparison failed because the buffer pointer wasn't advanced when no payload bytes were written.
306-309: Correct flag management and continuation header logic.Setting
headerSent = trueafter emitting the header ensures subsequent calls generate continuation frames without the START flag, properly implementing the chunk sequencing protocol.
312-312: LGTM: Minor formatting cleanup.Also applies to: 324-324
271-329: Well-structured fix with minimal scope.The implementation correctly addresses the SmartPort MSPv2 header-only first chunk issue while maintaining backward compatibility with MSPv1, MSPv2 over CRSF, and other telemetry protocols. The logic properly handles partial sends and response completion.
|
This code has been derived and tested on rotorflight rotorflight/rotorflight-firmware#344 The entire RFsuite stack works perfectly with this fix using mspv2 as the transport - on crsf and sport. Its also about to make it into the inav tree. |
Summary
This PR fixes an issue where MSPv2 telemetry over SmartPort would continuously resend the first “START” frame and never send continuation frames, preventing MSPv2 replies from completing.
Root Cause
SmartPort limits each telemetry frame to 6 bytes.
When
sendMspReply()sends the first MSPv2 reply frame, that frame often contains only the 6-byte header (no payload bytes).The function previously used:
to detect whether the current chunk is the first frame.
Because the header-only case doesn’t advance the buffer pointer, subsequent calls still satisfy the condition — every chunk is treated as “first”, so the firmware keeps setting the
MSP_STATUS_START_MASKbit.Fix
A minimal fix introduces a small static flag (
headerSent) to track whether the header has already been emitted:This ensures only the first frame of a response has the START flag, even if it carried no payload bytes.
Verification
Logs now show:
Impact
Tags
telemetry•smartport•mspv2•bugfixSummary by CodeRabbit