use core::fmt::{Result, Write};
use core::marker::PhantomData;
use core::ptr;
use hal;
use hal::prelude::*;
use nb;
use void::Void;
use stm32::{RCC, USART1, USART2};
use gpio::gpioa::{PA10, PA14, PA15, PA2, PA3, PA9};
use gpio::gpiob::{PB6, PB7};
use gpio::{Alternate, AF0, AF1};
use rcc::Clocks;
use time::Bps;
pub enum Event {
Rxne,
Txe,
}
#[derive(Debug)]
pub enum Error {
Framing,
Noise,
Overrun,
Parity,
#[doc(hidden)]
_Extensible,
}
pub trait Pins<USART> {}
impl Pins<USART1> for (PA9<Alternate<AF1>>, PA10<Alternate<AF1>>) {}
impl Pins<USART1> for (PB6<Alternate<AF0>>, PB7<Alternate<AF0>>) {}
impl Pins<USART1> for (PA9<Alternate<AF1>>, PB7<Alternate<AF0>>) {}
impl Pins<USART1> for (PB6<Alternate<AF0>>, PA10<Alternate<AF1>>) {}
impl Pins<USART2> for (PA2<Alternate<AF1>>, PA3<Alternate<AF1>>) {}
impl Pins<USART2> for (PA2<Alternate<AF1>>, PA15<Alternate<AF1>>) {}
impl Pins<USART2> for (PA14<Alternate<AF1>>, PA15<Alternate<AF1>>) {}
impl Pins<USART2> for (PA14<Alternate<AF1>>, PA3<Alternate<AF1>>) {}
pub struct Serial<USART, PINS> {
usart: USART,
pins: PINS,
}
pub struct Rx<USART> {
_usart: PhantomData<USART>,
}
pub struct Tx<USART> {
_usart: PhantomData<USART>,
}
impl<PINS> Serial<USART1, PINS> {
pub fn usart1(usart: USART1, pins: PINS, baud_rate: Bps, clocks: Clocks) -> Self
where
PINS: Pins<USART1>,
{
let rcc = unsafe { &(*RCC::ptr()) };
rcc.apb2enr.modify(|_, w| w.usart1en().set_bit());
let brr = clocks.pclk().0 / baud_rate.0;
usart.brr.write(|w| unsafe { w.bits(brr) });
usart.cr2.reset();
usart.cr3.reset();
usart.cr1.modify(|_, w| unsafe { w.bits(0xD) });
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)
}
}
impl hal::serial::Read<u8> for Rx<USART1> {
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Error> {
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() {
return Ok(unsafe { ptr::read_volatile(&(*USART1::ptr()).rdr as *const _ as *const _) });
} else {
nb::Error::WouldBlock
})
}
}
impl hal::serial::Write<u8> for Tx<USART1> {
type Error = Void;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
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> {
let isr = unsafe { (*USART1::ptr()).isr.read() };
if isr.txe().bit_is_set() {
unsafe { ptr::write_volatile(&(*USART1::ptr()).tdr as *const _ as *mut _, byte) }
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl<PINS> Serial<USART2, PINS> {
pub fn usart2(usart: USART2, pins: PINS, baud_rate: Bps, clocks: Clocks) -> Self
where
PINS: Pins<USART2>,
{
let rcc = unsafe { &(*RCC::ptr()) };
rcc.apb1enr.modify(|_, w| w.usart2en().set_bit());
let brr = clocks.pclk().0 / baud_rate.0;
usart.brr.write(|w| unsafe { w.bits(brr) });
usart.cr2.reset();
usart.cr3.reset();
usart.cr1.modify(|_, w| unsafe { w.bits(0xD) });
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)
}
}
impl hal::serial::Read<u8> for Rx<USART2> {
type Error = Error;
fn read(&mut self) -> nb::Result<u8, Error> {
let isr = unsafe { (*USART2::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() {
return Ok(unsafe { ptr::read_volatile(&(*USART2::ptr()).rdr as *const _ as *const _) });
} else {
nb::Error::WouldBlock
})
}
}
impl hal::serial::Write<u8> for Tx<USART2> {
type Error = Void;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
let isr = unsafe { (*USART2::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> {
let isr = unsafe { (*USART2::ptr()).isr.read() };
if isr.txe().bit_is_set() {
unsafe { ptr::write_volatile(&(*USART2::ptr()).tdr as *const _ as *mut _, byte) }
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl<USART> Write for Tx<USART>
where
Tx<USART>: hal::serial::Write<u8>,
{
fn write_str(&mut self, s: &str) -> Result {
let _ = s
.as_bytes()
.iter()
.map(|c| block!(self.write(*c)))
.last();
Ok(())
}
}