1extern crate nb;
2
3use {
5 crate::clock::{Enabled, Uart0Clock, Uart1Clock},
6 crate::gpio::{Pa10, Pa9, PfA},
7 crate::pac::{UART0, UART1},
8 core::marker::PhantomData,
9 hal::{serial::Read, serial::Write},
10 paste::paste,
11};
12
13#[cfg(feature = "atsam4s")]
14use crate::gpio::{Pb2, Pb3};
15
16#[cfg(any(feature = "atsam4e", feature = "atsam4n"))]
17use crate::gpio::{Pa5, Pa6, PfC};
18
19#[derive(Debug, defmt::Format)]
20pub enum Parity {
21 Even,
22 Odd,
23 Space,
24 Mark,
25}
26
27#[derive(Debug, defmt::Format)]
28pub enum CharacterLength {
29 FiveBits,
30 SixBits,
31 SevenBits,
32 EightBits,
33}
34
35#[derive(Debug, defmt::Format)]
36pub enum StopBits {
37 One,
38 OnePointFive,
39 Two,
40}
41
42#[derive(Debug, defmt::Format)]
43pub enum Error {
44 Overrun,
46 }
48
49macro_rules! uarts {
50 (
51 $($PortType:ident: (
52 $UART:ident,
53 $Uart:ident,
54 $uart:ident,
55 $pin_rx:ty,
56 $pin_tx:ty
57 ),)+
58 ) => {
59 paste! {
60 $(
61 pub struct $PortType {
62 uart: $UART,
63 clock: PhantomData<[<$Uart Clock>]<Enabled>>,
64 rx_pin: PhantomData<$pin_rx>,
65 tx_pin: PhantomData<$pin_tx>,
66 }
67
68 impl $PortType {
69 pub fn new (
70 mut uart: $UART,
71 clock: [<$Uart Clock>]<Enabled>,
72 _rx_pin: $pin_rx,
73 _tx_pin: $pin_tx,
74 baud_rate: u32,
75 parity: Option<Parity>,
76 ) -> Self {
77 Self::reset_and_disable(&mut uart);
78
79 let clock_divisor:u32 = ((clock.frequency() / baud_rate) / 16).raw();
80 if !(1..=65535).contains(&clock_divisor) {
81 panic!("Unsupported baud_rate specified for serial device (cd = {})", clock_divisor);
82 }
83
84 uart.brgr.write(|w| unsafe { w.bits(clock_divisor) });
86
87 uart.mr.write(|w| unsafe {
89 if let Some(parity) = parity {
91 let p = match parity {
92 Parity::Even => 0,
93 Parity::Odd => 1,
94 Parity::Space => 2,
95 Parity::Mark => 3,
96 };
97 w.par().bits(p);
98 }
99 else {
100 w.par().bits(4); }
102
103 w.chmode().bits(0) });
105
106 Self::enable(&mut uart);
107
108 $PortType {
109 uart,
110 clock: PhantomData,
111 rx_pin: PhantomData,
112 tx_pin: PhantomData,
113 }
114 }
115
116 fn reset_and_disable(uart: &mut $UART) {
117 unsafe { uart.cr.write_with_zero(|w| {
118 w.rstrx().set_bit().rsttx().set_bit().rxdis().set_bit().txdis().set_bit()
119 })};
120 }
121
122 fn enable(uart: &mut $UART) {
123 unsafe {uart.cr.write_with_zero(|w| {
124 w.rxen().set_bit().txen().set_bit()
125 })};
126 }
127
128 pub fn write_string_blocking(&mut self, data: &str) {
129 for c in data.chars() {
130 loop {
131 if let Err(_e) = self.write(c as u8) {
132 continue;
133 }
134
135 break;
136 }
137 }
138 }
139 }
140
141 impl Read<u8> for $PortType {
142 type Error = Error;
143
144 fn read(&mut self) -> nb::Result<u8, Error> {
145 let isr = self.uart.sr.read();
147
148 if isr.ovre().bit_is_set() {
149 Err(nb::Error::Other(Error::Overrun))
151 }
152 else if isr.rxrdy().bit_is_set() {
154 Ok(self.uart.rhr.read().bits() as u8)
156 } else {
157 Err(nb::Error::WouldBlock)
159 }
160 }
161 }
162
163 impl Write<u8> for $PortType {
164 type Error = Error;
165
166 fn write(&mut self, byte: u8) -> nb::Result<(), Error> {
167 let isr = self.uart.sr.read();
169
170 if isr.txrdy().bit_is_set() {
172 unsafe { Ok(self.uart.thr.write_with_zero(|w| w.txchr().bits(byte) )) }
173 } else {
174 Err(nb::Error::WouldBlock)
176 }
177 }
178
179 fn flush(&mut self) -> nb::Result<(), Error> {
180 Err(nb::Error::WouldBlock)
182 }
183 }
184 )+
185 }
186 }
187}
188
189#[cfg(any(feature = "atsam4e", feature = "atsam4n"))]
190uarts!(
191 Uart0: (UART0, Uart0, uart0, Pa9<PfA>, Pa10<PfA>),
192 Uart1: (UART1, Uart1, uart1, Pa5<PfC>, Pa6<PfC>),
193);
194
195#[cfg(feature = "atsam4s")]
196uarts!(
197 Uart0: (UART0, Uart0, uart0, Pa9<PfA>, Pa10<PfA>),
198 Uart1: (UART1, Uart1, uart1, Pb2<PfA>, Pb3<PfA>),
199);
200
201pub type Serial0 = Uart0;
202pub type Serial1 = Uart1;