Skip to content

Commit

Permalink
Add support for reconfiguring a Serial port
Browse files Browse the repository at this point in the history
Example use case is to implement a 1-Wire Bus "Master" [1]. In that
example, the UART is used instead of bit-banging the 1-Wire protocol.
However, not all signals can be generated with a single baud rate. In
particular, the 1-wire reset strobe is much longer than the 1-wire data
strobes, requiring to use a different, slower baud rate to reset
devices.

   [1]: https://www.maximintegrated.com/en/design/technical-documents/tutorials/2/214.html

Signed-off-by: Jonas Schäfer <j.wielicki@sotecware.net>
  • Loading branch information
horazont committed Jan 7, 2022
1 parent c62c997 commit 0da1409
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Added

- Serial can now be reconfigured, allowing to change e.g. the baud rate after initialisation.

## [v0.8.0] - 2021-12-29

### Breaking changes
Expand Down
41 changes: 31 additions & 10 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,19 @@ where
USART::reset(rcc);

remap();
self.apply_config(config, clocks);

// UE: enable USART
// RE: enable receiver
// TE: enable transceiver
self.usart
.cr1
.modify(|_r, w| w.ue().set_bit().re().set_bit().te().set_bit());

self
}

fn apply_config(&self, config: Config, clocks: Clocks) {
// Configure baud rate
let brr = USART::get_frequency(&clocks).0 / config.baudrate.0;
assert!(brr >= 16, "impossible baud rate");
Expand Down Expand Up @@ -267,16 +280,24 @@ where
StopBits::STOP1P5 => 0b11,
};
self.usart.cr2.modify(|_r, w| w.stop().bits(stop_bits));

// UE: enable USART
// RE: enable receiver
// TE: enable transceiver
self.usart
.cr1
.modify(|_r, w| w.ue().set_bit().re().set_bit().te().set_bit());

self
}
}

/// Reconfigure the USART instance.
///
/// If a transmission is currently in progress, this returns
/// [`nb::Error::WouldBlock`].
pub fn reconfigure(&mut self, config: impl Into<Config>, clocks: Clocks) -> nb::Result<(), ()> {
let sr = self.usart.sr.read();
// if we're currently busy transmitting, we have to wait until that is
// over -- regarding reception, we assume that the caller -- with
// exclusive access to the Serial instance due to &mut self -- knows
// what they're doing.
if sr.tc().bit_is_clear() {
return nb::Result::Err(nb::Error::WouldBlock)
}
self.apply_config(config.into(), clocks);
nb::Result::Ok(())
}

/// Starts listening to the USART by enabling the _Received data
/// ready to be read (RXNE)_ interrupt and _Transmit data
Expand Down

0 comments on commit 0da1409

Please sign in to comment.