Skip to content

Commit 6d7d30a

Browse files
Move read, flush & write in separate functions
1 parent 8a00351 commit 6d7d30a

File tree

1 file changed

+69
-59
lines changed

1 file changed

+69
-59
lines changed

src/serial.rs

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ use embedded_hal::prelude::*;
3636
#[allow(unused)]
3737
use crate::{gpio::*, rcc::Clocks, time::Bps};
3838

39+
use core::marker::PhantomData;
40+
3941
/// Serial error
4042
#[derive(Debug)]
4143
pub enum Error {
@@ -188,11 +190,15 @@ pub struct Serial<USART, TXPIN, RXPIN> {
188190
pins: (TXPIN, RXPIN),
189191
}
190192

193+
// Common register
194+
#[cfg(feature = "device-selected")]
195+
type SerialRegisterBlock = crate::stm32::usart1::RegisterBlock;
196+
191197
/// Serial receiver
192198
#[allow(unused)]
193199
pub struct Rx<USART> {
194-
// This is ok, because the USART types only contains PhantomData
195-
usart: *const USART,
200+
usart: *const SerialRegisterBlock,
201+
_instance: PhantomData<USART>,
196202
}
197203

198204
// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -201,8 +207,8 @@ unsafe impl<USART> Send for Rx<USART> {}
201207
/// Serial transmitter
202208
#[allow(unused)]
203209
pub struct Tx<USART> {
204-
// This is ok, because the USART types only contains PhantomData
205-
usart: *const USART,
210+
usart: *const SerialRegisterBlock,
211+
_instance: PhantomData<USART>,
206212
}
207213

208214
// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -343,11 +349,6 @@ usart! {
343349
USART6: (usart6, usart6tx, usart6rx,usart6en, apb2enr),
344350
}
345351

346-
// It's s needed for the impls, but rustc doesn't recognize that
347-
#[allow(dead_code)]
348-
#[cfg(feature = "device-selected")]
349-
type SerialRegisterBlock = crate::stm32::usart1::RegisterBlock;
350-
351352
#[cfg(feature = "device-selected")]
352353
impl<USART> embedded_hal::serial::Read<u8> for Rx<USART>
353354
where
@@ -357,23 +358,7 @@ where
357358

358359
/// Tries to read a byte from the uart
359360
fn read(&mut self) -> nb::Result<u8, Error> {
360-
// NOTE(unsafe) atomic read with no side effects
361-
let isr = unsafe { (*self.usart).isr.read() };
362-
363-
Err(if isr.pe().bit_is_set() {
364-
nb::Error::Other(Error::Parity)
365-
} else if isr.fe().bit_is_set() {
366-
nb::Error::Other(Error::Framing)
367-
} else if isr.nf().bit_is_set() {
368-
nb::Error::Other(Error::Noise)
369-
} else if isr.ore().bit_is_set() {
370-
nb::Error::Other(Error::Overrun)
371-
} else if isr.rxne().bit_is_set() {
372-
// NOTE(read_volatile) see `write_volatile` below
373-
return Ok(unsafe { ptr::read_volatile(&(*self.usart).rdr as *const _ as *const _) });
374-
} else {
375-
nb::Error::WouldBlock
376-
})
361+
read(self.usart)
377362
}
378363
}
379364

@@ -386,10 +371,7 @@ where
386371

387372
/// Tries to read a byte from the uart
388373
fn read(&mut self) -> nb::Result<u8, Error> {
389-
Rx {
390-
usart: &self.usart as *const _,
391-
}
392-
.read()
374+
read(&*self.usart)
393375
}
394376
}
395377

@@ -402,30 +384,13 @@ where
402384

403385
/// Ensures that none of the previously written words are still buffered
404386
fn flush(&mut self) -> nb::Result<(), Self::Error> {
405-
// NOTE(unsafe) atomic read with no side effects
406-
let isr = unsafe { (*self.usart).isr.read() };
407-
408-
if isr.tc().bit_is_set() {
409-
Ok(())
410-
} else {
411-
Err(nb::Error::WouldBlock)
412-
}
387+
flush(self.usart)
413388
}
414389

415390
/// Tries to write a byte to the uart
416391
/// Fails if the transmit buffer is full
417392
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
418-
// NOTE(unsafe) atomic read with no side effects
419-
let isr = unsafe { (*self.usart).isr.read() };
420-
421-
if isr.txe().bit_is_set() {
422-
// NOTE(unsafe) atomic write to stateless register
423-
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
424-
unsafe { ptr::write_volatile(&(*self.usart).tdr as *const _ as *mut _, byte) }
425-
Ok(())
426-
} else {
427-
Err(nb::Error::WouldBlock)
428-
}
393+
write(self.usart, byte)
429394
}
430395
}
431396

@@ -438,19 +403,13 @@ where
438403

439404
/// Ensures that none of the previously written words are still buffered
440405
fn flush(&mut self) -> nb::Result<(), Self::Error> {
441-
Tx {
442-
usart: &self.usart as *const _,
443-
}
444-
.flush()
406+
flush(&*self.usart)
445407
}
446408

447409
/// Tries to write a byte to the uart
448410
/// Fails if the transmit buffer is full
449411
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
450-
Tx {
451-
usart: &self.usart as *const _,
452-
}
453-
.write(byte)
412+
write(&*self.usart, byte)
454413
}
455414
}
456415

@@ -468,10 +427,12 @@ where
468427
{
469428
(
470429
Tx {
471-
usart: &self.usart as *const _,
430+
usart: &*self.usart,
431+
_instance: PhantomData,
472432
},
473433
Rx {
474-
usart: &self.usart as *const _,
434+
usart: &*self.usart,
435+
_instance: PhantomData,
475436
},
476437
)
477438
}
@@ -493,3 +454,52 @@ where
493454
Ok(())
494455
}
495456
}
457+
458+
/// Ensures that none of the previously written words are still buffered
459+
fn flush(usart: *const SerialRegisterBlock) -> nb::Result<(), void::Void> {
460+
// NOTE(unsafe) atomic read with no side effects
461+
let isr = unsafe { (*usart).isr.read() };
462+
463+
if isr.tc().bit_is_set() {
464+
Ok(())
465+
} else {
466+
Err(nb::Error::WouldBlock)
467+
}
468+
}
469+
470+
/// Tries to write a byte to the uart
471+
/// Fails if the transmit buffer is full
472+
fn write(usart: *const SerialRegisterBlock, byte: u8) -> nb::Result<(), void::Void> {
473+
// NOTE(unsafe) atomic read with no side effects
474+
let isr = unsafe { (*usart).isr.read() };
475+
476+
if isr.txe().bit_is_set() {
477+
// NOTE(unsafe) atomic write to stateless register
478+
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
479+
unsafe { ptr::write_volatile(&(*usart).tdr as *const _ as *mut _, byte) }
480+
Ok(())
481+
} else {
482+
Err(nb::Error::WouldBlock)
483+
}
484+
}
485+
486+
/// Tries to read a byte from the uart
487+
fn read(usart: *const SerialRegisterBlock) -> nb::Result<u8, Error> {
488+
// NOTE(unsafe) atomic read with no side effects
489+
let isr = unsafe { (*usart).isr.read() };
490+
491+
Err(if isr.pe().bit_is_set() {
492+
nb::Error::Other(Error::Parity)
493+
} else if isr.fe().bit_is_set() {
494+
nb::Error::Other(Error::Framing)
495+
} else if isr.nf().bit_is_set() {
496+
nb::Error::Other(Error::Noise)
497+
} else if isr.ore().bit_is_set() {
498+
nb::Error::Other(Error::Overrun)
499+
} else if isr.rxne().bit_is_set() {
500+
// NOTE(read_volatile) see `write_volatile` below
501+
return Ok(unsafe { ptr::read_volatile(&(*usart).rdr as *const _ as *const _) });
502+
} else {
503+
nb::Error::WouldBlock
504+
})
505+
}

0 commit comments

Comments
 (0)