Skip to content

Commit 86e3d76

Browse files
techmccatusbalbin
authored andcommitted
serial: implement embedded-io traits for UART
1 parent 01d88f7 commit 86e3d76

File tree

3 files changed

+129
-25
lines changed

3 files changed

+129
-25
lines changed

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ repository = "https://github.com/stm32-rs/stm32g4xx-hal"
1212
version = "0.0.2"
1313

1414
[dependencies]
15-
nb = "0.1.1"
15+
nb = "1"
1616
stm32g4 = "0.15.1"
1717
paste = "1.0"
1818
bitflags = "1.2"
@@ -21,6 +21,7 @@ static_assertions = "1.1"
2121
fugit = "0.3.7"
2222
stm32-usbd = { version = "0.7.0", optional = true }
2323
fixed = { version = "1.28.0", optional = true }
24+
embedded-io = "0.6"
2425

2526
[dependencies.cortex-m]
2627
version = "0.7.7"
@@ -99,7 +100,7 @@ stm32g4a1 = ["stm32g4/stm32g4a1"]
99100
log-itm = ["cortex-m-log/itm"]
100101
log-rtt = []
101102
log-semihost = ["cortex-m-log/semihosting"]
102-
defmt = ["dep:defmt", "fugit/defmt"]
103+
defmt = ["dep:defmt", "fugit/defmt", "nb/defmt-0-3", "embedded-hal-one/defmt-03", "embedded-io/defmt-03"]
103104
cordic = ["dep:fixed"]
104105

105106
[profile.dev]

examples/uart.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
#![no_main]
44
#![no_std]
55

6-
use core::fmt::Write;
7-
6+
use embedded_io::{Read, Write};
87
use hal::prelude::*;
98
use hal::pwr::PwrExt;
109
use hal::serial::FullConfig;
@@ -54,10 +53,13 @@ fn main() -> ! {
5453
.unwrap();
5554

5655
writeln!(usart, "Hello USART3, yay!!\r\n").unwrap();
56+
let mut read_buf = [0u8; 8];
57+
usart.read_exact(&mut read_buf).unwrap();
58+
usart.write_all(&read_buf).unwrap();
5759

5860
let mut cnt = 0;
5961
loop {
60-
match block!(usart.read()) {
62+
match block!(embedded_hal::serial::Read::read(&mut usart)) {
6163
Ok(byte) => writeln!(usart, "{}: {}\r", cnt, byte).unwrap(),
6264
Err(e) => writeln!(usart, "E: {:?}\r", e).unwrap(),
6365
};

src/serial/usart.rs

Lines changed: 121 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::stm32::*;
1212

1313
use cortex_m::interrupt;
1414
use nb::block;
15+
use embedded_io::{ReadReady, WriteReady};
1516

1617
use crate::serial::config::*;
1718
/// Serial error
@@ -27,6 +28,17 @@ pub enum Error {
2728
Parity,
2829
}
2930

31+
impl embedded_io::Error for Error {
32+
fn kind(&self) -> embedded_io::ErrorKind {
33+
match self {
34+
Error::Framing => embedded_io::ErrorKind::InvalidData,
35+
Error::Noise => embedded_io::ErrorKind::InvalidData,
36+
Error::Overrun => embedded_io::ErrorKind::Other,
37+
Error::Parity => embedded_io::ErrorKind::InvalidData,
38+
}
39+
}
40+
}
41+
3042
/// Interrupt event
3143
pub enum Event {
3244
/// TXFIFO reaches the threshold
@@ -202,6 +214,29 @@ macro_rules! uart_shared {
202214
_dma: PhantomData,
203215
}
204216
}
217+
fn data_ready(&mut self) -> nb::Result<(), Error> {
218+
let usart = unsafe { &(*$USARTX::ptr()) };
219+
let isr = usart.isr.read();
220+
Err(
221+
if isr.pe().bit_is_set() {
222+
usart.icr.write(|w| w.pecf().set_bit());
223+
nb::Error::Other(Error::Parity)
224+
} else if isr.fe().bit_is_set() {
225+
usart.icr.write(|w| w.fecf().set_bit());
226+
nb::Error::Other(Error::Framing)
227+
} else if isr.nf().bit_is_set() {
228+
usart.icr.write(|w| w.ncf().set_bit());
229+
nb::Error::Other(Error::Noise)
230+
} else if isr.ore().bit_is_set() {
231+
usart.icr.write(|w| w.orecf().set_bit());
232+
nb::Error::Other(Error::Overrun)
233+
} else if isr.rxne().bit_is_set() {
234+
return Ok(())
235+
} else {
236+
nb::Error::WouldBlock
237+
}
238+
)
239+
}
205240
}
206241

207242
impl<Pin> Rx<$USARTX, Pin, DMA> {
@@ -225,26 +260,7 @@ macro_rules! uart_shared {
225260

226261
fn read(&mut self) -> nb::Result<u8, Error> {
227262
let usart = unsafe { &(*$USARTX::ptr()) };
228-
let isr = usart.isr.read();
229-
Err(
230-
if isr.pe().bit_is_set() {
231-
usart.icr.write(|w| w.pecf().set_bit());
232-
nb::Error::Other(Error::Parity)
233-
} else if isr.fe().bit_is_set() {
234-
usart.icr.write(|w| w.fecf().set_bit());
235-
nb::Error::Other(Error::Framing)
236-
} else if isr.nf().bit_is_set() {
237-
usart.icr.write(|w| w.ncf().set_bit());
238-
nb::Error::Other(Error::Noise)
239-
} else if isr.ore().bit_is_set() {
240-
usart.icr.write(|w| w.orecf().set_bit());
241-
nb::Error::Other(Error::Overrun)
242-
} else if isr.rxne().bit_is_set() {
243-
return Ok(usart.rdr.read().bits() as u8)
244-
} else {
245-
nb::Error::WouldBlock
246-
}
247-
)
263+
self.data_ready().map(|_| usart.rdr.read().bits() as u8)
248264
}
249265
}
250266

@@ -349,6 +365,91 @@ macro_rules! uart_shared {
349365
}
350366
}
351367

368+
impl<Pin> embedded_io::ErrorType for Tx<$USARTX, Pin, NoDMA> {
369+
type Error = Error;
370+
}
371+
impl<Pin> WriteReady for Tx<$USARTX, Pin, NoDMA> {
372+
fn write_ready(&mut self) -> Result<bool, Self::Error> {
373+
let usart = unsafe { &(*$USARTX::ptr()) };
374+
Ok(usart.isr.read().txe().bit_is_set())
375+
}
376+
}
377+
// writes until fifo (or tdr) is full
378+
impl<Pin> embedded_io::Write for Tx<$USARTX, Pin, NoDMA> {
379+
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
380+
if buf.len() == 0 { return Ok(0) }
381+
let usart = unsafe { &(*$USARTX::ptr()) };
382+
while !self.write_ready()? {
383+
core::hint::spin_loop()
384+
}
385+
// can't know fifo capacity in advance
386+
let count = buf.into_iter()
387+
.take_while(|_| usart.isr.read().txe().bit_is_set())
388+
.map(|b| usart.tdr.write(|w| unsafe { w.tdr().bits(*b as u16) }))
389+
.count();
390+
391+
Ok(count)
392+
}
393+
fn flush(&mut self) -> Result<(), Error> {
394+
nb::block!(hal::serial::Write::<u8>::flush(self))
395+
}
396+
}
397+
398+
impl<Pin> embedded_io::ErrorType for Rx<$USARTX, Pin, NoDMA> {
399+
type Error = Error;
400+
}
401+
impl<Pin> ReadReady for Rx<$USARTX, Pin, NoDMA> {
402+
fn read_ready(&mut self) -> Result<bool, Self::Error> {
403+
match self.data_ready() {
404+
Ok(()) => Ok(true),
405+
Err(nb::Error::WouldBlock) => Ok(false),
406+
Err(nb::Error::Other(e)) => Err(e),
407+
}
408+
}
409+
}
410+
impl<Pin> embedded_io::Read for Rx<$USARTX, Pin, NoDMA> {
411+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
412+
if buf.len() == 0 { return Ok(0) }
413+
let usart = unsafe { &(*$USARTX::ptr()) };
414+
let mut count = 0;
415+
416+
while !self.read_ready()? {
417+
core::hint::spin_loop()
418+
}
419+
while self.read_ready()? && count < buf.len() {
420+
buf[count] = usart.rdr.read().bits() as u8;
421+
count += 1
422+
}
423+
Ok(count)
424+
}
425+
}
426+
427+
impl<TX, RX> embedded_io::ErrorType for Serial<$USARTX, TX, RX> {
428+
type Error = Error;
429+
}
430+
impl<TX, RX> WriteReady for Serial<$USARTX, TX, RX> {
431+
fn write_ready(&mut self) -> Result<bool, Self::Error> {
432+
self.tx.write_ready()
433+
}
434+
}
435+
impl<TX, RX> embedded_io::Write for Serial<$USARTX, TX, RX> {
436+
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
437+
embedded_io::Write::write(&mut self.tx, buf)
438+
}
439+
fn flush(&mut self) -> Result<(), Error> {
440+
embedded_io::Write::flush(&mut self.tx)
441+
}
442+
}
443+
impl<TX, RX> ReadReady for Serial<$USARTX, TX, RX> {
444+
fn read_ready(&mut self) -> Result<bool, Self::Error> {
445+
self.rx.read_ready()
446+
}
447+
}
448+
impl<TX, RX> embedded_io::Read for Serial<$USARTX, TX, RX> {
449+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
450+
embedded_io::Read::read(&mut self.rx, buf)
451+
}
452+
}
352453

353454
impl<TX, RX> Serial<$USARTX, TX, RX> {
354455

0 commit comments

Comments
 (0)