aboutsummaryrefslogtreecommitdiff
path: root/embassy-imxrt/src/flexcomm
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-imxrt/src/flexcomm')
-rw-r--r--embassy-imxrt/src/flexcomm/mod.rs252
-rw-r--r--embassy-imxrt/src/flexcomm/uart.rs1230
2 files changed, 1482 insertions, 0 deletions
diff --git a/embassy-imxrt/src/flexcomm/mod.rs b/embassy-imxrt/src/flexcomm/mod.rs
new file mode 100644
index 000000000..4473c9a77
--- /dev/null
+++ b/embassy-imxrt/src/flexcomm/mod.rs
@@ -0,0 +1,252 @@
1//! Implements Flexcomm interface wrapper for easier usage across modules
2
3pub mod uart;
4
5use paste::paste;
6
7use crate::clocks::{enable_and_reset, SysconPeripheral};
8use crate::peripherals::{
9 FLEXCOMM0, FLEXCOMM1, FLEXCOMM14, FLEXCOMM15, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7,
10};
11use crate::{pac, PeripheralType};
12
13/// clock selection option
14#[derive(Copy, Clone, Debug)]
15pub enum Clock {
16 /// SFRO
17 Sfro,
18
19 /// FFRO
20 Ffro,
21
22 /// `AUDIO_PLL`
23 AudioPll,
24
25 /// MASTER
26 Master,
27
28 /// FCn_FRG with Main clock source
29 FcnFrgMain,
30
31 /// FCn_FRG with Pll clock source
32 FcnFrgPll,
33
34 /// FCn_FRG with Sfro clock source
35 FcnFrgSfro,
36
37 /// FCn_FRG with Ffro clock source
38 FcnFrgFfro,
39
40 /// disabled
41 None,
42}
43
44/// do not allow implementation of trait outside this mod
45mod sealed {
46 /// trait does not get re-exported outside flexcomm mod, allowing us to safely expose only desired APIs
47 pub trait Sealed {}
48}
49
50/// primary low-level flexcomm interface
51pub(crate) trait FlexcommLowLevel: sealed::Sealed + PeripheralType + SysconPeripheral + 'static + Send {
52 // fetch the flexcomm register block for direct manipulation
53 fn reg() -> &'static pac::flexcomm0::RegisterBlock;
54
55 // set the clock select for this flexcomm instance and remove from reset
56 fn enable(clk: Clock);
57}
58
59macro_rules! impl_flexcomm {
60 ($($idx:expr),*) => {
61 $(
62 paste!{
63 impl sealed::Sealed for crate::peripherals::[<FLEXCOMM $idx>] {}
64
65 impl FlexcommLowLevel for crate::peripherals::[<FLEXCOMM $idx>] {
66 fn reg() -> &'static crate::pac::flexcomm0::RegisterBlock {
67 // SAFETY: safe from single executor, enforce
68 // via peripheral reference lifetime tracking
69 unsafe {
70 &*crate::pac::[<Flexcomm $idx>]::ptr()
71 }
72 }
73
74 fn enable(clk: Clock) {
75 // SAFETY: safe from single executor
76 let clkctl1 = unsafe { crate::pac::Clkctl1::steal() };
77
78 clkctl1.flexcomm($idx).fcfclksel().write(|w| match clk {
79 Clock::Sfro => w.sel().sfro_clk(),
80 Clock::Ffro => w.sel().ffro_clk(),
81 Clock::AudioPll => w.sel().audio_pll_clk(),
82 Clock::Master => w.sel().master_clk(),
83 Clock::FcnFrgMain => w.sel().fcn_frg_clk(),
84 Clock::FcnFrgPll => w.sel().fcn_frg_clk(),
85 Clock::FcnFrgSfro => w.sel().fcn_frg_clk(),
86 Clock::FcnFrgFfro => w.sel().fcn_frg_clk(),
87 Clock::None => w.sel().none(), // no clock? throw an error?
88 });
89
90 clkctl1.flexcomm($idx).frgclksel().write(|w| match clk {
91 Clock::FcnFrgMain => w.sel().main_clk(),
92 Clock::FcnFrgPll => w.sel().frg_pll_clk(),
93 Clock::FcnFrgSfro => w.sel().sfro_clk(),
94 Clock::FcnFrgFfro => w.sel().ffro_clk(),
95 _ => w.sel().none(), // not using frg ...
96 });
97
98 // todo: add support for frg div/mult
99 clkctl1
100 .flexcomm($idx)
101 .frgctl()
102 .write(|w|
103 // SAFETY: unsafe only used for .bits() call
104 unsafe { w.mult().bits(0) });
105
106 enable_and_reset::<[<FLEXCOMM $idx>]>();
107 }
108 }
109 }
110 )*
111 }
112}
113
114impl_flexcomm!(0, 1, 2, 3, 4, 5, 6, 7);
115
116// TODO: FLEXCOMM 14 is untested. Enable SPI support on FLEXCOMM14
117// Add special case FLEXCOMM14
118impl sealed::Sealed for crate::peripherals::FLEXCOMM14 {}
119
120impl FlexcommLowLevel for crate::peripherals::FLEXCOMM14 {
121 fn reg() -> &'static crate::pac::flexcomm0::RegisterBlock {
122 // SAFETY: safe from single executor, enforce
123 // via peripheral reference lifetime tracking
124 unsafe { &*crate::pac::Flexcomm14::ptr() }
125 }
126
127 fn enable(clk: Clock) {
128 // SAFETY: safe from single executor
129 let clkctl1 = unsafe { crate::pac::Clkctl1::steal() };
130
131 clkctl1.fc14fclksel().write(|w| match clk {
132 Clock::Sfro => w.sel().sfro_clk(),
133 Clock::Ffro => w.sel().ffro_clk(),
134 Clock::AudioPll => w.sel().audio_pll_clk(),
135 Clock::Master => w.sel().master_clk(),
136 Clock::FcnFrgMain => w.sel().fcn_frg_clk(),
137 Clock::FcnFrgPll => w.sel().fcn_frg_clk(),
138 Clock::FcnFrgSfro => w.sel().fcn_frg_clk(),
139 Clock::FcnFrgFfro => w.sel().fcn_frg_clk(),
140 Clock::None => w.sel().none(), // no clock? throw an error?
141 });
142
143 clkctl1.frg14clksel().write(|w| match clk {
144 Clock::FcnFrgMain => w.sel().main_clk(),
145 Clock::FcnFrgPll => w.sel().frg_pll_clk(),
146 Clock::FcnFrgSfro => w.sel().sfro_clk(),
147 Clock::FcnFrgFfro => w.sel().ffro_clk(),
148 _ => w.sel().none(), // not using frg ...
149 });
150
151 // todo: add support for frg div/mult
152 clkctl1.frg14ctl().write(|w|
153 // SAFETY: unsafe only used for .bits() call
154 unsafe { w.mult().bits(0) });
155
156 enable_and_reset::<FLEXCOMM14>();
157 }
158}
159
160// Add special case FLEXCOMM15
161impl sealed::Sealed for crate::peripherals::FLEXCOMM15 {}
162
163impl FlexcommLowLevel for crate::peripherals::FLEXCOMM15 {
164 fn reg() -> &'static crate::pac::flexcomm0::RegisterBlock {
165 // SAFETY: safe from single executor, enforce
166 // via peripheral reference lifetime tracking
167 unsafe { &*crate::pac::Flexcomm15::ptr() }
168 }
169
170 fn enable(clk: Clock) {
171 // SAFETY: safe from single executor
172 let clkctl1 = unsafe { crate::pac::Clkctl1::steal() };
173
174 clkctl1.fc15fclksel().write(|w| match clk {
175 Clock::Sfro => w.sel().sfro_clk(),
176 Clock::Ffro => w.sel().ffro_clk(),
177 Clock::AudioPll => w.sel().audio_pll_clk(),
178 Clock::Master => w.sel().master_clk(),
179 Clock::FcnFrgMain => w.sel().fcn_frg_clk(),
180 Clock::FcnFrgPll => w.sel().fcn_frg_clk(),
181 Clock::FcnFrgSfro => w.sel().fcn_frg_clk(),
182 Clock::FcnFrgFfro => w.sel().fcn_frg_clk(),
183 Clock::None => w.sel().none(), // no clock? throw an error?
184 });
185 clkctl1.frg15clksel().write(|w| match clk {
186 Clock::FcnFrgMain => w.sel().main_clk(),
187 Clock::FcnFrgPll => w.sel().frg_pll_clk(),
188 Clock::FcnFrgSfro => w.sel().sfro_clk(),
189 Clock::FcnFrgFfro => w.sel().ffro_clk(),
190 _ => w.sel().none(), // not using frg ...
191 });
192 // todo: add support for frg div/mult
193 clkctl1.frg15ctl().write(|w|
194 // SAFETY: unsafe only used for .bits() call
195 unsafe { w.mult().bits(0) });
196
197 enable_and_reset::<FLEXCOMM15>();
198 }
199}
200
201macro_rules! into_mode {
202 ($mode:ident, $($fc:ident),*) => {
203 paste! {
204 /// Sealed Mode trait
205 trait [<SealedInto $mode:camel>]: FlexcommLowLevel {}
206
207 /// Select mode of operation
208 #[allow(private_bounds)]
209 pub trait [<Into $mode:camel>]: [<SealedInto $mode:camel>] {
210 /// Set mode of operation
211 fn [<into_ $mode>]() {
212 Self::reg().pselid().write(|w| w.persel().[<$mode>]());
213 }
214 }
215 }
216
217 $(
218 paste!{
219 impl [<SealedInto $mode:camel>] for crate::peripherals::$fc {}
220 impl [<Into $mode:camel>] for crate::peripherals::$fc {}
221 }
222 )*
223 }
224}
225
226into_mode!(usart, FLEXCOMM0, FLEXCOMM1, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7);
227into_mode!(spi, FLEXCOMM0, FLEXCOMM1, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7, FLEXCOMM14);
228into_mode!(i2c, FLEXCOMM0, FLEXCOMM1, FLEXCOMM2, FLEXCOMM3, FLEXCOMM4, FLEXCOMM5, FLEXCOMM6, FLEXCOMM7, FLEXCOMM15);
229
230into_mode!(
231 i2s_transmit,
232 FLEXCOMM0,
233 FLEXCOMM1,
234 FLEXCOMM2,
235 FLEXCOMM3,
236 FLEXCOMM4,
237 FLEXCOMM5,
238 FLEXCOMM6,
239 FLEXCOMM7
240);
241
242into_mode!(
243 i2s_receive,
244 FLEXCOMM0,
245 FLEXCOMM1,
246 FLEXCOMM2,
247 FLEXCOMM3,
248 FLEXCOMM4,
249 FLEXCOMM5,
250 FLEXCOMM6,
251 FLEXCOMM7
252);
diff --git a/embassy-imxrt/src/flexcomm/uart.rs b/embassy-imxrt/src/flexcomm/uart.rs
new file mode 100644
index 000000000..230b30d43
--- /dev/null
+++ b/embassy-imxrt/src/flexcomm/uart.rs
@@ -0,0 +1,1230 @@
1//! Universal Asynchronous Receiver Transmitter (UART) driver.
2
3use core::future::poll_fn;
4use core::marker::PhantomData;
5use core::sync::atomic::{compiler_fence, AtomicU8, Ordering};
6use core::task::Poll;
7
8use embassy_futures::select::{select, Either};
9use embassy_hal_internal::drop::OnDrop;
10use embassy_hal_internal::{Peri, PeripheralType};
11use embassy_sync::waitqueue::AtomicWaker;
12use paste::paste;
13
14use crate::dma::AnyChannel;
15use crate::flexcomm::Clock;
16use crate::gpio::{AnyPin, GpioPin as Pin};
17use crate::interrupt::typelevel::Interrupt;
18use crate::iopctl::{DriveMode, DriveStrength, Inverter, IopctlPin, Pull, SlewRate};
19use crate::pac::usart0::cfg::{Clkpol, Datalen, Loop, Paritysel as Parity, Stoplen, Syncen, Syncmst};
20use crate::pac::usart0::ctl::Cc;
21use crate::sealed::Sealed;
22use crate::{dma, interrupt};
23
24/// Driver move trait.
25#[allow(private_bounds)]
26pub trait Mode: Sealed {}
27
28/// Blocking mode.
29pub struct Blocking;
30impl Sealed for Blocking {}
31impl Mode for Blocking {}
32
33/// Async mode.
34pub struct Async;
35impl Sealed for Async {}
36impl Mode for Async {}
37
38/// Uart driver.
39pub struct Uart<'a, M: Mode> {
40 tx: UartTx<'a, M>,
41 rx: UartRx<'a, M>,
42}
43
44/// Uart TX driver.
45pub struct UartTx<'a, M: Mode> {
46 info: Info,
47 tx_dma: Option<Peri<'a, AnyChannel>>,
48 _phantom: PhantomData<(&'a (), M)>,
49}
50
51/// Uart RX driver.
52pub struct UartRx<'a, M: Mode> {
53 info: Info,
54 rx_dma: Option<Peri<'a, AnyChannel>>,
55 _phantom: PhantomData<(&'a (), M)>,
56}
57
58/// UART config
59#[derive(Clone, Copy)]
60pub struct Config {
61 /// Baudrate of the Uart
62 pub baudrate: u32,
63 /// data length
64 pub data_bits: Datalen,
65 /// Parity
66 pub parity: Parity,
67 /// Stop bits
68 pub stop_bits: Stoplen,
69 /// Polarity of the clock
70 pub clock_polarity: Clkpol,
71 /// Sync/ Async operation selection
72 pub operation: Syncen,
73 /// Sync master/slave mode selection (only applicable in sync mode)
74 pub sync_mode_master_select: Syncmst,
75 /// USART continuous Clock generation enable in synchronous master mode.
76 pub continuous_clock: Cc,
77 /// Normal/ loopback mode
78 pub loopback_mode: Loop,
79 /// Clock type
80 pub clock: Clock,
81}
82
83impl Default for Config {
84 /// Default configuration for single channel sampling.
85 fn default() -> Self {
86 Self {
87 baudrate: 115_200,
88 data_bits: Datalen::Bit8,
89 parity: Parity::NoParity,
90 stop_bits: Stoplen::Bit1,
91 clock_polarity: Clkpol::FallingEdge,
92 operation: Syncen::AsynchronousMode,
93 sync_mode_master_select: Syncmst::Slave,
94 continuous_clock: Cc::ClockOnCharacter,
95 loopback_mode: Loop::Normal,
96 clock: crate::flexcomm::Clock::Sfro,
97 }
98 }
99}
100
101/// Uart Errors
102#[derive(Debug, Copy, Clone, Eq, PartialEq)]
103#[cfg_attr(feature = "defmt", derive(defmt::Format))]
104pub enum Error {
105 /// Read error
106 Read,
107
108 /// Buffer overflow
109 Overrun,
110
111 /// Noise error
112 Noise,
113
114 /// Framing error
115 Framing,
116
117 /// Parity error
118 Parity,
119
120 /// Failure
121 Fail,
122
123 /// Invalid argument
124 InvalidArgument,
125
126 /// Uart baud rate cannot be supported with the given clock
127 UnsupportedBaudrate,
128
129 /// RX FIFO Empty
130 RxFifoEmpty,
131
132 /// TX FIFO Full
133 TxFifoFull,
134
135 /// TX Busy
136 TxBusy,
137}
138/// shorthand for -> `Result<T>`
139pub type Result<T> = core::result::Result<T, Error>;
140
141impl<'a, M: Mode> UartTx<'a, M> {
142 fn new_inner<T: Instance>(tx_dma: Option<Peri<'a, AnyChannel>>) -> Self {
143 let uarttx = Self {
144 info: T::info(),
145 tx_dma,
146 _phantom: PhantomData,
147 };
148 uarttx.info.refcnt.fetch_add(1, Ordering::Relaxed);
149 uarttx
150 }
151}
152
153impl<'a, M: Mode> Drop for UartTx<'a, M> {
154 fn drop(&mut self) {
155 if self.info.refcnt.fetch_sub(1, Ordering::Relaxed) == 1 {
156 while self.info.regs.stat().read().txidle().bit_is_clear() {}
157
158 self.info.regs.fifointenclr().modify(|_, w| {
159 w.txerr()
160 .set_bit()
161 .rxerr()
162 .set_bit()
163 .txlvl()
164 .set_bit()
165 .rxlvl()
166 .set_bit()
167 });
168
169 self.info
170 .regs
171 .fifocfg()
172 .modify(|_, w| w.dmatx().clear_bit().dmarx().clear_bit());
173
174 self.info.regs.cfg().modify(|_, w| w.enable().disabled());
175 }
176 }
177}
178
179impl<'a> UartTx<'a, Blocking> {
180 /// Create a new UART which can only send data
181 /// Unidirectional Uart - Tx only
182 pub fn new_blocking<T: Instance>(_inner: Peri<'a, T>, tx: Peri<'a, impl TxPin<T>>, config: Config) -> Result<Self> {
183 tx.as_tx();
184
185 let _tx = tx.into();
186 Uart::<Blocking>::init::<T>(Some(_tx), None, None, None, config)?;
187
188 Ok(Self::new_inner::<T>(None))
189 }
190
191 fn write_byte_internal(&mut self, byte: u8) -> Result<()> {
192 // SAFETY: unsafe only used for .bits()
193 self.info
194 .regs
195 .fifowr()
196 .write(|w| unsafe { w.txdata().bits(u16::from(byte)) });
197
198 Ok(())
199 }
200
201 fn blocking_write_byte(&mut self, byte: u8) -> Result<()> {
202 while self.info.regs.fifostat().read().txnotfull().bit_is_clear() {}
203
204 // Prevent the compiler from reordering write_byte_internal()
205 // before the loop above.
206 compiler_fence(Ordering::Release);
207
208 self.write_byte_internal(byte)
209 }
210
211 fn write_byte(&mut self, byte: u8) -> Result<()> {
212 if self.info.regs.fifostat().read().txnotfull().bit_is_clear() {
213 Err(Error::TxFifoFull)
214 } else {
215 self.write_byte_internal(byte)
216 }
217 }
218
219 /// Transmit the provided buffer blocking execution until done.
220 pub fn blocking_write(&mut self, buf: &[u8]) -> Result<()> {
221 for x in buf {
222 self.blocking_write_byte(*x)?;
223 }
224
225 Ok(())
226 }
227
228 /// Transmit the provided buffer. Non-blocking version, bails out
229 /// if it would block.
230 pub fn write(&mut self, buf: &[u8]) -> Result<()> {
231 for x in buf {
232 self.write_byte(*x)?;
233 }
234
235 Ok(())
236 }
237
238 /// Flush UART TX blocking execution until done.
239 pub fn blocking_flush(&mut self) -> Result<()> {
240 while self.info.regs.stat().read().txidle().bit_is_clear() {}
241 Ok(())
242 }
243
244 /// Flush UART TX.
245 pub fn flush(&mut self) -> Result<()> {
246 if self.info.regs.stat().read().txidle().bit_is_clear() {
247 Err(Error::TxBusy)
248 } else {
249 Ok(())
250 }
251 }
252}
253
254impl<'a, M: Mode> UartRx<'a, M> {
255 fn new_inner<T: Instance>(rx_dma: Option<Peri<'a, AnyChannel>>) -> Self {
256 let uartrx = Self {
257 info: T::info(),
258 rx_dma,
259 _phantom: PhantomData,
260 };
261 uartrx.info.refcnt.fetch_add(1, Ordering::Relaxed);
262 uartrx
263 }
264}
265
266impl<'a, M: Mode> Drop for UartRx<'a, M> {
267 fn drop(&mut self) {
268 if self.info.refcnt.fetch_sub(1, Ordering::Relaxed) == 1 {
269 while self.info.regs.stat().read().rxidle().bit_is_clear() {}
270
271 self.info.regs.fifointenclr().modify(|_, w| {
272 w.txerr()
273 .set_bit()
274 .rxerr()
275 .set_bit()
276 .txlvl()
277 .set_bit()
278 .rxlvl()
279 .set_bit()
280 });
281
282 self.info
283 .regs
284 .fifocfg()
285 .modify(|_, w| w.dmatx().clear_bit().dmarx().clear_bit());
286
287 self.info.regs.cfg().modify(|_, w| w.enable().disabled());
288 }
289 }
290}
291
292impl<'a> UartRx<'a, Blocking> {
293 /// Create a new blocking UART which can only receive data
294 pub fn new_blocking<T: Instance>(_inner: Peri<'a, T>, rx: Peri<'a, impl RxPin<T>>, config: Config) -> Result<Self> {
295 rx.as_rx();
296
297 let _rx = rx.into();
298 Uart::<Blocking>::init::<T>(None, Some(_rx), None, None, config)?;
299
300 Ok(Self::new_inner::<T>(None))
301 }
302}
303
304impl UartRx<'_, Blocking> {
305 fn read_byte_internal(&mut self) -> Result<u8> {
306 if self.info.regs.fifostat().read().rxerr().bit_is_set() {
307 self.info.regs.fifocfg().modify(|_, w| w.emptyrx().set_bit());
308 self.info.regs.fifostat().modify(|_, w| w.rxerr().set_bit());
309 Err(Error::Read)
310 } else if self.info.regs.stat().read().parityerrint().bit_is_set() {
311 self.info.regs.stat().modify(|_, w| w.parityerrint().clear_bit_by_one());
312 Err(Error::Parity)
313 } else if self.info.regs.stat().read().framerrint().bit_is_set() {
314 self.info.regs.stat().modify(|_, w| w.framerrint().clear_bit_by_one());
315 Err(Error::Framing)
316 } else if self.info.regs.stat().read().rxnoiseint().bit_is_set() {
317 self.info.regs.stat().modify(|_, w| w.rxnoiseint().clear_bit_by_one());
318 Err(Error::Noise)
319 } else {
320 let byte = self.info.regs.fiford().read().rxdata().bits() as u8;
321 Ok(byte)
322 }
323 }
324
325 fn read_byte(&mut self) -> Result<u8> {
326 if self.info.regs.fifostat().read().rxnotempty().bit_is_clear() {
327 Err(Error::RxFifoEmpty)
328 } else {
329 self.read_byte_internal()
330 }
331 }
332
333 fn blocking_read_byte(&mut self) -> Result<u8> {
334 while self.info.regs.fifostat().read().rxnotempty().bit_is_clear() {}
335
336 // Prevent the compiler from reordering read_byte_internal()
337 // before the loop above.
338 compiler_fence(Ordering::Acquire);
339
340 self.read_byte_internal()
341 }
342
343 /// Read from UART RX. Non-blocking version, bails out if it would
344 /// block.
345 pub fn read(&mut self, buf: &mut [u8]) -> Result<()> {
346 for b in buf.iter_mut() {
347 *b = self.read_byte()?;
348 }
349
350 Ok(())
351 }
352
353 /// Read from UART RX blocking execution until done.
354 pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<()> {
355 for b in buf.iter_mut() {
356 *b = self.blocking_read_byte()?;
357 }
358
359 Ok(())
360 }
361}
362
363impl<'a, M: Mode> Uart<'a, M> {
364 fn init<T: Instance>(
365 tx: Option<Peri<'a, AnyPin>>,
366 rx: Option<Peri<'a, AnyPin>>,
367 rts: Option<Peri<'a, AnyPin>>,
368 cts: Option<Peri<'a, AnyPin>>,
369 config: Config,
370 ) -> Result<()> {
371 T::enable(config.clock);
372 T::into_usart();
373
374 let regs = T::info().regs;
375
376 if tx.is_some() {
377 regs.fifocfg().modify(|_, w| w.emptytx().set_bit().enabletx().enabled());
378
379 // clear FIFO error
380 regs.fifostat().write(|w| w.txerr().set_bit());
381 }
382
383 if rx.is_some() {
384 regs.fifocfg().modify(|_, w| w.emptyrx().set_bit().enablerx().enabled());
385
386 // clear FIFO error
387 regs.fifostat().write(|w| w.rxerr().set_bit());
388 }
389
390 if rts.is_some() && cts.is_some() {
391 regs.cfg().modify(|_, w| w.ctsen().enabled());
392 }
393
394 Self::set_baudrate_inner::<T>(config.baudrate, config.clock)?;
395 Self::set_uart_config::<T>(config);
396
397 Ok(())
398 }
399
400 fn get_fc_freq(clock: Clock) -> Result<u32> {
401 match clock {
402 Clock::Sfro => Ok(16_000_000),
403 Clock::Ffro => Ok(48_000_000),
404 // We only support Sfro and Ffro now.
405 _ => Err(Error::InvalidArgument),
406 }
407 }
408
409 fn set_baudrate_inner<T: Instance>(baudrate: u32, clock: Clock) -> Result<()> {
410 // Get source clock frequency according to clock type.
411 let source_clock_hz = Self::get_fc_freq(clock)?;
412
413 if baudrate == 0 {
414 return Err(Error::InvalidArgument);
415 }
416
417 let regs = T::info().regs;
418
419 // If synchronous master mode is enabled, only configure the BRG value.
420 if regs.cfg().read().syncen().is_synchronous_mode() {
421 // Master
422 if regs.cfg().read().syncmst().is_master() {
423 // Calculate the BRG value
424 let brgval = (source_clock_hz / baudrate) - 1;
425
426 // SAFETY: unsafe only used for .bits()
427 regs.brg().write(|w| unsafe { w.brgval().bits(brgval as u16) });
428 }
429 } else {
430 // Smaller values of OSR can make the sampling position within a
431 // data bit less accurate and may potentially cause more noise
432 // errors or incorrect data.
433 let (_, osr, brg) = (8..16).rev().fold(
434 (u32::MAX, u32::MAX, u32::MAX),
435 |(best_diff, best_osr, best_brg), osrval| {
436 // Compare source_clock_hz agaist with ((osrval + 1) * baudrate) to make sure
437 // (source_clock_hz / ((osrval + 1) * baudrate)) is not less than 0.
438 if source_clock_hz < ((osrval + 1) * baudrate) {
439 (best_diff, best_osr, best_brg)
440 } else {
441 let brgval = (source_clock_hz / ((osrval + 1) * baudrate)) - 1;
442 // We know brgval will not be less than 0 now, it should have already been a valid u32 value,
443 // then compare it agaist with 65535.
444 if brgval > 65535 {
445 (best_diff, best_osr, best_brg)
446 } else {
447 // Calculate the baud rate based on the BRG value
448 let candidate = source_clock_hz / ((osrval + 1) * (brgval + 1));
449
450 // Calculate the difference between the
451 // current baud rate and the desired baud rate
452 let diff = (candidate as i32 - baudrate as i32).unsigned_abs();
453
454 // Check if the current calculated difference is the best so far
455 if diff < best_diff {
456 (diff, osrval, brgval)
457 } else {
458 (best_diff, best_osr, best_brg)
459 }
460 }
461 }
462 },
463 );
464
465 // Value over range
466 if brg > 65535 {
467 return Err(Error::UnsupportedBaudrate);
468 }
469
470 // SAFETY: unsafe only used for .bits()
471 regs.osr().write(|w| unsafe { w.osrval().bits(osr as u8) });
472
473 // SAFETY: unsafe only used for .bits()
474 regs.brg().write(|w| unsafe { w.brgval().bits(brg as u16) });
475 }
476
477 Ok(())
478 }
479
480 fn set_uart_config<T: Instance>(config: Config) {
481 let regs = T::info().regs;
482
483 regs.cfg().modify(|_, w| w.enable().disabled());
484
485 regs.cfg().modify(|_, w| {
486 w.datalen()
487 .variant(config.data_bits)
488 .stoplen()
489 .variant(config.stop_bits)
490 .paritysel()
491 .variant(config.parity)
492 .loop_()
493 .variant(config.loopback_mode)
494 .syncen()
495 .variant(config.operation)
496 .clkpol()
497 .variant(config.clock_polarity)
498 });
499
500 regs.cfg().modify(|_, w| w.enable().enabled());
501 }
502
503 /// Split the Uart into a transmitter and receiver, which is particularly
504 /// useful when having two tasks correlating to transmitting and receiving.
505 pub fn split(self) -> (UartTx<'a, M>, UartRx<'a, M>) {
506 (self.tx, self.rx)
507 }
508
509 /// Split the Uart into a transmitter and receiver by mutable reference,
510 /// which is particularly useful when having two tasks correlating to
511 /// transmitting and receiving.
512 pub fn split_ref(&mut self) -> (&mut UartTx<'a, M>, &mut UartRx<'a, M>) {
513 (&mut self.tx, &mut self.rx)
514 }
515}
516
517impl<'a> Uart<'a, Blocking> {
518 /// Create a new blocking UART
519 pub fn new_blocking<T: Instance>(
520 _inner: Peri<'a, T>,
521 tx: Peri<'a, impl TxPin<T>>,
522 rx: Peri<'a, impl RxPin<T>>,
523 config: Config,
524 ) -> Result<Self> {
525 tx.as_tx();
526 rx.as_rx();
527
528 let tx = tx.into();
529 let rx = rx.into();
530
531 Self::init::<T>(Some(tx), Some(rx), None, None, config)?;
532
533 Ok(Self {
534 tx: UartTx::new_inner::<T>(None),
535 rx: UartRx::new_inner::<T>(None),
536 })
537 }
538
539 /// Read from UART RX blocking execution until done.
540 pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<()> {
541 self.rx.blocking_read(buf)
542 }
543
544 /// Read from UART RX. Non-blocking version, bails out if it would
545 /// block.
546 pub fn read(&mut self, buf: &mut [u8]) -> Result<()> {
547 self.rx.read(buf)
548 }
549
550 /// Transmit the provided buffer blocking execution until done.
551 pub fn blocking_write(&mut self, buf: &[u8]) -> Result<()> {
552 self.tx.blocking_write(buf)
553 }
554
555 /// Transmit the provided buffer. Non-blocking version, bails out
556 /// if it would block.
557 pub fn write(&mut self, buf: &[u8]) -> Result<()> {
558 self.tx.write(buf)
559 }
560
561 /// Flush UART TX blocking execution until done.
562 pub fn blocking_flush(&mut self) -> Result<()> {
563 self.tx.blocking_flush()
564 }
565
566 /// Flush UART TX.
567 pub fn flush(&mut self) -> Result<()> {
568 self.tx.flush()
569 }
570}
571
572impl<'a> UartTx<'a, Async> {
573 /// Create a new DMA enabled UART which can only send data
574 pub fn new_async<T: Instance>(
575 _inner: Peri<'a, T>,
576 tx: Peri<'a, impl TxPin<T>>,
577 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'a,
578 tx_dma: Peri<'a, impl TxDma<T>>,
579 config: Config,
580 ) -> Result<Self> {
581 tx.as_tx();
582
583 let _tx = tx.into();
584 Uart::<Async>::init::<T>(Some(_tx), None, None, None, config)?;
585
586 T::Interrupt::unpend();
587 unsafe { T::Interrupt::enable() };
588
589 Ok(Self::new_inner::<T>(Some(tx_dma.into())))
590 }
591
592 /// Transmit the provided buffer asynchronously.
593 pub async fn write(&mut self, buf: &[u8]) -> Result<()> {
594 let regs = self.info.regs;
595
596 // Disable DMA on completion/cancellation
597 let _dma_guard = OnDrop::new(|| {
598 regs.fifocfg().modify(|_, w| w.dmatx().disabled());
599 });
600
601 for chunk in buf.chunks(1024) {
602 regs.fifocfg().modify(|_, w| w.dmatx().enabled());
603
604 let ch = self.tx_dma.as_mut().unwrap().reborrow();
605 let transfer = unsafe { dma::write(ch, chunk, regs.fifowr().as_ptr() as *mut u8) };
606
607 let res = select(
608 transfer,
609 poll_fn(|cx| {
610 UART_WAKERS[self.info.index].register(cx.waker());
611
612 self.info.regs.intenset().write(|w| {
613 w.framerren()
614 .set_bit()
615 .parityerren()
616 .set_bit()
617 .rxnoiseen()
618 .set_bit()
619 .aberren()
620 .set_bit()
621 });
622
623 let stat = self.info.regs.stat().read();
624
625 self.info.regs.stat().write(|w| {
626 w.framerrint()
627 .clear_bit_by_one()
628 .parityerrint()
629 .clear_bit_by_one()
630 .rxnoiseint()
631 .clear_bit_by_one()
632 .aberr()
633 .clear_bit_by_one()
634 });
635
636 if stat.framerrint().bit_is_set() {
637 Poll::Ready(Err(Error::Framing))
638 } else if stat.parityerrint().bit_is_set() {
639 Poll::Ready(Err(Error::Parity))
640 } else if stat.rxnoiseint().bit_is_set() {
641 Poll::Ready(Err(Error::Noise))
642 } else if stat.aberr().bit_is_set() {
643 Poll::Ready(Err(Error::Fail))
644 } else {
645 Poll::Pending
646 }
647 }),
648 )
649 .await;
650
651 match res {
652 Either::First(()) | Either::Second(Ok(())) => (),
653 Either::Second(e) => return e,
654 }
655 }
656
657 Ok(())
658 }
659
660 /// Flush UART TX asynchronously.
661 pub async fn flush(&mut self) -> Result<()> {
662 self.wait_on(
663 |me| {
664 if me.info.regs.stat().read().txidle().bit_is_set() {
665 Poll::Ready(Ok(()))
666 } else {
667 Poll::Pending
668 }
669 },
670 |me| {
671 me.info.regs.intenset().write(|w| w.txidleen().set_bit());
672 },
673 )
674 .await
675 }
676
677 /// Calls `f` to check if we are ready or not.
678 /// If not, `g` is called once the waker is set (to eg enable the required interrupts).
679 async fn wait_on<F, U, G>(&mut self, mut f: F, mut g: G) -> U
680 where
681 F: FnMut(&mut Self) -> Poll<U>,
682 G: FnMut(&mut Self),
683 {
684 poll_fn(|cx| {
685 // Register waker before checking condition, to ensure that wakes/interrupts
686 // aren't lost between f() and g()
687 UART_WAKERS[self.info.index].register(cx.waker());
688 let r = f(self);
689
690 if r.is_pending() {
691 g(self);
692 }
693
694 r
695 })
696 .await
697 }
698}
699
700impl<'a> UartRx<'a, Async> {
701 /// Create a new DMA enabled UART which can only receive data
702 pub fn new_async<T: Instance>(
703 _inner: Peri<'a, T>,
704 rx: Peri<'a, impl RxPin<T>>,
705 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'a,
706 rx_dma: Peri<'a, impl RxDma<T>>,
707 config: Config,
708 ) -> Result<Self> {
709 rx.as_rx();
710
711 let _rx = rx.into();
712 Uart::<Async>::init::<T>(None, Some(_rx), None, None, config)?;
713
714 T::Interrupt::unpend();
715 unsafe { T::Interrupt::enable() };
716
717 Ok(Self::new_inner::<T>(Some(rx_dma.into())))
718 }
719
720 /// Read from UART RX asynchronously.
721 pub async fn read(&mut self, buf: &mut [u8]) -> Result<()> {
722 let regs = self.info.regs;
723
724 // Disable DMA on completion/cancellation
725 let _dma_guard = OnDrop::new(|| {
726 regs.fifocfg().modify(|_, w| w.dmarx().disabled());
727 });
728
729 for chunk in buf.chunks_mut(1024) {
730 regs.fifocfg().modify(|_, w| w.dmarx().enabled());
731
732 let ch = self.rx_dma.as_mut().unwrap().reborrow();
733 let transfer = unsafe { dma::read(ch, regs.fiford().as_ptr() as *const u8, chunk) };
734
735 let res = select(
736 transfer,
737 poll_fn(|cx| {
738 UART_WAKERS[self.info.index].register(cx.waker());
739
740 self.info.regs.intenset().write(|w| {
741 w.framerren()
742 .set_bit()
743 .parityerren()
744 .set_bit()
745 .rxnoiseen()
746 .set_bit()
747 .aberren()
748 .set_bit()
749 });
750
751 let stat = self.info.regs.stat().read();
752
753 self.info.regs.stat().write(|w| {
754 w.framerrint()
755 .clear_bit_by_one()
756 .parityerrint()
757 .clear_bit_by_one()
758 .rxnoiseint()
759 .clear_bit_by_one()
760 .aberr()
761 .clear_bit_by_one()
762 });
763
764 if stat.framerrint().bit_is_set() {
765 Poll::Ready(Err(Error::Framing))
766 } else if stat.parityerrint().bit_is_set() {
767 Poll::Ready(Err(Error::Parity))
768 } else if stat.rxnoiseint().bit_is_set() {
769 Poll::Ready(Err(Error::Noise))
770 } else if stat.aberr().bit_is_set() {
771 Poll::Ready(Err(Error::Fail))
772 } else {
773 Poll::Pending
774 }
775 }),
776 )
777 .await;
778
779 match res {
780 Either::First(()) | Either::Second(Ok(())) => (),
781 Either::Second(e) => return e,
782 }
783 }
784
785 Ok(())
786 }
787}
788
789impl<'a> Uart<'a, Async> {
790 /// Create a new DMA enabled UART
791 pub fn new_async<T: Instance>(
792 _inner: Peri<'a, T>,
793 tx: Peri<'a, impl TxPin<T>>,
794 rx: Peri<'a, impl RxPin<T>>,
795 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'a,
796 tx_dma: Peri<'a, impl TxDma<T>>,
797 rx_dma: Peri<'a, impl RxDma<T>>,
798 config: Config,
799 ) -> Result<Self> {
800 tx.as_tx();
801 rx.as_rx();
802
803 let tx = tx.into();
804 let rx = rx.into();
805
806 T::Interrupt::unpend();
807 unsafe { T::Interrupt::enable() };
808
809 Self::init::<T>(Some(tx), Some(rx), None, None, config)?;
810
811 Ok(Self {
812 tx: UartTx::new_inner::<T>(Some(tx_dma.into())),
813 rx: UartRx::new_inner::<T>(Some(rx_dma.into())),
814 })
815 }
816
817 /// Create a new DMA enabled UART with hardware flow control (RTS/CTS)
818 pub fn new_with_rtscts<T: Instance>(
819 _inner: Peri<'a, T>,
820 tx: Peri<'a, impl TxPin<T>>,
821 rx: Peri<'a, impl RxPin<T>>,
822 rts: Peri<'a, impl RtsPin<T>>,
823 cts: Peri<'a, impl CtsPin<T>>,
824 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'a,
825 tx_dma: Peri<'a, impl TxDma<T>>,
826 rx_dma: Peri<'a, impl RxDma<T>>,
827 config: Config,
828 ) -> Result<Self> {
829 tx.as_tx();
830 rx.as_rx();
831 rts.as_rts();
832 cts.as_cts();
833
834 let tx = tx.into();
835 let rx = rx.into();
836 let rts = rts.into();
837 let cts = cts.into();
838
839 Self::init::<T>(Some(tx), Some(rx), Some(rts), Some(cts), config)?;
840
841 Ok(Self {
842 tx: UartTx::new_inner::<T>(Some(tx_dma.into())),
843 rx: UartRx::new_inner::<T>(Some(rx_dma.into())),
844 })
845 }
846
847 /// Read from UART RX.
848 pub async fn read(&mut self, buf: &mut [u8]) -> Result<()> {
849 self.rx.read(buf).await
850 }
851
852 /// Transmit the provided buffer.
853 pub async fn write(&mut self, buf: &[u8]) -> Result<()> {
854 self.tx.write(buf).await
855 }
856
857 /// Flush UART TX.
858 pub async fn flush(&mut self) -> Result<()> {
859 self.tx.flush().await
860 }
861}
862
863impl embedded_hal_02::serial::Read<u8> for UartRx<'_, Blocking> {
864 type Error = Error;
865
866 fn read(&mut self) -> core::result::Result<u8, nb::Error<Self::Error>> {
867 let mut buf = [0; 1];
868
869 match self.read(&mut buf) {
870 Ok(_) => Ok(buf[0]),
871 Err(Error::RxFifoEmpty) => Err(nb::Error::WouldBlock),
872 Err(e) => Err(nb::Error::Other(e)),
873 }
874 }
875}
876
877impl embedded_hal_02::serial::Write<u8> for UartTx<'_, Blocking> {
878 type Error = Error;
879
880 fn write(&mut self, word: u8) -> core::result::Result<(), nb::Error<Self::Error>> {
881 match self.write(&[word]) {
882 Ok(_) => Ok(()),
883 Err(Error::TxFifoFull) => Err(nb::Error::WouldBlock),
884 Err(e) => Err(nb::Error::Other(e)),
885 }
886 }
887
888 fn flush(&mut self) -> core::result::Result<(), nb::Error<Self::Error>> {
889 match self.flush() {
890 Ok(_) => Ok(()),
891 Err(Error::TxBusy) => Err(nb::Error::WouldBlock),
892 Err(e) => Err(nb::Error::Other(e)),
893 }
894 }
895}
896
897impl embedded_hal_02::blocking::serial::Write<u8> for UartTx<'_, Blocking> {
898 type Error = Error;
899
900 fn bwrite_all(&mut self, buffer: &[u8]) -> core::result::Result<(), Self::Error> {
901 self.blocking_write(buffer)
902 }
903
904 fn bflush(&mut self) -> core::result::Result<(), Self::Error> {
905 self.blocking_flush()
906 }
907}
908
909impl embedded_hal_02::serial::Read<u8> for Uart<'_, Blocking> {
910 type Error = Error;
911
912 fn read(&mut self) -> core::result::Result<u8, nb::Error<Self::Error>> {
913 embedded_hal_02::serial::Read::read(&mut self.rx)
914 }
915}
916
917impl embedded_hal_02::serial::Write<u8> for Uart<'_, Blocking> {
918 type Error = Error;
919
920 fn write(&mut self, word: u8) -> core::result::Result<(), nb::Error<Self::Error>> {
921 embedded_hal_02::serial::Write::write(&mut self.tx, word)
922 }
923
924 fn flush(&mut self) -> core::result::Result<(), nb::Error<Self::Error>> {
925 embedded_hal_02::serial::Write::flush(&mut self.tx)
926 }
927}
928
929impl embedded_hal_02::blocking::serial::Write<u8> for Uart<'_, Blocking> {
930 type Error = Error;
931
932 fn bwrite_all(&mut self, buffer: &[u8]) -> core::result::Result<(), Self::Error> {
933 self.blocking_write(buffer)
934 }
935
936 fn bflush(&mut self) -> core::result::Result<(), Self::Error> {
937 self.blocking_flush()
938 }
939}
940
941impl embedded_hal_nb::serial::Error for Error {
942 fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
943 match *self {
944 Self::Framing => embedded_hal_nb::serial::ErrorKind::FrameFormat,
945 Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun,
946 Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity,
947 Self::Noise => embedded_hal_nb::serial::ErrorKind::Noise,
948 _ => embedded_hal_nb::serial::ErrorKind::Other,
949 }
950 }
951}
952
953impl embedded_hal_nb::serial::ErrorType for UartRx<'_, Blocking> {
954 type Error = Error;
955}
956
957impl embedded_hal_nb::serial::ErrorType for UartTx<'_, Blocking> {
958 type Error = Error;
959}
960
961impl embedded_hal_nb::serial::ErrorType for Uart<'_, Blocking> {
962 type Error = Error;
963}
964
965impl embedded_hal_nb::serial::Read for UartRx<'_, Blocking> {
966 fn read(&mut self) -> nb::Result<u8, Self::Error> {
967 let mut buf = [0; 1];
968
969 match self.read(&mut buf) {
970 Ok(_) => Ok(buf[0]),
971 Err(Error::RxFifoEmpty) => Err(nb::Error::WouldBlock),
972 Err(e) => Err(nb::Error::Other(e)),
973 }
974 }
975}
976
977impl embedded_hal_nb::serial::Write for UartTx<'_, Blocking> {
978 fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
979 match self.write(&[word]) {
980 Ok(_) => Ok(()),
981 Err(Error::TxFifoFull) => Err(nb::Error::WouldBlock),
982 Err(e) => Err(nb::Error::Other(e)),
983 }
984 }
985
986 fn flush(&mut self) -> nb::Result<(), Self::Error> {
987 match self.flush() {
988 Ok(_) => Ok(()),
989 Err(Error::TxBusy) => Err(nb::Error::WouldBlock),
990 Err(e) => Err(nb::Error::Other(e)),
991 }
992 }
993}
994
995impl embedded_hal_nb::serial::Read for Uart<'_, Blocking> {
996 fn read(&mut self) -> core::result::Result<u8, nb::Error<Self::Error>> {
997 embedded_hal_02::serial::Read::read(&mut self.rx)
998 }
999}
1000
1001impl embedded_hal_nb::serial::Write for Uart<'_, Blocking> {
1002 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
1003 self.blocking_write(&[char]).map_err(nb::Error::Other)
1004 }
1005
1006 fn flush(&mut self) -> nb::Result<(), Self::Error> {
1007 self.blocking_flush().map_err(nb::Error::Other)
1008 }
1009}
1010
1011struct Info {
1012 regs: &'static crate::pac::usart0::RegisterBlock,
1013 index: usize,
1014 refcnt: AtomicU8,
1015}
1016
1017trait SealedInstance {
1018 fn info() -> Info;
1019 fn index() -> usize;
1020}
1021
1022/// UART interrupt handler.
1023pub struct InterruptHandler<T: Instance> {
1024 _phantom: PhantomData<T>,
1025}
1026
1027const UART_COUNT: usize = 8;
1028static UART_WAKERS: [AtomicWaker; UART_COUNT] = [const { AtomicWaker::new() }; UART_COUNT];
1029
1030impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
1031 unsafe fn on_interrupt() {
1032 let waker = &UART_WAKERS[T::index()];
1033 let regs = T::info().regs;
1034 let stat = regs.intstat().read();
1035
1036 if stat.txidle().bit_is_set()
1037 || stat.framerrint().bit_is_set()
1038 || stat.parityerrint().bit_is_set()
1039 || stat.rxnoiseint().bit_is_set()
1040 || stat.aberrint().bit_is_set()
1041 {
1042 regs.intenclr().write(|w| {
1043 w.txidleclr()
1044 .set_bit()
1045 .framerrclr()
1046 .set_bit()
1047 .parityerrclr()
1048 .set_bit()
1049 .rxnoiseclr()
1050 .set_bit()
1051 .aberrclr()
1052 .set_bit()
1053 });
1054 }
1055
1056 waker.wake();
1057 }
1058}
1059
1060/// UART instance trait.
1061#[allow(private_bounds)]
1062pub trait Instance: crate::flexcomm::IntoUsart + SealedInstance + PeripheralType + 'static + Send {
1063 /// Interrupt for this UART instance.
1064 type Interrupt: interrupt::typelevel::Interrupt;
1065}
1066
1067macro_rules! impl_instance {
1068 ($($n:expr),*) => {
1069 $(
1070 paste!{
1071 impl SealedInstance for crate::peripherals::[<FLEXCOMM $n>] {
1072 fn info() -> Info {
1073 Info {
1074 regs: unsafe { &*crate::pac::[<Usart $n>]::ptr() },
1075 index: $n,
1076 refcnt: AtomicU8::new(0),
1077 }
1078 }
1079
1080 #[inline]
1081 fn index() -> usize {
1082 $n
1083 }
1084 }
1085
1086 impl Instance for crate::peripherals::[<FLEXCOMM $n>] {
1087 type Interrupt = crate::interrupt::typelevel::[<FLEXCOMM $n>];
1088 }
1089 }
1090 )*
1091 };
1092}
1093
1094impl_instance!(0, 1, 2, 3, 4, 5, 6, 7);
1095
1096impl<T: Pin> Sealed for T {}
1097
1098/// io configuration trait for Uart Tx configuration
1099pub trait TxPin<T: Instance>: Pin + Sealed + PeripheralType {
1100 /// convert the pin to appropriate function for Uart Tx usage
1101 fn as_tx(&self);
1102}
1103
1104/// io configuration trait for Uart Rx configuration
1105pub trait RxPin<T: Instance>: Pin + Sealed + PeripheralType {
1106 /// convert the pin to appropriate function for Uart Rx usage
1107 fn as_rx(&self);
1108}
1109
1110/// io configuration trait for Uart Cts
1111pub trait CtsPin<T: Instance>: Pin + Sealed + PeripheralType {
1112 /// convert the pin to appropriate function for Uart Cts usage
1113 fn as_cts(&self);
1114}
1115
1116/// io configuration trait for Uart Rts
1117pub trait RtsPin<T: Instance>: Pin + Sealed + PeripheralType {
1118 /// convert the pin to appropriate function for Uart Rts usage
1119 fn as_rts(&self);
1120}
1121
1122macro_rules! impl_pin_trait {
1123 ($fcn:ident, $mode:ident, $($pin:ident, $fn:ident),*) => {
1124 paste! {
1125 $(
1126 impl [<$mode:camel Pin>]<crate::peripherals::$fcn> for crate::peripherals::$pin {
1127 fn [<as_ $mode>](&self) {
1128 // UM11147 table 507 pg 495
1129 self.set_function(crate::iopctl::Function::$fn)
1130 .set_pull(Pull::None)
1131 .enable_input_buffer()
1132 .set_slew_rate(SlewRate::Standard)
1133 .set_drive_strength(DriveStrength::Normal)
1134 .disable_analog_multiplex()
1135 .set_drive_mode(DriveMode::PushPull)
1136 .set_input_inverter(Inverter::Disabled);
1137 }
1138 }
1139 )*
1140 }
1141 };
1142}
1143
1144// FLEXCOMM0
1145impl_pin_trait!(FLEXCOMM0, tx, PIO0_1, F1, PIO3_1, F5);
1146impl_pin_trait!(FLEXCOMM0, rx, PIO0_2, F1, PIO3_2, F5);
1147impl_pin_trait!(FLEXCOMM0, cts, PIO0_3, F1, PIO3_3, F5);
1148impl_pin_trait!(FLEXCOMM0, rts, PIO0_4, F1, PIO3_4, F5);
1149
1150// FLEXCOMM1
1151impl_pin_trait!(FLEXCOMM1, tx, PIO0_8, F1, PIO7_26, F1);
1152impl_pin_trait!(FLEXCOMM1, rx, PIO0_9, F1, PIO7_27, F1);
1153impl_pin_trait!(FLEXCOMM1, cts, PIO0_10, F1, PIO7_28, F1);
1154impl_pin_trait!(FLEXCOMM1, rts, PIO0_11, F1, PIO7_29, F1);
1155
1156// FLEXCOMM2
1157impl_pin_trait!(FLEXCOMM2, tx, PIO0_15, F1, PIO7_30, F5);
1158impl_pin_trait!(FLEXCOMM2, rx, PIO0_16, F1, PIO7_31, F5);
1159impl_pin_trait!(FLEXCOMM2, cts, PIO0_17, F1, PIO4_8, F5);
1160impl_pin_trait!(FLEXCOMM2, rts, PIO0_18, F1);
1161
1162// FLEXCOMM3
1163impl_pin_trait!(FLEXCOMM3, tx, PIO0_22, F1);
1164impl_pin_trait!(FLEXCOMM3, rx, PIO0_23, F1);
1165impl_pin_trait!(FLEXCOMM3, cts, PIO0_24, F1);
1166impl_pin_trait!(FLEXCOMM3, rts, PIO0_25, F1);
1167
1168// FLEXCOMM4
1169impl_pin_trait!(FLEXCOMM4, tx, PIO0_29, F1);
1170impl_pin_trait!(FLEXCOMM4, rx, PIO0_30, F1);
1171impl_pin_trait!(FLEXCOMM4, cts, PIO0_31, F1);
1172impl_pin_trait!(FLEXCOMM4, rts, PIO1_0, F1);
1173
1174// FLEXCOMM5
1175impl_pin_trait!(FLEXCOMM5, tx, PIO1_4, F1, PIO3_16, F5);
1176impl_pin_trait!(FLEXCOMM5, rx, PIO1_5, F1, PIO3_17, F5);
1177impl_pin_trait!(FLEXCOMM5, cts, PIO1_6, F1, PIO3_18, F5);
1178impl_pin_trait!(FLEXCOMM5, rts, PIO1_7, F1, PIO3_23, F5);
1179
1180// FLEXCOMM6
1181impl_pin_trait!(FLEXCOMM6, tx, PIO3_26, F1);
1182impl_pin_trait!(FLEXCOMM6, rx, PIO3_27, F1);
1183impl_pin_trait!(FLEXCOMM6, cts, PIO3_28, F1);
1184impl_pin_trait!(FLEXCOMM6, rts, PIO3_29, F1);
1185
1186// FLEXCOMM7
1187impl_pin_trait!(FLEXCOMM7, tx, PIO4_1, F1);
1188impl_pin_trait!(FLEXCOMM7, rx, PIO4_2, F1);
1189impl_pin_trait!(FLEXCOMM7, cts, PIO4_3, F1);
1190impl_pin_trait!(FLEXCOMM7, rts, PIO4_4, F1);
1191
1192/// UART Tx DMA trait.
1193#[allow(private_bounds)]
1194pub trait TxDma<T: Instance>: crate::dma::Channel {}
1195
1196/// UART Rx DMA trait.
1197#[allow(private_bounds)]
1198pub trait RxDma<T: Instance>: crate::dma::Channel {}
1199
1200macro_rules! impl_dma {
1201 ($fcn:ident, $mode:ident, $dma:ident) => {
1202 paste! {
1203 impl [<$mode Dma>]<crate::peripherals::$fcn> for crate::peripherals::$dma {}
1204 }
1205 };
1206}
1207
1208impl_dma!(FLEXCOMM0, Rx, DMA0_CH0);
1209impl_dma!(FLEXCOMM0, Tx, DMA0_CH1);
1210
1211impl_dma!(FLEXCOMM1, Rx, DMA0_CH2);
1212impl_dma!(FLEXCOMM1, Tx, DMA0_CH3);
1213
1214impl_dma!(FLEXCOMM2, Rx, DMA0_CH4);
1215impl_dma!(FLEXCOMM2, Tx, DMA0_CH5);
1216
1217impl_dma!(FLEXCOMM3, Rx, DMA0_CH6);
1218impl_dma!(FLEXCOMM3, Tx, DMA0_CH7);
1219
1220impl_dma!(FLEXCOMM4, Rx, DMA0_CH8);
1221impl_dma!(FLEXCOMM4, Tx, DMA0_CH9);
1222
1223impl_dma!(FLEXCOMM5, Rx, DMA0_CH10);
1224impl_dma!(FLEXCOMM5, Tx, DMA0_CH11);
1225
1226impl_dma!(FLEXCOMM6, Rx, DMA0_CH12);
1227impl_dma!(FLEXCOMM6, Tx, DMA0_CH13);
1228
1229impl_dma!(FLEXCOMM7, Rx, DMA0_CH14);
1230impl_dma!(FLEXCOMM7, Tx, DMA0_CH15);