Skip to content

Commit 1e12e92

Browse files
bors[bot]burrbull
andauthored
Merge #514
514: Serial Tx, Rx containing pins r=therealprof a=burrbull Related to #505 Instead of changing API I added alternative. So now to can choose between `Tx`, `Rx` with erased information about pins and `UTx`, `URx` which can join to restore `Serial` Co-authored-by: Andrey Zgarbul <zgarbul.andrey@gmail.com>
2 parents 0db12eb + 6f4b8b4 commit 1e12e92

File tree

4 files changed

+338
-5
lines changed

4 files changed

+338
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2525

2626
### Added
2727

28+
- Serial Tx, Rx containing pins [#514]
2829
- Implementation of From trait for Pin-to-PartiallyErasedPin [#507]
2930
- Implementation of From trait for Pin-to-ErasedPin [#507]
3031
- Implementation of From trait for PartiallyErasedPin-to-ErasedPin [#507]
@@ -38,6 +39,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
3839
[#507]: https://github.com/stm32-rs/stm32f4xx-hal/pull/507
3940
[#508]: https://github.com/stm32-rs/stm32f4xx-hal/pull/508
4041
[#510]: https://github.com/stm32-rs/stm32f4xx-hal/pull/510
42+
[#510]: https://github.com/stm32-rs/stm32f4xx-hal/pull/514
4143

4244
## [v0.13.2] - 2022-05-16
4345

src/serial.rs

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,123 @@ impl<USART, PINS, WORD> AsMut<Rx<USART, WORD>> for Serial<USART, PINS, WORD> {
332332
}
333333
}
334334

335+
/// Serial receiver containing RX pin
336+
pub struct URx<USART, RX, WORD = u8> {
337+
_usart: PhantomData<USART>,
338+
pin: RX,
339+
_word: PhantomData<WORD>,
340+
}
341+
342+
/// Serial transmitter containing TX pin
343+
pub struct UTx<USART, TX, WORD = u8> {
344+
usart: USART,
345+
pin: TX,
346+
_word: PhantomData<WORD>,
347+
}
348+
349+
impl<USART: Instance, RX, WORD> URx<USART, RX, WORD> {
350+
fn new(pin: RX) -> Self {
351+
Self {
352+
_usart: PhantomData,
353+
pin,
354+
_word: PhantomData,
355+
}
356+
}
357+
358+
pub fn erase(self) -> Rx<USART, WORD> {
359+
Rx::new()
360+
}
361+
362+
/// Start listening for an rx not empty interrupt event
363+
///
364+
/// Note, you will also have to enable the corresponding interrupt
365+
/// in the NVIC to start receiving events.
366+
pub fn listen(&mut self) {
367+
unsafe { (*USART::ptr()).cr1.modify(|_, w| w.rxneie().set_bit()) }
368+
}
369+
370+
/// Stop listening for the rx not empty interrupt event
371+
pub fn unlisten(&mut self) {
372+
unsafe { (*USART::ptr()).cr1.modify(|_, w| w.rxneie().clear_bit()) }
373+
}
374+
375+
/// Start listening for a line idle interrupt event
376+
///
377+
/// Note, you will also have to enable the corresponding interrupt
378+
/// in the NVIC to start receiving events.
379+
pub fn listen_idle(&mut self) {
380+
unsafe { (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit()) }
381+
}
382+
383+
/// Stop listening for the line idle interrupt event
384+
pub fn unlisten_idle(&mut self) {
385+
unsafe { (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()) }
386+
}
387+
388+
/// Return true if the line idle status is set
389+
pub fn is_idle(&self) -> bool {
390+
unsafe { (*USART::ptr()).sr.read().idle().bit_is_set() }
391+
}
392+
393+
/// Return true if the rx register is not empty (and can be read)
394+
pub fn is_rx_not_empty(&self) -> bool {
395+
unsafe { (*USART::ptr()).sr.read().rxne().bit_is_set() }
396+
}
397+
398+
/// Clear idle line interrupt flag
399+
pub fn clear_idle_interrupt(&self) {
400+
unsafe {
401+
let _ = (*USART::ptr()).sr.read();
402+
let _ = (*USART::ptr()).dr.read();
403+
}
404+
}
405+
}
406+
407+
impl<USART: Instance, TX, WORD> UTx<USART, TX, WORD> {
408+
fn new(usart: USART, pin: TX) -> Self {
409+
Self {
410+
usart,
411+
pin,
412+
_word: PhantomData,
413+
}
414+
}
415+
416+
pub fn erase(self) -> Tx<USART, WORD> {
417+
Tx::new()
418+
}
419+
420+
pub fn join<RX>(self, rx: URx<USART, RX, WORD>) -> Serial<USART, (TX, RX), WORD>
421+
where
422+
(TX, RX): Pins<USART>,
423+
{
424+
Serial {
425+
usart: self.usart,
426+
pins: (self.pin, rx.pin),
427+
tx: Tx::new(),
428+
rx: Rx::new(),
429+
}
430+
}
431+
432+
/// Start listening for a tx empty interrupt event
433+
///
434+
/// Note, you will also have to enable the corresponding interrupt
435+
/// in the NVIC to start receiving events.
436+
// TODO: replace with "self.usart"
437+
pub fn listen(&mut self) {
438+
unsafe { (*USART::ptr()).cr1.modify(|_, w| w.txeie().set_bit()) }
439+
}
440+
441+
/// Stop listening for the tx empty interrupt event
442+
pub fn unlisten(&mut self) {
443+
unsafe { (*USART::ptr()).cr1.modify(|_, w| w.txeie().clear_bit()) }
444+
}
445+
446+
/// Return true if the tx register is empty (and can accept data)
447+
pub fn is_tx_empty(&self) -> bool {
448+
unsafe { (*USART::ptr()).sr.read().txe().bit_is_set() }
449+
}
450+
}
451+
335452
pub trait SerialExt: Sized + Instance {
336453
fn serial<TX, RX, WORD>(
337454
self,
@@ -614,6 +731,12 @@ impl<USART: Instance, PINS, WORD> Serial<USART, PINS, WORD> {
614731
}
615732
}
616733

734+
impl<USART: Instance, TX, RX, WORD> Serial<USART, (TX, RX), WORD> {
735+
pub fn split_nondestructive(self) -> (UTx<USART, TX, WORD>, URx<USART, RX, WORD>) {
736+
(UTx::new(self.usart, self.pins.0), URx::new(self.pins.1))
737+
}
738+
}
739+
617740
impl<USART: Instance, PINS> Serial<USART, PINS, u8> {
618741
/// Converts this Serial into a version that can read and write `u16` values instead of `u8`s
619742
///
@@ -912,3 +1035,109 @@ impl<USART: Instance> Tx<USART, u16> {
9121035
nb::block!(self.flush())
9131036
}
9141037
}
1038+
1039+
impl<USART: Instance, TX> fmt::Write for UTx<USART, TX> {
1040+
fn write_str(&mut self, s: &str) -> fmt::Result {
1041+
s.bytes()
1042+
.try_for_each(|c| block!(self.write(c)))
1043+
.map_err(|_| fmt::Error)
1044+
}
1045+
}
1046+
1047+
impl<USART: Instance, RX> URx<USART, RX, u8> {
1048+
fn read(&mut self) -> nb::Result<u8, Error> {
1049+
// Delegate to the Read<u16> implementation, then truncate to 8 bits
1050+
Rx::<USART, u16>::new().read().map(|word16| word16 as u8)
1051+
}
1052+
}
1053+
1054+
impl<USART: Instance, RX> URx<USART, RX, u16> {
1055+
fn read(&mut self) -> nb::Result<u16, Error> {
1056+
// NOTE(unsafe) atomic read with no side effects
1057+
let sr = unsafe { (*USART::ptr()).sr.read() };
1058+
1059+
// Any error requires the dr to be read to clear
1060+
if sr.pe().bit_is_set()
1061+
|| sr.fe().bit_is_set()
1062+
|| sr.nf().bit_is_set()
1063+
|| sr.ore().bit_is_set()
1064+
{
1065+
unsafe { (*USART::ptr()).dr.read() };
1066+
}
1067+
1068+
Err(if sr.pe().bit_is_set() {
1069+
Error::Parity.into()
1070+
} else if sr.fe().bit_is_set() {
1071+
Error::FrameFormat.into()
1072+
} else if sr.nf().bit_is_set() {
1073+
Error::Noise.into()
1074+
} else if sr.ore().bit_is_set() {
1075+
Error::Overrun.into()
1076+
} else if sr.rxne().bit_is_set() {
1077+
// NOTE(unsafe) atomic read from stateless register
1078+
return Ok(unsafe { &*USART::ptr() }.dr.read().dr().bits());
1079+
} else {
1080+
nb::Error::WouldBlock
1081+
})
1082+
}
1083+
}
1084+
1085+
impl<USART: Instance, TX> UTx<USART, TX, u8> {
1086+
fn write(&mut self, word: u8) -> nb::Result<(), Error> {
1087+
// Delegate to u16 version
1088+
Tx::<USART, u16>::new().write(u16::from(word))
1089+
}
1090+
1091+
fn flush(&mut self) -> nb::Result<(), Error> {
1092+
// Delegate to u16 version
1093+
Tx::<USART, u16>::new().flush()
1094+
}
1095+
1096+
fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Error> {
1097+
for &b in bytes {
1098+
nb::block!(self.write(b))?;
1099+
}
1100+
Ok(())
1101+
}
1102+
1103+
fn bflush(&mut self) -> Result<(), Error> {
1104+
nb::block!(self.flush())
1105+
}
1106+
}
1107+
1108+
impl<USART: Instance, TX> UTx<USART, TX, u16> {
1109+
fn write(&mut self, word: u16) -> nb::Result<(), Error> {
1110+
// NOTE(unsafe) atomic read with no side effects
1111+
let sr = unsafe { (*USART::ptr()).sr.read() };
1112+
1113+
if sr.txe().bit_is_set() {
1114+
// NOTE(unsafe) atomic write to stateless register
1115+
unsafe { &*USART::ptr() }.dr.write(|w| w.dr().bits(word));
1116+
Ok(())
1117+
} else {
1118+
Err(nb::Error::WouldBlock)
1119+
}
1120+
}
1121+
1122+
fn flush(&mut self) -> nb::Result<(), Error> {
1123+
// NOTE(unsafe) atomic read with no side effects
1124+
let sr = unsafe { (*USART::ptr()).sr.read() };
1125+
1126+
if sr.tc().bit_is_set() {
1127+
Ok(())
1128+
} else {
1129+
Err(nb::Error::WouldBlock)
1130+
}
1131+
}
1132+
1133+
fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Error> {
1134+
for &b in buffer {
1135+
nb::block!(self.write(b))?;
1136+
}
1137+
Ok(())
1138+
}
1139+
1140+
fn bflush(&mut self) -> Result<(), Error> {
1141+
nb::block!(self.flush())
1142+
}
1143+
}

src/serial/hal_02.rs

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod nb {
2-
use super::super::{Error, Instance, Rx, Serial, Tx};
2+
use super::super::{Error, Instance, Rx, Serial, Tx, URx, UTx};
33
use embedded_hal::serial::{Read, Write};
44

55
impl<USART, PINS, WORD> Read<WORD> for Serial<USART, PINS, WORD>
@@ -22,6 +22,14 @@ mod nb {
2222
}
2323
}
2424

25+
impl<USART: Instance, RX> Read<u8> for URx<USART, RX, u8> {
26+
type Error = Error;
27+
28+
fn read(&mut self) -> nb::Result<u8, Self::Error> {
29+
self.read()
30+
}
31+
}
32+
2533
/// Reads 9-bit words from the UART/USART
2634
///
2735
/// If the UART/USART was configured with `WordLength::DataBits9`, the returned value will contain
@@ -35,6 +43,14 @@ mod nb {
3543
}
3644
}
3745

46+
impl<USART: Instance, RX> Read<u16> for URx<USART, RX, u16> {
47+
type Error = Error;
48+
49+
fn read(&mut self) -> nb::Result<u16, Self::Error> {
50+
self.read()
51+
}
52+
}
53+
3854
impl<USART, PINS, WORD> Write<WORD> for Serial<USART, PINS, WORD>
3955
where
4056
USART: Instance,
@@ -51,7 +67,7 @@ mod nb {
5167
}
5268
}
5369

54-
impl<USART: Instance> Write<u8> for Tx<USART, u8> {
70+
impl<USART: Instance, TX> Write<u8> for UTx<USART, TX, u8> {
5571
type Error = Error;
5672

5773
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
@@ -79,10 +95,22 @@ mod nb {
7995
self.flush()
8096
}
8197
}
98+
99+
impl<USART: Instance, TX> Write<u16> for UTx<USART, TX, u16> {
100+
type Error = Error;
101+
102+
fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> {
103+
self.write(word)
104+
}
105+
106+
fn flush(&mut self) -> nb::Result<(), Self::Error> {
107+
self.flush()
108+
}
109+
}
82110
}
83111

84112
mod blocking {
85-
use super::super::{Error, Instance, Serial, Tx};
113+
use super::super::{Error, Instance, Serial, Tx, UTx};
86114
use embedded_hal::blocking::serial::Write;
87115

88116
impl<USART: Instance> Write<u8> for Tx<USART, u8> {
@@ -97,6 +125,18 @@ mod blocking {
97125
}
98126
}
99127

128+
impl<USART: Instance, TX> Write<u8> for UTx<USART, TX, u8> {
129+
type Error = Error;
130+
131+
fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
132+
self.bwrite_all(bytes)
133+
}
134+
135+
fn bflush(&mut self) -> Result<(), Self::Error> {
136+
self.bflush()
137+
}
138+
}
139+
100140
impl<USART: Instance, PINS> Write<u8> for Serial<USART, PINS, u8> {
101141
type Error = Error;
102142

@@ -121,6 +161,18 @@ mod blocking {
121161
}
122162
}
123163

164+
impl<USART: Instance, TX> Write<u16> for UTx<USART, TX, u16> {
165+
type Error = Error;
166+
167+
fn bwrite_all(&mut self, slice: &[u16]) -> Result<(), Self::Error> {
168+
self.bwrite_all(slice)
169+
}
170+
171+
fn bflush(&mut self) -> Result<(), Self::Error> {
172+
self.bflush()
173+
}
174+
}
175+
124176
impl<USART: Instance, PINS> Write<u16> for Serial<USART, PINS, u16> {
125177
type Error = Error;
126178

0 commit comments

Comments
 (0)