Skip to content

Commit 0117973

Browse files
dbrgnTheZoq2
authored andcommitted
Implement Read<u8> / Write<u8> on Serial type
1 parent 9a59273 commit 0117973

File tree

3 files changed

+78
-25
lines changed

3 files changed

+78
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88
## [Unreleased]
99

1010
- Add `InputPin` impl for generic open drain outputs
11+
- Implement `Read<u8>` / `Write<u8>` for `Serial` (#171)
1112

1213
## [v0.5.2] - 2019-12-15
1314

examples/serial.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ fn main() -> ! {
5959

6060
// Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of
6161
// the registers are used to enable and configure the device.
62-
let serial = Serial::usart3(
62+
let mut serial = Serial::usart3(
6363
p.USART3,
6464
(tx, rx),
6565
&mut afio.mapr,
@@ -68,22 +68,29 @@ fn main() -> ! {
6868
&mut rcc.apb1,
6969
);
7070

71-
// Split the serial struct into a receiving and a transmitting part
72-
let (mut tx, mut rx) = serial.split();
7371

72+
// Loopback test. Write `X` and wait until the write is successful.
7473
let sent = b'X';
75-
76-
// Write `X` and wait until the write is successful
77-
block!(tx.write(sent)).ok();
74+
block!(serial.write(sent)).ok();
7875

7976
// Read the byte that was just sent. Blocks until the read is complete
80-
let received = block!(rx.read()).unwrap();
77+
let received = block!(serial.read()).unwrap();
8178

8279
// Since we have connected tx and rx, the byte we sent should be the one we received
8380
assert_eq!(received, sent);
8481

8582
// Trigger a breakpoint to allow us to inspect the values
8683
asm::bkpt();
8784

85+
86+
// You can also split the serial struct into a receiving and a transmitting part
87+
let (mut tx, mut rx) = serial.split();
88+
let sent = b'Y';
89+
block!(tx.write(sent)).ok();
90+
let received = block!(rx.read()).unwrap();
91+
assert_eq!(received, sent);
92+
asm::bkpt();
93+
94+
8895
loop {}
8996
}

src/serial.rs

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! # Serial Communication (USART)
2+
//!
23
//! This module contains the functions to utilize the USART (Universal
34
//! synchronous asynchronous receiver transmitter)
45
//!
5-
//!
66
//! ## Example usage:
7+
//!
78
//! ```rust
89
//! // prelude: create handles to the peripherals and registers
910
//! let p = crate::pac::Peripherals::take().unwrap();
@@ -113,6 +114,16 @@ impl Pins<USART3> for (PD8<Alternate<PushPull>>, PD9<Input<Floating>>) {
113114
const REMAP: u8 = 0b11;
114115
}
115116

117+
/// Internal trait for the serial read / write logic.
118+
///
119+
/// Note that reading / writing is done on the USART peripheral, not on the
120+
/// rx / tx pins!
121+
trait UsartReadWrite<Word> {
122+
fn read() -> nb::Result<Word, Error>;
123+
fn write(byte: Word) -> nb::Result<(), Infallible>;
124+
fn flush() -> nb::Result<(), Infallible>;
125+
}
126+
116127
pub enum Parity {
117128
ParityNone,
118129
ParityEven,
@@ -346,10 +357,8 @@ macro_rules! hal {
346357
}
347358
}
348359

349-
impl crate::hal::serial::Read<u8> for Rx<$USARTX> {
350-
type Error = Error;
351-
352-
fn read(&mut self) -> nb::Result<u8, Error> {
360+
impl UsartReadWrite<u8> for $USARTX {
361+
fn read() -> nb::Result<u8, Error> {
353362
// NOTE(unsafe) atomic read with no side effects
354363
let sr = unsafe { (*$USARTX::ptr()).sr.read() };
355364

@@ -389,38 +398,74 @@ macro_rules! hal {
389398
}
390399
}
391400
}
392-
}
393-
394-
impl crate::hal::serial::Write<u8> for Tx<$USARTX> {
395-
type Error = Infallible;
396401

397-
fn flush(&mut self) -> nb::Result<(), Self::Error> {
402+
fn write(byte: u8) -> nb::Result<(), Infallible> {
398403
// NOTE(unsafe) atomic read with no side effects
399404
let sr = unsafe { (*$USARTX::ptr()).sr.read() };
400405

401-
if sr.tc().bit_is_set() {
406+
if sr.txe().bit_is_set() {
407+
// NOTE(unsafe) atomic write to stateless register
408+
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
409+
unsafe {
410+
ptr::write_volatile(&(*$USARTX::ptr()).dr as *const _ as *mut _, byte)
411+
}
402412
Ok(())
403413
} else {
404414
Err(nb::Error::WouldBlock)
405415
}
406416
}
407417

408-
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
418+
fn flush() -> nb::Result<(), Infallible> {
409419
// NOTE(unsafe) atomic read with no side effects
410420
let sr = unsafe { (*$USARTX::ptr()).sr.read() };
411421

412-
if sr.txe().bit_is_set() {
413-
// NOTE(unsafe) atomic write to stateless register
414-
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
415-
unsafe {
416-
ptr::write_volatile(&(*$USARTX::ptr()).dr as *const _ as *mut _, byte)
417-
}
422+
if sr.tc().bit_is_set() {
418423
Ok(())
419424
} else {
420425
Err(nb::Error::WouldBlock)
421426
}
422427
}
423428
}
429+
430+
impl crate::hal::serial::Read<u8> for Rx<$USARTX> {
431+
type Error = Error;
432+
433+
fn read(&mut self) -> nb::Result<u8, Error> {
434+
$USARTX::read()
435+
}
436+
}
437+
438+
impl crate::hal::serial::Write<u8> for Tx<$USARTX> {
439+
type Error = Infallible;
440+
441+
fn flush(&mut self) -> nb::Result<(), Self::Error> {
442+
$USARTX::flush()
443+
}
444+
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
445+
$USARTX::write(byte)
446+
}
447+
}
448+
449+
impl<PINS> crate::hal::serial::Read<u8> for Serial<$USARTX, PINS> {
450+
type Error = Error;
451+
452+
fn read(&mut self) -> nb::Result<u8, Error> {
453+
$USARTX::read()
454+
}
455+
}
456+
457+
impl<PINS> crate::hal::serial::Write<u8> for Serial<$USARTX, PINS> {
458+
type Error = Infallible;
459+
460+
fn flush(&mut self) -> nb::Result<(), Self::Error> {
461+
$USARTX::flush()
462+
}
463+
464+
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
465+
$USARTX::write(byte)
466+
}
467+
}
468+
424469
)+
425470
}
426471
}

0 commit comments

Comments
 (0)