Skip to content

Commit aa849e1

Browse files
committed
eh-1.0.0: serial
1 parent 407eaf7 commit aa849e1

File tree

7 files changed

+114
-72
lines changed

7 files changed

+114
-72
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
* pwm: `enable` method now returns type `Result<(), PwmError>`
1111
* pwm: LPTIMs can return a `NotEnabled` error from `set_duty_cycle`
1212

13+
* serial: Implement embedded-io `Read` and `Write` traits
14+
* serial: Rename methods `read` -> `read_byte`; `write` -> `write_byte`
15+
1316
## [v0.15.1] 2023-11-03
1417

1518
* Bugfix, usb: On RM0455 and RM0468 parts, PA11/PA12 do not have an alternate function

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ rustdoc-args = ["--cfg", "docsrs"]
3030
fugit = "0.3.5"
3131
embedded-hal = { version = "=1.0.0-rc.3" }
3232
embedded-dma = "0.2.0"
33+
embedded-io = "0.6.1"
3334
cortex-m = { version = "^0.7.7", features = ["critical-section-single-core"] }
3435
defmt = { version = ">=0.2.0,<0.4", optional = true }
3536
stm32h7 = { version = "^0.15.1", default-features = false }

examples/serial-advanced.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ use cortex_m_rt::entry;
88
mod utilities;
99
use log::info;
1010

11+
use embedded_io::Write;
1112
use stm32h7xx_hal::{pac, prelude::*, serial::config::Config};
1213

13-
use core::fmt::Write;
14-
1514
#[entry]
1615
fn main() -> ! {
1716
utilities::logger::init();

examples/serial-halfduplex.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ fn main() -> ! {
7171
loop {
7272
// Tx from usart3
7373
for c in "Hello, world!".chars() {
74-
block!(usart3.write(c as u8)).unwrap();
75-
let received = block!(usart6.read()).unwrap();
74+
block!(usart3.write_byte(c as u8)).unwrap();
75+
let received = block!(usart6.read_byte()).unwrap();
7676
info!("usart6 rx {}", received as char);
7777
}
7878

7979
// Tx from usart6
8080
for c in "Hello, world!".chars() {
81-
block!(usart6.write(c as u8)).unwrap();
82-
let received = block!(usart3.read()).unwrap();
81+
block!(usart6.write_byte(c as u8)).unwrap();
82+
let received = block!(usart3.read_byte()).unwrap();
8383
info!("usart3 rx {}", received as char);
8484
}
8585
}

examples/serial-inverted-loopback.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ use cortex_m_rt::entry;
1212
mod utilities;
1313
use log::info;
1414

15+
use embedded_io::Write;
1516
use stm32h7xx_hal::{pac, prelude::*, serial};
1617

17-
use core::fmt::Write;
18-
1918
use nb::block;
2019

2120
#[entry]
@@ -60,9 +59,9 @@ fn main() -> ! {
6059

6160
loop {
6261
// Echo what is received on the serial link.
63-
let received = block!(rx.read()).unwrap();
62+
let received = block!(rx.read_byte()).unwrap();
6463
asm::delay(1000);
6564
info!("rx {}", received as char);
66-
block!(tx.write(received)).ok();
65+
block!(tx.write_byte(received)).ok();
6766
}
6867
}

examples/serial.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ use cortex_m_rt::entry;
1010
mod utilities;
1111
use log::info;
1212

13+
use embedded_io::Write;
1314
use stm32h7xx_hal::{pac, prelude::*};
1415

15-
use core::fmt::Write;
16-
1716
use nb::block;
1817

1918
#[entry]
@@ -55,7 +54,7 @@ fn main() -> ! {
5554

5655
loop {
5756
// Echo what is received on the serial link.
58-
let received = block!(rx.read()).unwrap();
59-
block!(tx.write(received)).ok();
57+
let received = block!(rx.read_byte()).unwrap();
58+
block!(tx.write_byte(received)).ok();
6059
}
6160
}

src/serial.rs

Lines changed: 99 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
//! - [Inverted Signal Levels](https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/serial-inverted-loopback.rs)
99
1010
use core::cell::UnsafeCell;
11-
use core::fmt;
11+
use core::convert::Infallible;
1212
use core::marker::PhantomData;
1313
use core::ptr;
1414

15-
use embedded_hal::blocking::serial as serial_block;
16-
use embedded_hal::prelude::*;
17-
use embedded_hal::serial;
18-
use nb::block;
15+
// use embedded_hal::blocking::serial as serial_block;
16+
// use embedded_hal::prelude::*;
17+
// use embedded_hal::serial;
18+
use embedded_io as eio;
1919

2020
use stm32::usart1::cr2::{
2121
CLKEN_A, CPHA_A, CPOL_A, LBCL_A, MSBFIRST_A, RXINV_A, TXINV_A,
@@ -44,6 +44,8 @@ use crate::time::Hertz;
4444
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
4545
#[non_exhaustive]
4646
pub enum Error {
47+
/// An attempted write could not write any data
48+
WriteZero,
4749
/// Framing error
4850
Framing,
4951
/// Noise error
@@ -53,6 +55,14 @@ pub enum Error {
5355
/// Parity check error
5456
Parity,
5557
}
58+
impl eio::Error for Error {
59+
fn kind(&self) -> eio::ErrorKind {
60+
match self {
61+
Error::WriteZero => eio::ErrorKind::WriteZero,
62+
_ => eio::ErrorKind::Other,
63+
}
64+
}
65+
}
5666

5767
/// Interrupt event
5868
#[derive(Copy, Clone, PartialEq, Eq)]
@@ -964,22 +974,60 @@ macro_rules! usart {
964974
}
965975
}
966976

967-
impl serial::Read<u8> for Serial<$USARTX> {
968-
type Error = Error;
977+
// Implement embedded_io::Write
969978

970-
fn read(&mut self) -> nb::Result<u8, Error> {
979+
impl eio::ErrorType for Serial<$USARTX> {
980+
type Error = Error;
981+
}
982+
impl eio::Read for Serial<$USARTX> {
983+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
971984
let mut rx: Rx<$USARTX> = Rx {
972985
_usart: PhantomData,
973986
ker_ck: self.ker_ck,
974987
};
975-
rx.read()
988+
rx.read(buf)
976989
}
977990
}
978-
979-
impl serial::Read<u8> for Rx<$USARTX> {
991+
impl eio::ErrorType for Rx<$USARTX> {
980992
type Error = Error;
993+
}
994+
impl eio::Read for Rx<$USARTX> {
995+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
996+
for (i, byte) in buf.iter_mut().enumerate() {
997+
while true {
998+
match self.read_byte() {
999+
Ok(b) => {
1000+
*byte = b;
1001+
continue;
1002+
},
1003+
Err(nb::Error::WouldBlock) => {
1004+
if i > 0 {
1005+
return Ok(i);
1006+
}
1007+
},
1008+
Err(nb::Error::Other(e)) => {
1009+
return Err(e);
1010+
}
1011+
}
1012+
}
1013+
}
1014+
Ok(buf.len())
1015+
}
1016+
}
9811017

982-
fn read(&mut self) -> nb::Result<u8, Error> {
1018+
impl Serial<$USARTX> {
1019+
/// Reads a single word from the serial interface
1020+
pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
1021+
let mut rx: Rx<$USARTX> = Rx {
1022+
_usart: PhantomData,
1023+
ker_ck: self.ker_ck,
1024+
};
1025+
rx.read_byte()
1026+
}
1027+
}
1028+
impl Rx<$USARTX> {
1029+
/// Reads a single word from the serial interface
1030+
pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
9831031
// NOTE(unsafe) atomic read with no side effects
9841032
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
9851033

@@ -1004,9 +1052,7 @@ macro_rules! usart {
10041052
nb::Error::WouldBlock
10051053
})
10061054
}
1007-
}
10081055

1009-
impl Rx<$USARTX> {
10101056
/// Start listening for `Rxne` event
10111057
pub fn listen(&mut self) {
10121058
// unsafe: rxneie bit accessed by Rx part only
@@ -1064,49 +1110,66 @@ macro_rules! usart {
10641110
}
10651111
}
10661112

1067-
impl serial::Write<u8> for Serial<$USARTX> {
1068-
type Error = core::convert::Infallible;
1113+
// Implement embedded_io::Write
10691114

1070-
fn flush(&mut self) -> nb::Result<(), Self::Error> {
1115+
impl eio::Write for Serial<$USARTX> {
1116+
fn flush(&mut self) -> Result<(), Error> {
10711117
let mut tx: Tx<$USARTX> = Tx {
10721118
_usart: PhantomData,
10731119
};
10741120
tx.flush()
10751121
}
1076-
1077-
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
1122+
fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
10781123
let mut tx: Tx<$USARTX> = Tx {
10791124
_usart: PhantomData,
10801125
};
1081-
tx.write(byte)
1126+
tx.write(buf)
10821127
}
10831128
}
1129+
impl eio::ErrorType for Tx<$USARTX> {
1130+
type Error = Error;
1131+
}
1132+
impl eio::Write for Tx<$USARTX> {
1133+
fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
1134+
for (i, byte) in buf.iter().enumerate() {
1135+
if self.write_byte(*byte).is_ok() {
1136+
continue;
1137+
} else if i == 0 {
1138+
return Err(Error::WriteZero);
1139+
} else {
1140+
return Ok(i);
1141+
}
1142+
}
1143+
Ok(buf.len())
1144+
}
1145+
fn flush(&mut self) -> Result<(), Error> {
1146+
// NOTE(unsafe) atomic read with no side effects
1147+
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
10841148

1085-
impl serial_block::write::Default<u8> for Serial<$USARTX> {
1086-
//implement marker trait to opt-in to default blocking write implementation
1149+
while !isr.tc().bit_is_set() {}
1150+
Ok(())
1151+
}
10871152
}
10881153

1089-
impl serial::Write<u8> for Tx<$USARTX> {
1154+
impl Serial<$USARTX> {
1155+
/// Writes a single word to the serial interface
1156+
pub fn write_byte(&mut self, byte: u8) -> nb::Result<(), Infallible> {
1157+
let mut tx: Tx<$USARTX> = Tx {
1158+
_usart: PhantomData,
1159+
};
1160+
tx.write_byte(byte)
1161+
}
1162+
}
1163+
impl Tx<$USARTX> {
10901164
// NOTE(Void) See section "29.7 USART interrupts"; the
10911165
// only possible errors during transmission are: clear
10921166
// to send (which is disabled in this case) errors and
10931167
// framing errors (which only occur in SmartCard
10941168
// mode); neither of these apply to our hardware
10951169
// configuration
1096-
type Error = core::convert::Infallible;
1097-
1098-
fn flush(&mut self) -> nb::Result<(), Self::Error> {
1099-
// NOTE(unsafe) atomic read with no side effects
1100-
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
1101-
1102-
if isr.tc().bit_is_set() {
1103-
Ok(())
1104-
} else {
1105-
Err(nb::Error::WouldBlock)
1106-
}
1107-
}
11081170

1109-
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
1171+
/// Writes a single word to the serial interface
1172+
pub fn write_byte(&mut self, byte: u8) -> nb::Result<(), Infallible> {
11101173
// NOTE(unsafe) atomic read with no side effects
11111174
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
11121175

@@ -1124,9 +1187,7 @@ macro_rules! usart {
11241187
Err(nb::Error::WouldBlock)
11251188
}
11261189
}
1127-
}
11281190

1129-
impl Tx<$USARTX> {
11301191
/// Start listening for `Txe` event
11311192
pub fn listen(&mut self) {
11321193
// unsafe: txeie bit accessed by Tx part only
@@ -1294,23 +1355,3 @@ usart_sel! {
12941355
UART8: "UART8",
12951356
UART7: "UART7",
12961357
}
1297-
1298-
impl<USART> fmt::Write for Tx<USART>
1299-
where
1300-
Tx<USART>: serial::Write<u8>,
1301-
{
1302-
fn write_str(&mut self, s: &str) -> fmt::Result {
1303-
let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last();
1304-
Ok(())
1305-
}
1306-
}
1307-
1308-
impl<USART> fmt::Write for Serial<USART>
1309-
where
1310-
Serial<USART>: serial::Write<u8>,
1311-
{
1312-
fn write_str(&mut self, s: &str) -> fmt::Result {
1313-
let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last();
1314-
Ok(())
1315-
}
1316-
}

0 commit comments

Comments
 (0)