Browse Source

Enable macro less implementations of multiple usarts

features/pwm
David Sawatzke 4 years ago
parent
commit
d059c11b3b
  1. 147
      src/serial.rs

147
src/serial.rs

@ -1,5 +1,5 @@
use core::fmt::{Result, Write};
use core::marker::PhantomData;
use core::ops::Deref;
use core::ptr;
use embedded_hal::prelude::*;
@ -7,7 +7,7 @@ use nb::block;
use void::Void;
#[cfg(any(feature = "stm32f042", feature = "stm32f030"))]
use crate::stm32::{RCC, USART1, USART2};
use crate::stm32::{usart1, RCC, USART1, USART2};
use crate::gpio::*;
use crate::rcc::Clocks;
@ -83,12 +83,14 @@ pub struct Serial<USART, PINS> {
/// Serial receiver
pub struct Rx<USART> {
_usart: PhantomData<USART>,
// This is ok, because the USART types only contains PhantomData
usart: *const USART,
}
/// Serial transmitter
pub struct Tx<USART> {
_usart: PhantomData<USART>,
// This is ok, because the USART types only contains PhantomData
usart: *const USART,
}
/// USART1
@ -117,75 +119,6 @@ impl<PINS> Serial<USART1, PINS> {
Serial { usart, pins }
}
pub fn split(self) -> (Tx<USART1>, Rx<USART1>) {
(
Tx {
_usart: PhantomData,
},
Rx {
_usart: PhantomData,
},
)
}
pub fn release(self) -> (USART1, PINS) {
(self.usart, self.pins)
}
}
#[cfg(any(feature = "stm32f042", feature = "stm32f030"))]
impl embedded_hal::serial::Read<u8> for Rx<USART1> {
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Error> {
// NOTE(unsafe) atomic read with no side effects
let isr = unsafe { (*USART1::ptr()).isr.read() };
Err(if isr.pe().bit_is_set() {
nb::Error::Other(Error::Parity)
} else if isr.fe().bit_is_set() {
nb::Error::Other(Error::Framing)
} else if isr.nf().bit_is_set() {
nb::Error::Other(Error::Noise)
} else if isr.ore().bit_is_set() {
nb::Error::Other(Error::Overrun)
} else if isr.rxne().bit_is_set() {
// NOTE(read_volatile) see `write_volatile` below
return Ok(unsafe { ptr::read_volatile(&(*USART1::ptr()).rdr as *const _ as *const _) });
} else {
nb::Error::WouldBlock
})
}
}
#[cfg(any(feature = "stm32f042", feature = "stm32f030"))]
impl embedded_hal::serial::Write<u8> for Tx<USART1> {
type Error = Void;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
// NOTE(unsafe) atomic read with no side effects
let isr = unsafe { (*USART1::ptr()).isr.read() };
if isr.tc().bit_is_set() {
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
// NOTE(unsafe) atomic read with no side effects
let isr = unsafe { (*USART1::ptr()).isr.read() };
if isr.txe().bit_is_set() {
// NOTE(unsafe) atomic write to stateless register
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
unsafe { ptr::write_volatile(&(*USART1::ptr()).tdr as *const _ as *mut _, byte) }
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
/// USART2
@ -218,33 +151,21 @@ impl<PINS> Serial<USART2, PINS> {
Serial { usart, pins }
}
pub fn split(self) -> (Tx<USART2>, Rx<USART2>) {
(
Tx {
_usart: PhantomData,
},
Rx {
_usart: PhantomData,
},
)
}
pub fn release(self) -> (USART2, PINS) {
(self.usart, self.pins)
}
}
#[cfg(any(
feature = "stm32f042",
feature = "stm32f030x8",
feature = "stm32f030x8"
))]
impl embedded_hal::serial::Read<u8> for Rx<USART2> {
// It's s needed for the impls, but rustc doesn't recognize that
#[allow(dead_code)]
type SerialRegisterBlock = usart1::RegisterBlock;
impl<USART> embedded_hal::serial::Read<u8> for Rx<USART>
where
USART: Deref<Target = SerialRegisterBlock>,
{
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Error> {
// NOTE(unsafe) atomic read with no side effects
let isr = unsafe { (*USART2::ptr()).isr.read() };
let isr = unsafe { (*self.usart).isr.read() };
Err(if isr.pe().bit_is_set() {
nb::Error::Other(Error::Parity)
@ -256,24 +177,22 @@ impl embedded_hal::serial::Read<u8> for Rx<USART2> {
nb::Error::Other(Error::Overrun)
} else if isr.rxne().bit_is_set() {
// NOTE(read_volatile) see `write_volatile` below
return Ok(unsafe { ptr::read_volatile(&(*USART2::ptr()).rdr as *const _ as *const _) });
return Ok(unsafe { ptr::read_volatile(&(*self.usart).rdr as *const _ as *const _) });
} else {
nb::Error::WouldBlock
})
}
}
#[cfg(any(
feature = "stm32f042",
feature = "stm32f030x8",
feature = "stm32f030x8"
))]
impl embedded_hal::serial::Write<u8> for Tx<USART2> {
impl<USART> embedded_hal::serial::Write<u8> for Tx<USART>
where
USART: Deref<Target = SerialRegisterBlock>,
{
type Error = Void;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
// NOTE(unsafe) atomic read with no side effects
let isr = unsafe { (*USART2::ptr()).isr.read() };
let isr = unsafe { (*self.usart).isr.read() };
if isr.tc().bit_is_set() {
Ok(())
@ -284,12 +203,12 @@ impl embedded_hal::serial::Write<u8> for Tx<USART2> {
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
// NOTE(unsafe) atomic read with no side effects
let isr = unsafe { (*USART2::ptr()).isr.read() };
let isr = unsafe { (*self.usart).isr.read() };
if isr.txe().bit_is_set() {
// NOTE(unsafe) atomic write to stateless register
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
unsafe { ptr::write_volatile(&(*USART2::ptr()).tdr as *const _ as *mut _, byte) }
unsafe { ptr::write_volatile(&(*self.usart).tdr as *const _ as *mut _, byte) }
Ok(())
} else {
Err(nb::Error::WouldBlock)
@ -297,6 +216,26 @@ impl embedded_hal::serial::Write<u8> for Tx<USART2> {
}
}
impl<USART, PINS> Serial<USART, PINS>
where
USART: Deref<Target = SerialRegisterBlock>,
PINS: Pins<USART>,
{
pub fn split(self) -> (Tx<USART>, Rx<USART>) {
(
Tx {
usart: &self.usart as *const _,
},
Rx {
usart: &self.usart as *const _,
},
)
}
pub fn release(self) -> (USART, PINS) {
(self.usart, self.pins)
}
}
impl<USART> Write for Tx<USART>
where
Tx<USART>: embedded_hal::serial::Write<u8>,

Loading…
Cancel
Save