Skip to content

Commit 406186d

Browse files
Disasmdbrgn
authored andcommitted
Deduplicate USART driver code
1 parent 7b242b7 commit 406186d

File tree

1 file changed

+73
-80
lines changed

1 file changed

+73
-80
lines changed

src/serial.rs

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

127190
pub enum Parity {
128191
ParityNone,
@@ -357,112 +420,42 @@ macro_rules! hal {
357420
}
358421
}
359422

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-
430423
impl crate::hal::serial::Read<u8> for Rx<$USARTX> {
431424
type Error = Error;
432425

433426
fn read(&mut self) -> nb::Result<u8, Error> {
434-
$USARTX::read()
427+
unsafe { &*$USARTX::ptr() }.read()
435428
}
436429
}
437430

438431
impl crate::hal::serial::Write<u8> for Tx<$USARTX> {
439432
type Error = Infallible;
440433

441434
fn flush(&mut self) -> nb::Result<(), Self::Error> {
442-
$USARTX::flush()
435+
unsafe { &*$USARTX::ptr() }.flush()
443436
}
444437
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
445-
$USARTX::write(byte)
438+
unsafe { &*$USARTX::ptr() }.write(byte)
446439
}
447440
}
448441

449442
impl<PINS> crate::hal::serial::Read<u8> for Serial<$USARTX, PINS> {
450443
type Error = Error;
451444

452445
fn read(&mut self) -> nb::Result<u8, Error> {
453-
$USARTX::read()
446+
self.usart.deref().read()
454447
}
455448
}
456449

457450
impl<PINS> crate::hal::serial::Write<u8> for Serial<$USARTX, PINS> {
458451
type Error = Infallible;
459452

460453
fn flush(&mut self) -> nb::Result<(), Self::Error> {
461-
$USARTX::flush()
454+
self.usart.deref().flush()
462455
}
463456

464457
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
465-
$USARTX::write(byte)
458+
self.usart.deref().write(byte)
466459
}
467460
}
468461

0 commit comments

Comments
 (0)