Skip to content

Comments

nrf: Add stop_rx() and flush_rx() to NRF UART#5460

Open
de-vri-es wants to merge 2 commits intoembassy-rs:mainfrom
de-vri-es:nrf-uarte-flush-rx
Open

nrf: Add stop_rx() and flush_rx() to NRF UART#5460
de-vri-es wants to merge 2 commits intoembassy-rs:mainfrom
de-vri-es:nrf-uarte-flush-rx

Conversation

@de-vri-es
Copy link
Contributor

This PR exposes the ability to flush the internal UART RX FIFO without enabling the receiver (by doing a read).

This can be useful to either retrieve the last bit of data that you already received, or to purge the RX FIFO.

I want to do that latter in this case, because I have a half-duplex serial bus and all data that gets send is also seen on the RX pin. I want to purge the RX FIFO of any data that was accidentally written to ourselves before activating the receiver (which can also happen because the receiver can still read 4 bytes after being stopped).

@lulf
Copy link
Member

lulf commented Feb 16, 2026

Needs some transforms added to nrf-pac to correct the register names perhaps? https://github.com/embassy-rs/nrf-pac/blob/main/transform-extra.yaml (or maybe not available on all chip families, I haven't looked in detail).

@de-vri-es
Copy link
Contributor Author

Ah, hmm, for the nrf54l family, the task is not called TASK_DM.RX.FLUSHRX but just TASK_FLUSHRX:

image

Best to just stick with that in the PAC, I guess?

Although for the NRF9160 I was basing this off, none of the tasks have a TASK_DMA prefix:

image

I'm not familiar with the rewrite rules in the PAC generation. Do you think it's better to rename things there are use a cfg in embassy_nrf like I did now? It's a bit surprising that the PAC renames registers, but I assume it's to avoid cfg spam in the high level crate?

@lulf
Copy link
Member

lulf commented Feb 17, 2026

Ah, hmm, for the nrf54l family, the task is not called TASK_DM.RX.FLUSHRX but just TASK_FLUSHRX:
image

Best to just stick with that in the PAC, I guess?

Although for the NRF9160 I was basing this off, none of the tasks have a TASK_DMA prefix:
image

I'm not familiar with the rewrite rules in the PAC generation. Do you think it's better to rename things there are use a cfg in embassy_nrf like I did now? It's a bit surprising that the PAC renames registers, but I assume it's to avoid cfg spam in the high level crate?

Yes, this is exactly the reason. I think in this case, what's happening is that it's rewriting the nrf52 flushrx accidentally (https://github.com/embassy-rs/nrf-pac/blob/main/transform-extra.yaml#L219 - only run for non-nrf54), so that regex need to be adjusted.

@de-vri-es de-vri-es force-pushed the nrf-uarte-flush-rx branch 2 times, most recently from 5934e1c to 962ade8 Compare February 17, 2026 11:59
@de-vri-es
Copy link
Contributor Author

de-vri-es commented Feb 17, 2026

Ok, opened a PR here to adjust the generated bindings: embassy-rs/nrf-pac#16

In the mean time, I also adjusted this PR to expose stop_rx() to users, as I also really need to stop the receiver when I start sending.

Also adjusted this PR to use the updated PAC already, but I assume that should be merged first ^_^

/edit: Updated to use the merge commit from the main branch now.

@de-vri-es
Copy link
Contributor Author

de-vri-es commented Feb 17, 2026

Hmm, the CI failure seems odd:

error: failed to run custom build command for `nrf-pac v0.2.0 (https://github.com/embassy-rs/nrf-pac.git?rev=074935b9b24ab302fe812f91725937f57cd082cf#074935b9)`

Caused by:
  process didn't exit successfully: `/ci/cache/target/release/build/nrf-pac-b7acaa83f4f618c4/build-script-build` (exit status: 101)
  --- stderr

  thread 'main' (1455) panicked at /ci/cache/cargo/git/checkouts/nrf-pac-5434cf7d907da92b/074935b/build.rs:10:35:
  No nrfxx Cargo feature enabled
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
Error: Failed to execute cargo subcommand `cargo batch --- build --release --manifest-path=/ci/code/docs/examples/layer-by-layer/blinky-async/Carg... (58712 chars)`
run failed: exited with code 1

"No nrfxxx Cargo feature enabled"

I don't see how my changes could have caused that :o

The blinky-async example doesn't even use embassy-nrf or nrf-pac.

/edit: Ah, it must be some other command in the 58712 chars passed to cargo batch :]

/edit: I get the feeling that CI is running cargo build on nrf-pac without any features. But how would that ever have worked?

@Dirbaio
Copy link
Member

Dirbaio commented Feb 17, 2026

No nrfxxx Cargo feature enabled

replace nrf-pac to the exact same git version in all cargo.tomls in this repo, then it'll work.

@de-vri-es
Copy link
Contributor Author

Yay, that worked! Thanks!

@de-vri-es de-vri-es changed the title nrf: Add flush_rx to NRF UART nrf: Add stop_rx() and flush_rx() to NRF UART Feb 17, 2026
@de-vri-es de-vri-es marked this pull request as draft February 17, 2026 13:06
@de-vri-es
Copy link
Contributor Author

de-vri-es commented Feb 17, 2026

Note: it seems that the RXTO event is not guaranteed to fire if the receiver was already off when you trigger the STOPRX task. But there is also no status flag to see if the receiver is currently on or off..

No, the problem was just that the interrupt handler wasn't updated.

It was both.

@de-vri-es de-vri-es force-pushed the nrf-uarte-flush-rx branch 2 times, most recently from f0b100c to b4003a1 Compare February 17, 2026 14:18
@de-vri-es
Copy link
Contributor Author

de-vri-es commented Feb 17, 2026

Ok, also adjusted the UARTE driver now to preserve the status of the receiver in the RXTO bit: it will be 1 if the receiver is off.

The bit is now cleared when the driver starts the receiver, and set by the hardware. Additionally, there's a rx_on flag to remember if the receiver was started, since the receiver starts off but the RXTO bit starts cleared.

This prevents stop_rx() from hanging indefinitely if called when the receiver is already off.

@de-vri-es de-vri-es marked this pull request as ready for review February 17, 2026 15:37
r: pac::uarte::Uarte,
state: &'static State,
_p: PhantomData<&'d ()>,
rx_on: bool,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not too happy to add this, but I don't see a way to avoid this:

Even if you only clear RXTO when starting the receiver, the initial state of the RXTO bit does not match the state of the receiver. I tried manually fixing the RXTO bit on startupt, but writing a 1 is ignored.

So the only way to avoid stop_rx() from hanging if the receiver is already off, is to remember ourselves that it is off :(

@de-vri-es de-vri-es requested a review from lulf February 17, 2026 15:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants