Skip to content

Commit ec1fa41

Browse files
Move read, flush & write in separate functions
1 parent 2c62bd9 commit ec1fa41

File tree

1 file changed

+68
-58
lines changed

1 file changed

+68
-58
lines changed

src/serial.rs

Lines changed: 68 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ use embedded_hal::prelude::*;
4141

4242
use crate::{gpio::*, rcc::Rcc, time::Bps};
4343

44+
use core::marker::PhantomData;
45+
4446
/// Serial error
4547
#[derive(Debug)]
4648
pub enum Error {
@@ -208,19 +210,22 @@ pub struct Serial<USART, TXPIN, RXPIN> {
208210
pins: (TXPIN, RXPIN),
209211
}
210212

213+
// Common register
214+
type SerialRegisterBlock = crate::stm32::usart1::RegisterBlock;
215+
211216
/// Serial receiver
212217
pub struct Rx<USART> {
213-
// This is ok, because the USART types only contains PhantomData
214-
usart: *const USART,
218+
usart: *const SerialRegisterBlock,
219+
_instance: PhantomData<USART>,
215220
}
216221

217222
// NOTE(unsafe) Required to allow protected shared access in handlers
218223
unsafe impl<USART> Send for Rx<USART> {}
219224

220225
/// Serial transmitter
221226
pub struct Tx<USART> {
222-
// This is ok, because the USART types only contains PhantomData
223-
usart: *const USART,
227+
usart: *const SerialRegisterBlock,
228+
_instance: PhantomData<USART>,
224229
}
225230

226231
// NOTE(unsafe) Required to allow protected shared access in handlers
@@ -359,10 +364,6 @@ usart! {
359364
USART6: (usart6, usart6tx, usart6rx,usart6en, apb2enr),
360365
}
361366

362-
// It's s needed for the impls, but rustc doesn't recognize that
363-
#[allow(dead_code)]
364-
type SerialRegisterBlock = crate::stm32::usart1::RegisterBlock;
365-
366367
impl<USART> embedded_hal::serial::Read<u8> for Rx<USART>
367368
where
368369
USART: Deref<Target = SerialRegisterBlock>,
@@ -371,23 +372,7 @@ where
371372

372373
/// Tries to read a byte from the uart
373374
fn read(&mut self) -> nb::Result<u8, Error> {
374-
// NOTE(unsafe) atomic read with no side effects
375-
let isr = unsafe { (*self.usart).isr.read() };
376-
377-
Err(if isr.pe().bit_is_set() {
378-
nb::Error::Other(Error::Parity)
379-
} else if isr.fe().bit_is_set() {
380-
nb::Error::Other(Error::Framing)
381-
} else if isr.nf().bit_is_set() {
382-
nb::Error::Other(Error::Noise)
383-
} else if isr.ore().bit_is_set() {
384-
nb::Error::Other(Error::Overrun)
385-
} else if isr.rxne().bit_is_set() {
386-
// NOTE(read_volatile) see `write_volatile` below
387-
return Ok(unsafe { ptr::read_volatile(&(*self.usart).rdr as *const _ as *const _) });
388-
} else {
389-
nb::Error::WouldBlock
390-
})
375+
read(self.usart)
391376
}
392377
}
393378

@@ -400,10 +385,7 @@ where
400385

401386
/// Tries to read a byte from the uart
402387
fn read(&mut self) -> nb::Result<u8, Error> {
403-
Rx {
404-
usart: &self.usart as *const _,
405-
}
406-
.read()
388+
read(&*self.usart)
407389
}
408390
}
409391

@@ -415,30 +397,13 @@ where
415397

416398
/// Ensures that none of the previously written words are still buffered
417399
fn flush(&mut self) -> 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.tc().bit_is_set() {
422-
Ok(())
423-
} else {
424-
Err(nb::Error::WouldBlock)
425-
}
400+
flush(self.usart)
426401
}
427402

428403
/// Tries to write a byte to the uart
429404
/// Fails if the transmit buffer is full
430405
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
431-
// NOTE(unsafe) atomic read with no side effects
432-
let isr = unsafe { (*self.usart).isr.read() };
433-
434-
if isr.txe().bit_is_set() {
435-
// NOTE(unsafe) atomic write to stateless register
436-
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
437-
unsafe { ptr::write_volatile(&(*self.usart).tdr as *const _ as *mut _, byte) }
438-
Ok(())
439-
} else {
440-
Err(nb::Error::WouldBlock)
441-
}
406+
write(self.usart, byte)
442407
}
443408
}
444409

@@ -451,19 +416,13 @@ where
451416

452417
/// Ensures that none of the previously written words are still buffered
453418
fn flush(&mut self) -> nb::Result<(), Self::Error> {
454-
Tx {
455-
usart: &self.usart as *const _,
456-
}
457-
.flush()
419+
flush(&*self.usart)
458420
}
459421

460422
/// Tries to write a byte to the uart
461423
/// Fails if the transmit buffer is full
462424
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
463-
Tx {
464-
usart: &self.usart as *const _,
465-
}
466-
.write(byte)
425+
write(&*self.usart, byte)
467426
}
468427
}
469428

@@ -480,10 +439,12 @@ where
480439
{
481440
(
482441
Tx {
483-
usart: &self.usart as *const _,
442+
usart: &*self.usart,
443+
_instance: PhantomData,
484444
},
485445
Rx {
486-
usart: &self.usart as *const _,
446+
usart: &*self.usart,
447+
_instance: PhantomData,
487448
},
488449
)
489450
}
@@ -504,3 +465,52 @@ where
504465
Ok(())
505466
}
506467
}
468+
469+
/// Ensures that none of the previously written words are still buffered
470+
fn flush(usart: *const SerialRegisterBlock) -> nb::Result<(), void::Void> {
471+
// NOTE(unsafe) atomic read with no side effects
472+
let isr = unsafe { (*usart).isr.read() };
473+
474+
if isr.tc().bit_is_set() {
475+
Ok(())
476+
} else {
477+
Err(nb::Error::WouldBlock)
478+
}
479+
}
480+
481+
/// Tries to write a byte to the uart
482+
/// Fails if the transmit buffer is full
483+
fn write(usart: *const SerialRegisterBlock, byte: u8) -> nb::Result<(), void::Void> {
484+
// NOTE(unsafe) atomic read with no side effects
485+
let isr = unsafe { (*usart).isr.read() };
486+
487+
if isr.txe().bit_is_set() {
488+
// NOTE(unsafe) atomic write to stateless register
489+
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
490+
unsafe { ptr::write_volatile(&(*usart).tdr as *const _ as *mut _, byte) }
491+
Ok(())
492+
} else {
493+
Err(nb::Error::WouldBlock)
494+
}
495+
}
496+
497+
/// Tries to read a byte from the uart
498+
fn read(usart: *const SerialRegisterBlock) -> nb::Result<u8, Error> {
499+
// NOTE(unsafe) atomic read with no side effects
500+
let isr = unsafe { (*usart).isr.read() };
501+
502+
Err(if isr.pe().bit_is_set() {
503+
nb::Error::Other(Error::Parity)
504+
} else if isr.fe().bit_is_set() {
505+
nb::Error::Other(Error::Framing)
506+
} else if isr.nf().bit_is_set() {
507+
nb::Error::Other(Error::Noise)
508+
} else if isr.ore().bit_is_set() {
509+
nb::Error::Other(Error::Overrun)
510+
} else if isr.rxne().bit_is_set() {
511+
// NOTE(read_volatile) see `write_volatile` below
512+
return Ok(unsafe { ptr::read_volatile(&(*usart).rdr as *const _ as *const _) });
513+
} else {
514+
nb::Error::WouldBlock
515+
})
516+
}

0 commit comments

Comments
 (0)