use core::{
convert::Infallible,
fmt::{Result, Write},
ops::Deref,
};
use embedded_hal::prelude::*;
use crate::gpio::{gpioa::*, gpiob::*};
use crate::gpio::{Alternate, AF1};
use crate::{rcc::Rcc, time::Bps};
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
use crate::gpio::{gpiof::*, AF0, AF8};
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
use crate::gpio::{AF3, AF4, AF9};
#[cfg(feature = "py32f002b")]
use crate::gpio::AF3;
use core::marker::PhantomData;
#[non_exhaustive]
#[derive(Debug)]
pub enum Error {
Framing,
Noise,
Overrun,
Parity,
}
pub enum Event {
Rxne,
Txe,
Idle,
}
pub trait TxPin<USART> {}
pub trait RxPin<USART> {}
macro_rules! impl_pins {
($($pin:ident, $af:ident, $instance:ident, $trait:ident;)*) => {
$(
impl $trait<crate::pac::$instance> for $pin<Alternate<$af>> {}
)*
}
}
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
impl_pins!(
PA0, AF9, USART2, TxPin;
PA1, AF9, USART2, RxPin;
PA2, AF1, USART1, TxPin;
PA2, AF4, USART2, TxPin;
PA3, AF1, USART1, RxPin;
PA3, AF4, USART2, RxPin;
PA4, AF9, USART2, TxPin;
PA5, AF9, USART2, RxPin;
PA7, AF8, USART1, TxPin;
PA7, AF9, USART2, TxPin;
PA13, AF8, USART1, RxPin;
PA14, AF1, USART1, TxPin;
PA14, AF4, USART2, TxPin;
PB2, AF0, USART1, RxPin;
PB2, AF3, USART2, RxPin;
PB6, AF0, USART1, TxPin;
PB6, AF4, USART2, TxPin;
PB7, AF0, USART1, RxPin;
PB7, AF4, USART2, RxPin;
PF0, AF4, USART2, RxPin;
PF0, AF8, USART1, RxPin;
PF0, AF9, USART2, TxPin;
PF1, AF4, USART2, TxPin;
PF1, AF8, USART1, TxPin;
PF1, AF9, USART2, RxPin;
PF2, AF4, USART2, RxPin;
PF3, AF0, USART1, TxPin;
PF3, AF4, USART2, TxPin;
);
#[cfg(feature = "py32f030")]
impl_pins!(
PA8, AF8, USART1, RxPin;
PA8, AF9, USART2, RxPin;
PA9, AF1, USART1, TxPin;
PA9, AF4, USART2, TxPin;
PA9, AF8, USART1, RxPin;
PA10, AF1, USART1, RxPin;
PA10, AF4, USART2, RxPin;
PA10, AF8, USART1, TxPin;
PA15, AF1, USART1, RxPin;
PA15, AF4, USART2, RxPin;
PB8, AF4, USART2, TxPin;
PB8, AF8, USART1, TxPin;
);
#[cfg(feature = "py32f002a")]
impl_pins!(
PA2, AF1, USART1, TxPin;
PA3, AF1, USART1, RxPin;
PA7, AF8, USART1, TxPin;
PA8, AF8, USART1, RxPin;
PA9, AF1, USART1, TxPin;
PA9, AF8, USART1, RxPin;
PA10, AF1, USART1, RxPin;
PA10, AF8, USART1, TxPin;
PA13, AF8, USART1, RxPin;
PA14, AF1, USART1, TxPin;
PB2, AF0, USART1, RxPin;
PB6, AF0, USART1, TxPin;
PF0, AF8, USART1, RxPin;
PF1, AF8, USART1, TxPin;
);
#[cfg(feature = "py32f002b")]
impl_pins!(
PA2, AF1, USART1, RxPin;
PA3, AF1, USART1, TxPin;
PA4, AF1, USART1, RxPin;
PA6, AF1, USART1, TxPin;
PA7, AF1, USART1, TxPin;
PA7, AF3, USART1, RxPin;
PB4, AF1, USART1, TxPin;
PB5, AF1, USART1, RxPin;
PB6, AF1, USART1, TxPin;
);
pub struct Serial<USART, TXPIN, RXPIN> {
usart: USART,
pins: (TXPIN, RXPIN),
}
type SerialRegisterBlock = crate::pac::usart1::RegisterBlock;
pub struct Rx<USART> {
usart: *const SerialRegisterBlock,
_instance: PhantomData<USART>,
}
unsafe impl<USART> Send for Rx<USART> {}
pub struct Tx<USART> {
usart: *const SerialRegisterBlock,
_instance: PhantomData<USART>,
}
unsafe impl<USART> Send for Tx<USART> {}
macro_rules! usart {
($($USART:ident: ($usart:ident, $usarttx:ident, $usartrx:ident, $usartXen:ident, $apbenr:ident),)+) => {
$(
use crate::pac::$USART;
impl<TXPIN, RXPIN> Serial<$USART, TXPIN, RXPIN>
where
TXPIN: TxPin<$USART>,
RXPIN: RxPin<$USART>,
{
/// Creates a new serial instance
pub fn $usart(usart: $USART, pins: (TXPIN, RXPIN), baud_rate: Bps, rcc: &mut Rcc) -> Self
{
let mut serial = Serial { usart, pins };
serial.configure(baud_rate, rcc);
serial.usart.cr1.modify(|_, w| w.te().set_bit().re().set_bit().ue().set_bit());
serial
}
}
impl<TXPIN> Serial<$USART, TXPIN, ()>
where
TXPIN: TxPin<$USART>,
{
pub fn $usarttx(usart: $USART, txpin: TXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self
{
let rxpin = ();
let mut serial = Serial { usart, pins: (txpin, rxpin) };
serial.configure(baud_rate, rcc);
serial.usart.cr1.modify(|_, w| w.te().set_bit().ue().set_bit());
serial
}
}
impl<RXPIN> Serial<$USART, (), RXPIN>
where
RXPIN: RxPin<$USART>,
{
pub fn $usartrx(usart: $USART, rxpin: RXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self
{
let txpin = ();
let mut serial = Serial { usart, pins: (txpin, rxpin) };
serial.configure(baud_rate, rcc);
serial.usart.cr1.modify(|_, w| w.re().set_bit().ue().set_bit());
serial
}
}
impl<TXPIN, RXPIN> Serial<$USART, TXPIN, RXPIN> {
fn configure(&mut self, baud_rate: Bps, rcc: &mut Rcc) {
rcc.regs.$apbenr.modify(|_, w| w.$usartXen().set_bit());
let brr = rcc.clocks.pclk().0 / baud_rate.0;
self.usart.brr.write(|w| unsafe { w.bits(brr) });
self.usart.cr2.reset();
self.usart.cr3.reset();
}
pub fn listen(&mut self, event: Event) {
match event {
Event::Rxne => {
self.usart.cr1.modify(|_, w| w.rxneie().set_bit())
},
Event::Txe => {
self.usart.cr1.modify(|_, w| w.txeie().set_bit())
},
Event::Idle => {
self.usart.cr1.modify(|_, w| w.idleie().set_bit())
},
}
}
pub fn unlisten(&mut self, event: Event) {
match event {
Event::Rxne => {
self.usart.cr1.modify(|_, w| w.rxneie().clear_bit())
},
Event::Txe => {
self.usart.cr1.modify(|_, w| w.txeie().clear_bit())
},
Event::Idle => {
self.usart.cr1.modify(|_, w| w.idleie().clear_bit())
},
}
}
pub fn is_idle(&self) -> bool {
self.usart.sr.read().idle().bit_is_set()
}
pub fn is_txe(&self) -> bool {
self.usart.sr.read().txe().bit_is_set()
}
pub fn is_rx_not_empty(&self) -> bool {
self.usart.sr.read().rxne().bit_is_set()
}
pub fn is_tx_complete(&self) -> bool {
self.usart.sr.read().tc().bit_is_set()
}
}
)+
}
}
#[cfg(any(
feature = "py32f002a",
feature = "py32f002b",
feature = "py32f003",
feature = "py32f030",
))]
usart! {
USART1: (usart1, usart1tx, usart1rx, usart1en, apbenr2),
}
#[cfg(any(feature = "py32f003", feature = "py32f030",))]
usart! {
USART2: (usart2, usart2tx, usart2rx,usart2en, apbenr1),
}
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> {
read(self.usart)
}
}
impl<USART, TXPIN, RXPIN> embedded_hal::serial::Read<u8> for Serial<USART, TXPIN, RXPIN>
where
USART: Deref<Target = SerialRegisterBlock>,
RXPIN: RxPin<USART>,
{
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Error> {
read(&*self.usart)
}
}
impl<USART> embedded_hal::serial::Write<u8> for Tx<USART>
where
USART: Deref<Target = SerialRegisterBlock>,
{
type Error = Infallible;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
flush(self.usart)
}
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
write(self.usart, byte)
}
}
impl<USART, TXPIN, RXPIN> embedded_hal::serial::Write<u8> for Serial<USART, TXPIN, RXPIN>
where
USART: Deref<Target = SerialRegisterBlock>,
TXPIN: TxPin<USART>,
{
type Error = Infallible;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
flush(&*self.usart)
}
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
write(&*self.usart, byte)
}
}
impl<USART, TXPIN, RXPIN> Serial<USART, TXPIN, RXPIN>
where
USART: Deref<Target = SerialRegisterBlock>,
{
pub fn split(self) -> (Tx<USART>, Rx<USART>)
where
TXPIN: TxPin<USART>,
RXPIN: RxPin<USART>,
{
(
Tx {
usart: &*self.usart,
_instance: PhantomData,
},
Rx {
usart: &*self.usart,
_instance: PhantomData,
},
)
}
pub fn release(self) -> (USART, (TXPIN, RXPIN)) {
(self.usart, self.pins)
}
}
impl<USART> Write for Tx<USART>
where
Tx<USART>: embedded_hal::serial::Write<u8>,
{
fn write_str(&mut self, s: &str) -> Result {
s.as_bytes()
.iter()
.try_for_each(|c| nb::block!(self.write(*c)))
.map_err(|_| core::fmt::Error)
}
}
impl<USART, TXPIN, RXPIN> Write for Serial<USART, TXPIN, RXPIN>
where
USART: Deref<Target = SerialRegisterBlock>,
TXPIN: TxPin<USART>,
{
fn write_str(&mut self, s: &str) -> Result {
s.as_bytes()
.iter()
.try_for_each(|c| nb::block!(self.write(*c)))
.map_err(|_| core::fmt::Error)
}
}
fn flush(usart: *const SerialRegisterBlock) -> nb::Result<(), Infallible> {
let sr = unsafe { (*usart).sr.read() };
if sr.tc().bit_is_set() {
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
fn write(usart: *const SerialRegisterBlock, byte: u8) -> nb::Result<(), Infallible> {
let sr = unsafe { (*usart).sr.read() };
if sr.txe().bit_is_set() {
unsafe { (*usart).dr.write(|w| w.dr().bits(byte as u16)) }
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
fn read(usart: *const SerialRegisterBlock) -> nb::Result<u8, Error> {
let sr = unsafe { (*usart).sr.read() };
let dr = unsafe { (*usart).dr.read() };
if sr.pe().bit_is_set() {
Err(nb::Error::Other(Error::Parity))
} else if sr.fe().bit_is_set() {
Err(nb::Error::Other(Error::Framing))
} else if sr.ne().bit_is_set() {
Err(nb::Error::Other(Error::Noise))
} else if sr.ore().bit_is_set() {
Err(nb::Error::Other(Error::Overrun))
} else if sr.rxne().bit_is_set() {
Ok(dr.dr().bits() as u8)
} else {
Err(nb::Error::WouldBlock)
}
}