Skip to content
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

nrf_rpc: improve UART transport stability #21013

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Damian-Nordic
Copy link
Contributor

  1. Fix one possible racy scenario in which both nRF RPC peers start at the same time
  2. Fix HDLC decoding and handling too long frames
  3. Improve ACK handling to avoid spurious retransmissions

@Damian-Nordic Damian-Nordic requested review from a team as code owners March 18, 2025 12:57
@github-actions github-actions bot added manifest changelog-entry-required Update changelog before merge. Remove label if entry is not needed or already added. labels Mar 18, 2025
@NordicBuilder
Copy link
Contributor

NordicBuilder commented Mar 18, 2025

The following west manifest projects have changed revision in this Pull Request:

Name Old Revision New Revision Diff
nrfxlib nrfconnect/sdk-nrfxlib@fcf28d8 (main) nrfconnect/sdk-nrfxlib#1681 nrfconnect/sdk-nrfxlib#1681/files

DNM label due to: 1 project with PR revision

Note: This message is automatically posted and updated by the Manifest GitHub Action.

@NordicBuilder
Copy link
Contributor

NordicBuilder commented Mar 18, 2025

CI Information

To view the history of this post, clich the 'edited' button above
Build number: 3

Inputs:

Sources:

sdk-nrf: PR head: daafadfd3f51a35894cc093b3a8659b6fb7749eb
nrfxlib: PR head: 95397acaacce27214ba5550f064e35330cecc7d7

more details

sdk-nrf:

PR head: daafadfd3f51a35894cc093b3a8659b6fb7749eb
merge base: 71ba8e3db7158e5f203ea7ccb0890ab01ed2fda9
target head (main): 762492f3d6d86efb602182ce86ce21a3be588260
Diff

nrfxlib:

PR head: 95397acaacce27214ba5550f064e35330cecc7d7
merge base: fcf28d82f64f1e21dbcd6a436cc77bc9ee0537eb
target head (main): fcf28d82f64f1e21dbcd6a436cc77bc9ee0537eb
Diff

Github labels

Enabled Name Description
ci-disabled Disable the ci execution
ci-all-test Run all of ci, no test spec filtering will be done
ci-force-downstream Force execution of downstream even if twister fails
ci-run-twister Force run twister
ci-run-zephyr-twister Force run zephyr twister
List of changed files detected by CI (3)
nrfxlib
│  ├── nrf_rpc
│  │  │ nrf_rpc.c
subsys
│  ├── nrf_rpc
│  │  │ nrf_rpc_uart.c
west.yml

Outputs:

Toolchain

Version: 4ffa2202d5
Build docker image: docker-dtr.nordicsemi.no/sw-production/ncs-build:4ffa2202d5_e579f9fbe6

Test Spec & Results: ✅ Success; ❌ Failure; 🟠 Queued; 🟡 Progress; ◻️ Skipped; ⚠️ Quarantine

  • ◻️ Toolchain - Skipped: existing toolchain is used
  • ✅ Build twister
    • sdk-nrf test count: 598
  • ✅ Integration tests
    • ✅ test-fw-nrfconnect-ble_samples
    • ✅ test-fw-nrfconnect-nrf-iot_cloud
    • ✅ test-fw-nrfconnect-rpc
    • ✅ test-fw-nrfconnect-rs
    • ✅ test-fw-nrfconnect-fem
    • ✅ test-sdk-dfu
    • ✅ test-fw-nrfconnect-ps
    • ⚠️ test_ble_nrf_config
Disabled integration tests
    • desktop52_verification
    • doc-internal
    • test-fw-nrfconnect-apps
    • test-fw-nrfconnect-boot
    • test-fw-nrfconnect-chip
    • test-fw-nrfconnect-nfc
    • test-fw-nrfconnect-nrf-iot_libmodem-nrf
    • test-fw-nrfconnect-nrf-iot_mosh
    • test-fw-nrfconnect-nrf-iot_positioning
    • test-fw-nrfconnect-nrf-iot_samples
    • test-fw-nrfconnect-nrf-iot_serial_lte_modem
    • test-fw-nrfconnect-nrf-iot_thingy91
    • test-fw-nrfconnect-nrf-iot_zephyr_lwm2m
    • test-fw-nrfconnect-nrf_crypto
    • test-fw-nrfconnect-proprietary_esb
    • test-fw-nrfconnect-tfm
    • test-fw-nrfconnect-thread
    • test-fw-nrfconnect-zigbee
    • test-low-level
    • test-sdk-audio
    • test-sdk-find-my
    • test-sdk-mcuboot
    • test-sdk-pmic-samples
    • test-sdk-wifi
    • test-secdom-samples-public

Note: This message is automatically posted and updated by the CI

@@ -176,39 +184,49 @@ static bool crc_compare(uint16_t rx_crc, uint16_t calc_crc)
return rx_crc == calc_crc;
}

static void hdlc_decode_byte(struct nrf_rpc_uart *uart_tr, uint8_t byte)
static void hdlc_decode_byte(enum hdlc_state *state, uint8_t *out, size_t *len, size_t capacity,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please stick with struct nrf_rpc_uart *uart_tr.
Returning through pointers is bug prone and you (as in this case) quickly go beyond 4 function args

Copy link
Contributor Author

@Damian-Nordic Damian-Nordic Mar 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but I wanted to reuse this function for 2 decoding states (for decoding ACKs in ISR and long packets in work queue). I thought about abstracting struct decoding_state and passing just one member instead of all these pointers, but this would result in a small RAM increase. Though I think the increase is acceptable in this case for the sake of cleaner code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added struct hdlc_decode_ctx to reduce the number of input arguments.

__fallthrough;
case HDLC_STATE_FRAME:
if (byte == HDLC_CHAR_DELIMITER) {
if (*len > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if delimiter is found without prior data? is this empty frame or protocol does not allow this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HDLC defines that the delimiter should be present at the start and end of the frame but if 2 frames are sent back to back you can either send two delimiters (end of the previous frame and start of the next frame) or just one. I think this implies that empty frames cannot be supported.

@pdunaj pdunaj requested a review from doki-nordic March 19, 2025 09:20
1. Skip incoming bytes while in the unsync state.
2. Handle receive buffer overflow.
3. Prepare hdlc_decode_byte() for multiple simultaneous
   decoding states.

Signed-off-by: Damian Krolik <damian.krolik@nordicsemi.no>
Currently, decoding both normal packets and ACKs happens
in the receive thread. This imposes certain limitations,
for example the receive thread shall not send any packets
as this would introduce a chicken-egg problem: the thread
is waiting for an ACK but the ACK can only be decoded by
the current thread.

More importantly, this can also introduce spurious ACK
timeouts and retransissions because the receive thread may
be blocked when trying to push a packet to the thead pool.

Move the ACK decoding to ISR to overcome the mentioned
issues.

Signed-off-by: Damian Krolik <damian.krolik@nordicsemi.no>
Fix one missed scenario in which transport_initialized flag
may be false because of the thread running nrf_rpc_init()
being switched out by the scheduler before setting this flag.

Signed-off-by: Damian Krolik <damian.krolik@nordicsemi.no>
Copy link

You can find the documentation preview for this PR here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog-entry-required Update changelog before merge. Remove label if entry is not needed or already added. DNM manifest manifest-nrfxlib
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants