Skip to content

Commit 3b9e709

Browse files
DisasmTheZoq2
authored andcommitted
Deduplicate USART driver code
1 parent ec8aafb commit 3b9e709

File tree

1 file changed

+73
-83
lines changed

1 file changed

+73
-83
lines changed

src/serial.rs

Lines changed: 73 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
use core::marker::PhantomData;
4141
use core::ptr;
4242
use core::sync::atomic::{self, Ordering};
43+
use core::ops::Deref;
4344

4445
use nb;
4546
use crate::pac::{USART1, USART2, USART3};
@@ -115,14 +116,73 @@ impl Pins<USART3> for (PD8<Alternate<PushPull>>, PD9<Input<Floating>>) {
115116
}
116117

117118
/// 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 {
122-
fn read() -> nb::Result<u8, Error>;
123-
fn write(byte: u8) -> nb::Result<(), Infallible>;
124-
fn flush() -> nb::Result<(), Infallible>;
119+
trait UsartReadWrite: Deref<Target=crate::stm32::usart1::RegisterBlock> {
120+
fn read(&self) -> nb::Result<u8, Error> {
121+
let sr = self.sr.read();
122+
123+
// Check for any errors
124+
let err = if sr.pe().bit_is_set() {
125+
Some(Error::Parity)
126+
} else if sr.fe().bit_is_set() {
127+
Some(Error::Framing)
128+
} else if sr.ne().bit_is_set() {
129+
Some(Error::Noise)
130+
} else if sr.ore().bit_is_set() {
131+
Some(Error::Overrun)
132+
} else {
133+
None
134+
};
135+
136+
if let Some(err) = err {
137+
// Some error occured. In order to clear that error flag, you have to
138+
// do a read from the sr register followed by a read from the dr
139+
// register
140+
// NOTE(read_volatile) see `write_volatile` below
141+
unsafe {
142+
ptr::read_volatile(&self.sr as *const _ as *const _);
143+
ptr::read_volatile(&self.dr as *const _ as *const _);
144+
}
145+
Err(nb::Error::Other(err))
146+
} else {
147+
// Check if a byte is available
148+
if sr.rxne().bit_is_set() {
149+
// Read the received byte
150+
// NOTE(read_volatile) see `write_volatile` below
151+
Ok(unsafe {
152+
ptr::read_volatile(&self.dr as *const _ as *const _)
153+
})
154+
} else {
155+
Err(nb::Error::WouldBlock)
156+
}
157+
}
158+
}
159+
160+
fn write(&self, byte: u8) -> nb::Result<(), Infallible> {
161+
let sr = self.sr.read();
162+
163+
if sr.txe().bit_is_set() {
164+
// NOTE(unsafe) atomic write to stateless register
165+
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
166+
unsafe {
167+
ptr::write_volatile(&self.dr as *const _ as *mut _, byte)
168+
}
169+
Ok(())
170+
} else {
171+
Err(nb::Error::WouldBlock)
172+
}
173+
}
174+
175+
fn flush(&self) -> nb::Result<(), Infallible> {
176+
let sr = self.sr.read();
177+
178+
if sr.tc().bit_is_set() {
179+
Ok(())
180+
} else {
181+
Err(nb::Error::WouldBlock)
182+
}
183+
}
125184
}
185+
impl UsartReadWrite for &crate::stm32::usart1::RegisterBlock {}
126186

127187
pub enum Parity {
128188
ParityNone,
@@ -357,112 +417,42 @@ macro_rules! hal {
357417
}
358418
}
359419

360-
impl UsartReadWrite for $USARTX {
361-
fn read() -> nb::Result<u8, Error> {
362-
// NOTE(unsafe) atomic read with no side effects
363-
let sr = unsafe { (*$USARTX::ptr()).sr.read() };
364-
365-
// Check for any errors
366-
let err = if sr.pe().bit_is_set() {
367-
Some(Error::Parity)
368-
} else if sr.fe().bit_is_set() {
369-
Some(Error::Framing)
370-
} else if sr.ne().bit_is_set() {
371-
Some(Error::Noise)
372-
} else if sr.ore().bit_is_set() {
373-
Some(Error::Overrun)
374-
} else {
375-
None
376-
};
377-
378-
if let Some(err) = err {
379-
// Some error occured. In order to clear that error flag, you have to
380-
// do a read from the sr register followed by a read from the dr
381-
// register
382-
// NOTE(read_volatile) see `write_volatile` below
383-
unsafe {
384-
ptr::read_volatile(&(*$USARTX::ptr()).sr as *const _ as *const _);
385-
ptr::read_volatile(&(*$USARTX::ptr()).dr as *const _ as *const _);
386-
}
387-
Err(nb::Error::Other(err))
388-
} else {
389-
// Check if a byte is available
390-
if sr.rxne().bit_is_set() {
391-
// Read the received byte
392-
// NOTE(read_volatile) see `write_volatile` below
393-
Ok(unsafe {
394-
ptr::read_volatile(&(*$USARTX::ptr()).dr as *const _ as *const _)
395-
})
396-
} else {
397-
Err(nb::Error::WouldBlock)
398-
}
399-
}
400-
}
401-
402-
fn write(byte: u8) -> nb::Result<(), Infallible> {
403-
// NOTE(unsafe) atomic read with no side effects
404-
let sr = unsafe { (*$USARTX::ptr()).sr.read() };
405-
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-
}
412-
Ok(())
413-
} else {
414-
Err(nb::Error::WouldBlock)
415-
}
416-
}
417-
418-
fn flush() -> nb::Result<(), Infallible> {
419-
// NOTE(unsafe) atomic read with no side effects
420-
let sr = unsafe { (*$USARTX::ptr()).sr.read() };
421-
422-
if sr.tc().bit_is_set() {
423-
Ok(())
424-
} else {
425-
Err(nb::Error::WouldBlock)
426-
}
427-
}
428-
}
429-
430420
impl crate::hal::serial::Read<u8> for Rx<$USARTX> {
431421
type Error = Error;
432422

433423
fn read(&mut self) -> nb::Result<u8, Error> {
434-
$USARTX::read()
424+
unsafe { &*$USARTX::ptr() }.read()
435425
}
436426
}
437427

438428
impl crate::hal::serial::Write<u8> for Tx<$USARTX> {
439429
type Error = Infallible;
440430

441431
fn flush(&mut self) -> nb::Result<(), Self::Error> {
442-
$USARTX::flush()
432+
unsafe { &*$USARTX::ptr() }.flush()
443433
}
444434
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
445-
$USARTX::write(byte)
435+
unsafe { &*$USARTX::ptr() }.write(byte)
446436
}
447437
}
448438

449439
impl<PINS> crate::hal::serial::Read<u8> for Serial<$USARTX, PINS> {
450440
type Error = Error;
451441

452442
fn read(&mut self) -> nb::Result<u8, Error> {
453-
$USARTX::read()
443+
self.usart.deref().read()
454444
}
455445
}
456446

457447
impl<PINS> crate::hal::serial::Write<u8> for Serial<$USARTX, PINS> {
458448
type Error = Infallible;
459449

460450
fn flush(&mut self) -> nb::Result<(), Self::Error> {
461-
$USARTX::flush()
451+
self.usart.deref().flush()
462452
}
463453

464454
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
465-
$USARTX::write(byte)
455+
self.usart.deref().write(byte)
466456
}
467457
}
468458

0 commit comments

Comments
 (0)