use core::marker::PhantomData;
use core::ops::Deref;
use crate::gcr::{
clocks::{Clock, InternalBaudRateOscillator, PeripheralClock},
ClockForPeripheral,
};
use crate::gpio::{Af1, Pin};
use embedded_hal_nb::{nb, serial};
use paste::paste;
enum UartClockSource {
Pclk,
Ibro,
}
pub enum DataBits {
Five,
Six,
Seven,
Eight,
}
pub enum StopBits {
One,
More,
}
pub enum ParityBit {
None,
Even,
Odd,
SpaceZero,
MarkOne,
}
#[doc(hidden)]
pub mod marker {
pub trait UartState: crate::Sealed {}
#[doc(hidden)]
pub struct NotBuilt;
#[doc(hidden)]
pub struct Built;
impl crate::Sealed for NotBuilt {}
impl crate::Sealed for Built {}
impl UartState for NotBuilt {}
impl UartState for Built {}
pub trait UartClockState: crate::Sealed {}
#[doc(hidden)]
pub struct NotClockSet;
#[doc(hidden)]
pub struct ClockSet;
impl crate::Sealed for NotClockSet {}
impl crate::Sealed for ClockSet {}
impl UartClockState for NotClockSet {}
impl UartClockState for ClockSet {}
}
pub struct UartPeripheral<STATE: marker::UartState, CLOCK, UART, RX, TX, CTS, RTS> {
_state: PhantomData<STATE>,
_clock: PhantomData<CLOCK>,
uart: UART,
_rx_pin: RX,
_tx_pin: TX,
_cts_pin: CTS,
_rts_pin: RTS,
clk_src: Option<UartClockSource>,
clk_src_freq: Option<u32>,
baud: u32,
data_bits: DataBits,
stop_bits: StopBits,
parity: ParityBit,
}
pub struct BuiltUartPeripheral<UART, RX, TX, CTS, RTS> {
uart: UART,
_rx_pin: RX,
_tx_pin: TX,
_cts_pin: CTS,
_rts_pin: RTS,
}
pub trait RxPin<UART>: crate::Sealed {}
pub trait TxPin<UART>: crate::Sealed {}
type UartRegisterBlock = crate::pac::uart0::RegisterBlock;
macro_rules! uart {
(
$uart:ident,
rx: $rx_pin:ty,
tx: $tx_pin:ty,
cts: $cts_pin:ty,
rts: $rts_pin:ty,
) => {
paste! {
use crate::pac::$uart;
impl crate::Sealed for $rx_pin {}
impl RxPin<$uart> for $rx_pin {}
impl crate::Sealed for $tx_pin {}
impl TxPin<$uart> for $tx_pin {}
impl UartPeripheral<
marker::NotBuilt,
marker::NotClockSet,
$uart,
$rx_pin,
$tx_pin,
(),
(),
>
{
#[doc = "Construct a new "]
#[doc = stringify!([<$uart:upper>])]
#[doc = " peripheral."]
pub fn [<$uart:lower>](
uart: $uart,
reg: &mut crate::gcr::GcrRegisters,
rx_pin: $rx_pin,
tx_pin: $tx_pin
) -> UartPeripheral<marker::NotBuilt, marker::NotClockSet, $uart, $rx_pin, $tx_pin, (), ()> {
unsafe { uart.enable_clock(&mut reg.gcr); }
UartPeripheral {
_state: PhantomData,
_clock: PhantomData,
uart,
_rx_pin: rx_pin,
_tx_pin: tx_pin,
_cts_pin: (),
_rts_pin: (),
clk_src: None,
clk_src_freq: None,
baud: 115200,
data_bits: DataBits::Eight,
stop_bits: StopBits::One,
parity: ParityBit::None,
}
}
}
}
};
}
uart! {Uart0,
rx: Pin<0, 0, Af1>,
tx: Pin<0, 1, Af1>,
cts: (),
rts: (),
}
uart! {Uart1,
rx: Pin<0, 12, Af1>,
tx: Pin<0, 13, Af1>,
cts: (),
rts: (),
}
uart! {Uart2,
rx: Pin<1, 0, Af1>,
tx: Pin<1, 1, Af1>,
cts: (),
rts: (),
}
impl<UART, RX, TX, CTS, RTS>
UartPeripheral<marker::NotBuilt, marker::NotClockSet, UART, RX, TX, CTS, RTS>
{
pub fn clock_pclk(
self,
clock: &Clock<PeripheralClock>,
) -> UartPeripheral<marker::NotBuilt, marker::ClockSet, UART, RX, TX, CTS, RTS> {
UartPeripheral {
_state: PhantomData,
_clock: PhantomData,
uart: self.uart,
_rx_pin: self._rx_pin,
_tx_pin: self._tx_pin,
_cts_pin: self._cts_pin,
_rts_pin: self._rts_pin,
clk_src: Some(UartClockSource::Pclk),
clk_src_freq: Some(clock.frequency),
baud: self.baud,
data_bits: self.data_bits,
stop_bits: self.stop_bits,
parity: self.parity,
}
}
pub fn clock_ibro(
self,
clock: &Clock<InternalBaudRateOscillator>,
) -> UartPeripheral<marker::NotBuilt, marker::ClockSet, UART, RX, TX, CTS, RTS> {
UartPeripheral {
_state: PhantomData,
_clock: PhantomData,
uart: self.uart,
_rx_pin: self._rx_pin,
_tx_pin: self._tx_pin,
_cts_pin: self._cts_pin,
_rts_pin: self._rts_pin,
clk_src: Some(UartClockSource::Ibro),
clk_src_freq: Some(clock.frequency),
baud: self.baud,
data_bits: self.data_bits,
stop_bits: self.stop_bits,
parity: self.parity,
}
}
}
impl<CLOCK, UART, RX, TX, CTS, RTS> UartPeripheral<marker::NotBuilt, CLOCK, UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
pub fn baud(mut self, baud: u32) -> Self {
self.baud = baud;
self
}
pub fn data_bits(mut self, data_bits: DataBits) -> Self {
self.data_bits = data_bits;
self
}
pub fn stop_bits(mut self, stop_bits: StopBits) -> Self {
self.stop_bits = stop_bits;
self
}
pub fn parity(mut self, parity: ParityBit) -> Self {
self.parity = parity;
self
}
}
impl<UART, RX, TX, CTS, RTS>
UartPeripheral<marker::NotBuilt, marker::ClockSet, UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
pub fn build(self) -> BuiltUartPeripheral<UART, RX, TX, CTS, RTS> {
let clk_src_freq = self.clk_src_freq.unwrap();
self.uart.ctrl().write(|w| {
w.ucagm().set_bit();
match self.clk_src {
Some(UartClockSource::Pclk) => w.bclksrc().peripheral_clock(),
Some(UartClockSource::Ibro) => w.bclksrc().clk2(),
None => unreachable!("UART clock source not set"),
};
w.bclken().set_bit();
match self.data_bits {
DataBits::Five => w.char_size()._5bits(),
DataBits::Six => w.char_size()._6bits(),
DataBits::Seven => w.char_size()._7bits(),
DataBits::Eight => w.char_size()._8bits(),
};
match self.stop_bits {
StopBits::One => w.stopbits().clear_bit(),
StopBits::More => w.stopbits().set_bit(),
};
match self.parity {
ParityBit::None => w.par_en().clear_bit(),
ParityBit::Even => w.par_en().set_bit().par_eo().clear_bit(),
ParityBit::Odd => w.par_en().set_bit().par_eo().set_bit(),
ParityBit::SpaceZero => w.par_en().set_bit().par_md().clear_bit(),
ParityBit::MarkOne => w.par_en().set_bit().par_md().set_bit(),
};
return w;
});
let clkdiv = clk_src_freq / self.baud;
self.uart
.clkdiv()
.write(|w| unsafe { w.clkdiv().bits(clkdiv) });
while self.uart.ctrl().read().bclkrdy().bit_is_clear() {}
BuiltUartPeripheral {
uart: self.uart,
_rx_pin: self._rx_pin,
_tx_pin: self._tx_pin,
_cts_pin: self._cts_pin,
_rts_pin: self._rts_pin,
}
}
}
impl<UART, RX, TX, CTS, RTS> BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
#[doc(hidden)]
#[inline(always)]
fn _is_tx_full(&self) -> bool {
self.uart.status().read().tx_full().bit_is_set()
}
#[doc(hidden)]
#[inline(always)]
fn _is_tx_empty(&self) -> bool {
self.uart.status().read().tx_em().bit_is_set()
}
#[doc(hidden)]
#[inline(always)]
fn _is_rx_empty(&self) -> bool {
self.uart.status().read().rx_em().bit_is_set()
}
#[doc(hidden)]
#[inline(always)]
fn _read_byte(&self) -> nb::Result<u8, serial::ErrorKind> {
if self._is_rx_empty() {
return Err(nb::Error::WouldBlock);
}
Ok(self.uart.fifo().read().data().bits())
}
#[doc(hidden)]
#[inline(always)]
fn _write_byte(&self, byte: u8) -> nb::Result<(), serial::ErrorKind> {
if self._is_tx_full() {
return Err(nb::Error::WouldBlock);
}
self.uart.fifo().write(|w| unsafe { w.data().bits(byte) });
Ok(())
}
#[inline(always)]
fn flush_tx(&self) {
while !self._is_tx_empty() {}
}
pub fn read_byte(&self) -> u8 {
nb::block!(self._read_byte()).unwrap()
}
pub fn write_byte(&self, byte: u8) {
nb::block!(self._write_byte(byte)).unwrap()
}
pub fn read_bytes(&self, buffer: &mut [u8]) {
for byte in buffer {
*byte = self.read_byte();
}
}
pub fn write_bytes(&self, buffer: &[u8]) {
for byte in buffer {
self.write_byte(*byte);
}
}
}
impl<UART, RX, TX, CTS, RTS> serial::ErrorType for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
type Error = serial::ErrorKind;
}
impl<UART, RX, TX, CTS, RTS> serial::Read<u8> for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
fn read(&mut self) -> nb::Result<u8, Self::Error> {
self._read_byte()
}
}
impl<UART, RX, TX, CTS, RTS> serial::Write<u8> for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
self._write_byte(byte)
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
self.flush_tx();
Ok(())
}
}
impl<UART, RX, TX, CTS, RTS> embedded_io::ErrorType for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
type Error = core::convert::Infallible;
}
impl<UART, RX, TX, CTS, RTS> embedded_io::Read for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let mut count = 0;
if buf.len() == 0 {
return Ok(0);
}
if self._is_rx_empty() {
let byte = self.read_byte();
buf[count] = byte;
count += 1;
} else {
while count < buf.len() && !self._is_rx_empty() {
let byte = self.read_byte();
buf[count] = byte;
count += 1;
}
}
Ok(count)
}
}
impl<UART, RX, TX, CTS, RTS> embedded_io::ReadReady for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
fn read_ready(&mut self) -> Result<bool, Self::Error> {
Ok(!self._is_rx_empty())
}
}
impl<UART, RX, TX, CTS, RTS> embedded_io::Write for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
for byte in buf {
self.write_byte(*byte);
}
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.flush_tx();
Ok(())
}
}
impl<UART, RX, TX, CTS, RTS> embedded_io::WriteReady for BuiltUartPeripheral<UART, RX, TX, CTS, RTS>
where
UART: Deref<Target = UartRegisterBlock>,
{
fn write_ready(&mut self) -> Result<bool, Self::Error> {
Ok(!self._is_tx_full())
}
}