Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

- **Breaking:** Changed the return type of `Uart16550::config(&self)` from
`(&Config, &B::Address)` to `(&Config, &B)`
- **Breaking:** `ready_to_send()` (and `send_bytes()` in turn) doesn't check
`MSR::CTS` anymore by default, as modern hardware tends to leave that pin
disconnected. This behavior is configurable through `Config::flow_control`.
Additionally, for manual checks, users can check
`if device.msr().contains(MSR::CTS) {}`.

## 0.6.0 - 2026-03-28

Expand Down
7 changes: 7 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ pub struct Config {
pub extra_stop_bits: bool,
/// Whether parity bits should be used.
pub parity: Parity,
/// Whether to wait for CTS before sending.
///
/// Only activate this if your hardware connects the CTS/RTS flow control
/// signals and you wish to make use of them. Keep this setting disabled to
/// make sure that the UART works when CTS is left disconnected.
pub flow_control: bool,
}

impl Config {
Expand All @@ -176,6 +182,7 @@ impl Config {
data_bits: WordLength::EightBits,
extra_stop_bits: false,
parity: Parity::Disabled,
flow_control: false,
};
}

Expand Down
14 changes: 10 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,6 @@ impl<B: Backend> Uart16550<B> {
/// an established connection.
pub fn ready_to_send(&mut self) -> Result<(), ByteSendError> {
let lsr = self.lsr();
let msr = self.msr();
let mcr = self.mcr();

// In FIFO mode, this bit is set when the transmitter’s FIFO is
// completely empty, being 0 if there is at least one byte in the
Expand All @@ -681,8 +679,16 @@ impl<B: Backend> Uart16550<B> {

// Software flow control. TODO, what to do with hardware flow control?
// Is this something we can and should support?
Comment on lines 680 to 681

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is this a stale comment?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Now that you mention it, possibly so? I previously assumed that "software flow control" meant "we're driving the flow control lines manually instead of configuring the UART to do it for us", but now that I've looked it up, it appears that software flow control usually refers to using the ASCII XON/XOFF characters for in-band signaling.

@phip1611 phip1611 Aug 14, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm also not 100 percent sure about software and hardware flow control. I tried my best by reading the spec and experimenting on real hardware. Any improvement to the (likely unnecessary?) comment is highly appreciated

We might also just remove that comment. WDYT @meithecatte?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I can take care of the comment in a follow-up. thanks for your contribution. Highly appreciated!

if !mcr.contains(MCR::LOOP_BACK) && !msr.contains(MSR::CTS) {
return Err(ByteSendError::RemoteNotClearToSend);
if self.config.flow_control {
// The CTS line is meaningless when in loopback mode.
let mcr = self.mcr();
if !mcr.contains(MCR::LOOP_BACK) {
let msr = self.msr();

if !msr.contains(MSR::CTS) {
return Err(ByteSendError::RemoteNotClearToSend);
}
}
}

Ok(())
Expand Down