atsamd_hal/sercom/uart.rs
1//! Use the SERCOM peripheral for UART communications
2//!
3//! Configuring an UART peripheral occurs in three steps. First, you must create
4//! a set of [`Pads`] for use by the peripheral. Next, you assemble pieces into
5//! a [`Config`] struct. After configuring the peripheral, you then [`enable`]
6//! it, yielding a functional [`Uart`] struct. Transactions are performed using
7//! the [`embedded_io::Write`], [`embedded_io::Read`],
8//! [`embedded_hal_nb::serial::Write`], and [`embedded_hal_nb::serial::Read`]
9//! traits.
10//!
11//! # [`Pads`]
12//!
13//! A [`Sercom`] can use up to four [`Pin`]s as peripheral [`Pad`]s, but only
14//! certain [`Pin`] combinations are acceptable. In particular, all [`Pin`]s
15//! must be mapped to the same `Sercom` (see the datasheet). This HAL makes it
16//! impossible to use invalid [`Pin`]/[`Pad`] combinations, and the [`Pads`]
17//! struct is responsible for enforcing these constraints.
18//!
19//!
20//! A `Pads` type takes five or six type parameters, depending on the chip.The
21//! first type always specifies the `Sercom`. On SAMx5x chips, the second type
22//! specifies the `IoSet`. The remaining four, `DI`, `DO`, `CK` and `SS`,
23//! represent the Data In, Data Out, Sclk and SS pads respectively. Each of the
24//! remaining type parameters is an [`OptionalPad`] and defaults to [`NoneT`]. A
25//! [`Pad`] is just a [`Pin`] configured in the correct [`PinMode`] that
26//! implements [`IsPad`]. The [`bsp_pins!`](crate::bsp_pins) macro can be used
27//! to define convenient type aliases for [`Pad`] types.
28//!
29//! ```
30//! use atsamd_hal::gpio::{PA08, PA09, AlternateC};
31//! use atsamd_hal::sercom::{Sercom0, uart};
32//! use atsamd_hal::typelevel::NoneT;
33//!
34//! type Rx = Pin<PA08, AlternateC>;
35//! type Tx = Pin<PA09, AlternateC>;
36//! type Pads = uart::Pads<Sercom0, Rx, Tx>;
37//! ```
38//!
39//! Alternatively, you can use the [`PadsFromIds`] alias to define a set of
40//! `Pads` in terms of [`PinId`]s instead of `Pin`s. This is useful when you
41//! don't have [`Pin`] aliases pre-defined.
42//!
43//! ```
44//! use atsamd_hal::gpio::{PA08, PA09};
45//! use atsamd_hal::sercom::{Sercom0, uart};
46//!
47//! type Pads = uart::PadsFromIds<Sercom0, PA08, PA09>;
48//! ```
49//!
50//! Instances of [`Pads`] are created using the builder pattern. Start by
51//! creating an empty set of [`Pads`] using [`Default`]. Then pass each
52//! respective [`Pin`] using the corresponding methods.
53//!
54//! On SAMD21 and SAMx5x chips, the builder methods automatically convert each
55//! pin to the correct [`PinMode`]. But for SAMD11 chips, users must manually
56//! convert each pin before calling the builder methods. This is a consequence
57//! of inherent ambiguities in the SAMD11 SERCOM pad definitions. Specifically,
58//! the same [`PinId`] can correspond to two different [`PadNum`]s for the
59//! *same* `Sercom`.
60//!
61//! ```
62//! use atsamd_hal::pac::Peripherals;
63//! use atsamd_hal::gpio::Pins;
64//! use atsamd_hal::sercom::{Sercom0, uart};
65//!
66//! let mut peripherals = Peripherals::take().unwrap();
67//! let pins = Pins::new(peripherals.PORT);
68//! let pads = uart::Pads::<Sercom0>::default()
69//! .rx(pins.pa09)
70//! .tx(pins.pa08);
71//! ```
72//!
73//! To be accepted as [`ValidPads`], a set of [`Pads`] must do two things:
74//! - Specify a type for at least one of `RX` or `TX`
75//! - Satisfy the `RxpoTxpo` trait (SAMD11/SAMD21), or the `Rxpo` and `Txpo`
76//! traits (SAMx5x)
77//!
78//! # [`Config`]
79//!
80//! Next, create a [`Config`] struct, which represents the UART peripheral in
81//! its disabled state. A [`Config`] is specified with two type parameters: the
82//! [`Pads`] type; and a [`CharSize`], which defaults to [`EightBit`].
83//!
84//! ```
85//! use atsamd_hal::gpio::{PA08, PA09};
86//! use atsamd_hal::sercom::{Sercom0, uart};
87//! use atsamd_hal::sercom::uart::{NineBit};
88//! use atsamd_hal::typelevel::NoneT;
89//!
90//! type Pads = uart::PadsFromIds<Sercom0, PA08, PA09>;
91//! type Config = uart::Config<Pads, NineBit>;
92//! ```
93//!
94//! Upon creation, the [`Config`] takes ownership of both the [`Pads`] struct
95//! and the PAC `SercomN` struct (eg [`Sercom0`]). It takes a reference to the
96//! PM, so that it can enable the APB clock, and it takes a frequency to
97//! indicate the GCLK configuration. Users are responsible for correctly
98//! configuring the GCLK.
99//!
100//! ```
101//! use atsamd_hal::time::U32Ext;
102//!
103//! let pm = peripherals.PM;
104//! let sercom = peripherals.Sercom0;
105//! // Configure GCLK for 10 MHz
106//! let freq = 10.mhz();
107//! let config = uart::Config::new(&pm, sercom, pads, freq);
108//! ```
109//!
110//! The [`Config`] struct can configure the peripheral in one of two ways:
111//!
112//! * A set of methods is provided to use in a builder pattern: for example
113//! [`baud`](Config::baud), [`stop_bits`](Config::stop_bits), etc. These
114//! methods take `self` and return `Self`.
115//! * A set of methods is provided to use as setters: for example
116//! [`set_baud`](Config::set_baud), [`set_stop_bits`](Config::set_stop_bits),
117//! etc. These methods take `&mut self` and return nothing.
118//!
119//! In any case, the peripheral setup ends with a call to [`enable`], which
120//! consumes the [`Config`] and returns an enabled [`Uart`] peripheral.
121//!
122//! ```
123//! use atsamd_hal::sercom::uart::{StopBits, NineBit, BitOrder, BaudMode, Oversampling};
124//!
125//! let uart = uart::Config::new(&mclk, sercom, pads, freq)
126//! .baud(1.mhz(), BaudMode::Arithmetic(Oversampling::Bits16))
127//! .char_size::<NineBit>()
128//! .bit_order(BitOrder::LsbFirst)
129//! .stop_bits(StopBits::TwoBits)
130//! .enable();
131//! ```
132//!
133//! Alternatively,
134//!
135//! ```
136//! use atsamd_hal::sercom::uart::{StopBits, NineBit, BitOrder, BaudMode, Oversampling};
137//!
138//! let uart = uart::Config::new(&mclk, sercom, pads, freq);
139//! uart.set_baud(1.mhz(), BaudMode::Arithmetic(Oversampling::Bits16));
140//! uart.set_char_size::<NineBit>();
141//! uart.set_bit_order(BitOrder::LsbFirst);
142//! uart.set_stop_bits(StopBits::TwoBits);
143//! let uart = uart.enable();
144//! ```
145//!
146//!
147//! To be accepted as a [`ValidConfig`], the [`Config`] must have at least one
148//! of `Rx` or `Tx` pads.
149//!
150//! ## [`CharSize`]
151//!
152//! The UART peripheral can be configured to use different character sizes. By
153//! default, a [`Config`] is configured with an [`EightBit`] character size.
154//! This can be changed through the [`char_size`](Config::char_size) method.
155//! Changing the character normally also changes the [`Config`]'s type.
156//! Alternatively, you can also use a [`DynCharSize`] through the
157//! [`dyn_char_size`](Config::dyn_char_size) method. This enables you to
158//! dynamically change the character size on the fly through the
159//! [`set_dyn_char_size`](Config::set_dyn_char_size) method when calling
160//! [`reconfigure`](Uart::reconfigure).
161//!
162//! ## Reading the current configuration
163//!
164//! It is possible to read the current configuration by using the getter methods
165//! provided: for example [`get_baud`](Config::get_baud),
166//! [`get_stop_bits`](Config::get_stop_bits), etc.
167//!
168//! # [`Uart`] and capabilities
169//!
170//! [`Uart`] structs can only be created from a [`Config`]. They have two type
171//! parameters: the first one represents the underlying [`Config`], while the
172//! second represents the [`Uart`]'s capabilities. The second type parameter can
173//! be one of:
174//!
175//! * [`Rx`] or [`RxDuplex`]: Can perform receive transactions
176//! * [`Tx`] or [`TxDuplex`]: Can perform transmit transactions
177//! * [`Duplex`]: UART configured as duplex that can perform receive and
178//! transmit transactions. Additionally, the [`split`] method can be called to
179//! return a `Uart<C, RxDuplex>, Uart<C, TxDuplex>)` tuple. See the
180//! [Splitting](self#Splitting) section for more information.
181//!
182//! The nature of the underlying [`Pads`] contained inside [`Config`] determines
183//! the type returned by a call to [`enable`]. If the pads only have a `TX` pin
184//! specified, then [`enable`] will return a `Uart<C, Tx>`. Similarly, If the
185//! pads only have a `RX` pin specified, then [`enable`] will return a `Uart<C,
186//! Rx>`. Finally, if both `RX` and `TX` pins are specified, then [`enable`]
187//! will return a `Uart<C, Duplex>`, which can be further split into a `Uart<C,
188//! RxDuplex>` and a `Uart<C, TxDuplex>`.
189//!
190//! ```
191//! use atsamd_hal::gpio::{PA08, PA09};
192//! use atsamd_hal::sercom::{Sercom0, uart};
193//! use atsamd_hal::sercom::uart::NineBit;
194//! use atsamd_hal::typelevel::NoneT;
195//!
196//! // Assuming SAMD21 or SAMx5x
197//! type Pads = uart::PadsFromIds<Sercom0, PA08, NoneT, PA09>;
198//! type Config = uart::Config<Pads, NineBit>;
199//! type UartRx = uart::Uart<Config, RxDuplex>;
200//! type UartTx = uart::UartTx<Config, RxDuples>;
201//! ```
202//!
203//! Only the [`Uart`] struct can actually perform transactions. To do so, use
204//! the embedded HAL traits, like [`embedded_hal_nb::serial::Read`],
205//! [`embedded_hal_nb::serial::Write`], [`embedded_io::Read`], and
206//! [`embedded_io::Write`].
207//!
208//! ```
209//! use nb::block;
210//! use atsamd_hal::embedded_hal_nb::serial::Write;
211//!
212//! block!(uart_tx.write(0x0fe));
213//! ```
214//!
215//! # UART flow control (CTS/RTS)
216//!
217//! This module supports CTS and RTS pins.
218//!
219//! The `RTS` pin is a fully hardware-controlled output pin that gets deasserted
220//! when:
221//!
222//! * The USART receiver is disabled;
223//! * The USART's RX buffer is full.
224//!
225//! The `CTS` pin is an input pin that provides an interrupt when a change
226//! (rising or falling edge) is detected on the corresponding Pad. This
227//! interrupt, `CTSIC`, can be enabled with the
228//! [`enable_ctsic`](Uart::enable_ctsic) method only when the corresponding
229//! [`Config`] has a `CTS` pad specified. The
230//! [`disable_ctsic`](Uart::disable_ctsic) and
231//! [`clear_ctsic`](Uart::clear_ctsic) methods are also available under the same
232//! conditions. [This application
233//! note](https://www.silabs.com/documents/public/application-notes/an0059.0-uart-flow-control.pdf)
234//! provides more information about UART hardware flow control.
235//!
236//! # Splitting
237//!
238//! A `Uart<C, Duplex>` can be split into its [`RxDuplex`] and [`TxDuplex`]
239//! constituents:
240//!
241//! ```
242//! use atsamd_hal::sercom::uart::Uart;
243//! // Assume uart is a Uart<C, Duplex>
244//! let (rx, tx) = uart.split();
245//! ```
246//!
247//! # Joining
248//!
249//! When a `Uart<C, Duplex>` has been split into its [`RxDuplex`] and
250//! [`TxDuplex`] parts, these parts can be joined back into a `Uart<C, Duplex>`
251//! by calling the [`join`] function for `Uart<C, Duplex>`. It takes a `Uart<C,
252//! RxDuplex>` and a `Uart<C, TxDuplex>` and moves them into a full [`Duplex`]
253//! [`Uart`].
254//!
255//! ```
256//! use atsamd_hal::sercom::uart::Uart;
257//!
258//! // Assume rx is a Uart<C, RxDuplex> and tx is a Uart<C, TxDuplex>
259//! let uart = Uart::join(rx, tx);
260//! // uart is now a Uart<C, Duplex>
261//! ```
262//!
263//! The [`AsMut<Uart<C, Duplex>>`] trait is also implemented for `(&mut Uart<C,
264//! RxDuplex>, &mut Uart<C, TxDuplex>)`. This is useful if you need an `&mut
265//! Uart<C, Duplex>` but you only have a pair of `&mut Uart<C, RxDuplex>` and
266//! `&mut Uart<C, TxDuplex>`. This can be leveraged to use the [`reconfigure`]
267//! method when all you have is a pair of mutable references to the [`RxDuplex`]
268//! and [`TxDuplex`] halves.
269//!
270//! ```
271//! use atsamd_hal::sercom::uart::Uart;
272//!
273//! // Assume rx is a Uart<C, RxDuplex> and tx is a Uart<C, TxDuplex>
274//!
275//! // Reconfigure peripheral from mutable references to RxDuplex
276//! // and TxDuplex halves
277//! (&mut rx, &mut tx).as_mut().reconfigure(|c| c.set_run_in_standby(false));
278//! ```
279//!
280//! # Reading the current configuration
281//!
282//! The `AsRef<Config<P, C>>` trait is implemented for `Uart<Config<P, C>, D>`.
283//! This means you can use the `get_` methods implemented for `Config`, since
284//! they take an `&self` argument.
285//!
286//! ```
287//! // Assume uart is a Uart<C, D>
288//! let (baud, baud_mode) = uart.as_ref().get_baud();
289//! ```
290//!
291//! # Disabling and reconfiguring
292//!
293//! Some methods, such as [`disable`] and [`reconfigure`], need to operate on
294//! all parts of a UART at once. In practice, this means that these methods
295//! operate on the type that was returned by [`enable`]. This can be `Uart<C,
296//! Rx>`, `Uart<C, Tx>`, or `Uart<C, Duplex>`, depending on how the peripheral
297//! was configured.
298//!
299//! The [`reconfigure`] method gives out an `&mut Config` reference, which can
300//! then use the `set_*` methods.
301//!
302//! ```
303//! use atsamd_hal::sercom::uart::Uart;
304//! use atsamd_hal::time::*;
305//!
306//! // Assume config is a valid Duplex UART Config struct
307//! let (rx, tx)= config.enable().split();
308//!
309//! // Send/receive data with tx/rx halves...
310//!
311//! // If the UART peripheral is configured in Duplex mode,
312//! // the two constituting halves need to be joined back into
313//! // a Uart<C, Duplex> before calling disable()
314//! let uart = Uart::join(rx, tx);
315//!
316//! // Reconfigure UART peripheral
317//! uart.reconfigure(|c| c.set_run_in_standby(false));
318//!
319//! // Disable UART peripheral
320//! let config = uart.disable();
321//! ```
322//!
323//! # Non-supported advanced features
324//!
325//! * Synchronous mode (USART) is not supported
326//! * LIN mode is not supported (SAMx5x)
327//! * 32-bit extension mode is not supported (SAMx5x). If you need to transfer
328//! slices, consider using the DMA methods instead. The <span class="stab
329//! portability" title="Available on crate feature `dma`
330//! only"><code>dma</code></span> Cargo feature must be enabled.
331//!
332//! # Using UART with DMA <span class="stab portability" title="Available on crate feature `dma` only"><code>dma</code></span>
333//!
334//! This HAL includes support for DMA-enabled UART transfers. Use
335//! [`Uart::with_rx_channel`] and [`Uart::with_tx_channel`] to attach DMA
336//! channels to the [`Uart`] struct. A DMA-enabled [`Uart`] implements the
337//! blocking [`embedded_io::Write`] and/or [`embedded_io::Read`] traits, which
338//! can be used to perform UART read/writes which are fast, continuous and low
339//! jitter, even if they are preemped by a higher priority interrupt.
340//!
341//!
342//! ```no_run
343//! use atsamd_hal::dmac::channel::{AnyChannel, Ready};
344//! use atsamd_hal::sercom::Uart::{I2c, ValidConfig, Error, TxDuplex};
345//! use atsamd_hal::embedded_io::Write;
346//! fn uart_send_with_dma<A: ValidConfig, C: AnyChannel<Status = Ready>>(uart: Uart<A, TxDuplex>, channel: C, bytes: &[u8]) -> Result<(), Error>{
347//! // Attach a DMA channel
348//! let uart = uart.with_tx_channel(channel);
349//! uart.write(bytes)?;
350//! }
351//! ```
352//!
353//! ## Non-blocking DMA transfers
354//!
355//! Non-blocking DMA transfers are also supported.
356//!
357//! The provided [`send_with_dma`] and [`receive_with_dma`] build and begin a
358//! [`Transfer`], thus starting the UART in a non-blocking way. Note that these
359//! methods require `'static` buffers in order to remain memory-safe.
360//!
361//! Optionally, interrupts can be enabled on the provided [`Channel`]. Please
362//! refer to the [`dmac`](crate::dmac) module-level documentation for more
363//! information.
364//!
365//! ```
366//! // Assume channel0 and channel1 are configured `dmac::Channel`s,
367//! // rx is a Uart<C, RxDuplex>, and tx is a Uart<C, TxDuplex>.
368//!
369//! /// Create data to send
370//! let tx_buffer: [u8; 50] = [0xff; 50];
371//! let rx_buffer: [u8; 100] = [0xab; 100];
372//!
373//! // Launch transmit transfer
374//! let tx_dma = tx.send_with_dma(&mut tx_buffer, channel0, |_| {});
375//!
376//! // Launch receive transfer
377//! let rx_dma = rx.receive_with_dma(&mut rx_buffer, channel1, |_| {});
378//!
379//! // Wait for transfers to complete and reclaim resources
380//! let (chan0, tx_buffer, tx) = tx_dma.wait();
381//! let (chan1, rx, rx_buffer) = rx_dma.wait();
382//! ```
383//!
384//! # `async` operation <span class="stab portability" title="Available on crate feature `async` only"><code>async</code></span>
385//!
386//! A [`Uart`] can be used for `async` operations. Configuring a [`Uart`] in
387//! async mode is relatively simple:
388//!
389//! * Bind the corresponding `SERCOM` interrupt source to the UART
390//! [`InterruptHandler`] (refer to the module-level [`async_hal`]
391//! documentation for more information).
392//! * Turn a previously configured [`Uart`] into a [`UartFuture`] by calling
393//! [`Uart::into_future`]
394//! * Optionally, add DMA channels to RX, TX or both using
395//! [`UartFuture::with_rx_dma_channel`] and
396//! [`UartFuture::with_tx_dma_channel`]. The API is exactly the same whether
397//! DMA channels are used or not.
398//! * Use the provided async methods for reading or writing to the UART
399//! peripheral.
400//!
401//! `UartFuture` implements `AsRef<Uart>` and `AsMut<Uart>` so that it can be
402//! reconfigured using the regular [`Uart`] methods. It also exposes a
403//! [`split`](UartFuture::split) method to split it into its RX and TX parts.
404//!
405//! ## Considerations when using `async` [`Uart`] with DMA <span class="stab portability" title="Available on crate feature `async` only"> <code>async</code></span> <span class="stab portability" title="Available on crate feature `dma` only"><code>dma</code></span>
406//!
407//! * An [`Uart`] struct must be turned into an [`UartFuture`] by calling
408//! [`Uart::into_future`] before calling `with_dma_channel`. The DMA channel
409//! itself must also be configured in async mode by using
410//! [`DmaController::into_future`](crate::dmac::DmaController::into_future).
411//! If a DMA channel is added to the [`Uart`] struct before it is turned into
412//! an [`UartFuture`], it will not be able to use DMA in async mode.
413//!
414//! ```
415//! // This will work
416//! let uart = uart.into_future().with_dma_channels(rx_channel, tx_channel);
417//!
418//! // This won't
419//! let uart = uart.with_dma_channels(rx_channel, tx_channel).into_future();
420//! ```
421//!
422//! ### Safety considerations
423//!
424//! In `async` mode, an SPI+DMA transfer does not require `'static` source and
425//! destination buffers. This, in theory, makes its use `unsafe`. However it is
426//! marked as safe for better ergonomics.
427//!
428//! This means that, as an user, you **must** ensure that the [`Future`]s
429//! returned by the [`read`](UartFuture::read) and [`write`](UartFuture::write)
430//! methods may never be forgotten through [`forget`] or by wrapping them with a
431//! [`ManuallyDrop`].
432//!
433//! The returned futures implement [`Drop`] and will automatically stop any
434//! ongoing transfers; this guarantees that the memory occupied by the
435//! now-dropped buffers may not be corrupted by running transfers.
436//!
437//! This means that using functions like [`futures::select_biased`] to implement
438//! timeouts is safe; transfers will be safely cancelled if the timeout expires.
439//!
440//! This also means that should you [`forget`] this [`Future`] after its first
441//! [`poll`] call, the transfer will keep running, ruining the now-reclaimed
442//! memory, as well as the rest of your day.
443//!
444//! * `await`ing is fine: the [`Future`] will run to completion.
445//! * Dropping an incomplete transfer is also fine. Dropping can happen, for
446//! example, if the transfer doesn't complete before a timeout expires.
447//! * Dropping an incomplete transfer *without running its destructor* is
448//! **unsound** and will trigger undefined behavior.
449//!
450//! ```ignore
451//! async fn always_ready() {}
452//!
453//! let mut buffer = [0x00; 10];
454//!
455//! // This is completely safe
456//! uart.read(&mut buffer).await?;
457//!
458//! // This is also safe: we launch a transfer, which is then immediately cancelled
459//! futures::select_biased! {
460//! _ = uart.read(&mut buffer)?,
461//! _ = always_ready(),
462//! }
463//!
464//! // This, while contrived, is also safe.
465//! {
466//! use core::future::Future;
467//!
468//! let future = uart.read(&mut buffer);
469//! futures::pin_mut!(future);
470//! // Assume ctx is a `core::task::Context` given out by the executor.
471//! // The future is polled, therefore starting the transfer
472//! future.as_mut().poll(ctx);
473//!
474//! // Future is dropped here - transfer is cancelled.
475//! }
476//!
477//! // DANGER: This is an example of undefined behavior
478//! {
479//! use core::future::Future;
480//! use core::ops::DerefMut;
481//!
482//! let future = core::mem::ManuallyDrop::new(uart.read(&mut buffer));
483//! futures::pin_mut!(future);
484//! // To actually make this example compile, we would need to wrap the returned
485//! // future from `i2c.read()` in a newtype that implements Future, because we
486//! // can't actually call as_mut() without being able to name the type we want
487//! // to deref to.
488//! let future_ref: &mut SomeNewTypeFuture = &mut future.as_mut();
489//! future.as_mut().poll(ctx);
490//!
491//! // Future is NOT dropped here - transfer is not cancelled, resulting un UB.
492//! }
493//! ```
494//!
495//! As you can see, unsoundness is relatively hard to come by - however, caution
496//! should still be exercised.
497//!
498//! [`enable`]: Config::enable
499//! [`disable`]: Uart::disable
500//! [`reconfigure`]: Uart::reconfigure
501//! [`bsp_pins`]: crate::bsp_pins
502//! [`Pin`]: crate::gpio::pin::Pin
503//! [`Pin`]: crate::gpio::pin::Pin
504//! [`PinId`]: crate::gpio::pin::PinId
505//! [`PinMode`]: crate::gpio::pin::PinMode
506//! [`split`]: Uart::split
507//! [`join`]: Uart::join
508//! [`NoneT`]: crate::typelevel::NoneT
509//! [`receive_with_dma`]: Uart::receive_with_dma
510//! [`send_with_dma`]: Uart::send_with_dma
511//! [`Transfer`]: crate::dmac::Transfer
512//! [`Channel`]: crate::dmac::Channel
513//! [`async_hal`]: crate::async_hal
514//! [`forget`]: core::mem::forget
515//! [`ManuallyDrop`]: core::mem::ManuallyDrop
516//! [`Future`]: core::future::Future
517//! [`poll`]: core::future::Future::poll
518//! [`Sercom`]: crate::sercom::Sercom
519//! [`Sercom0`]: crate::pac::Sercom0
520//! [`PadNum`]: crate::sercom::pad::PadNum
521//! [`Pad`]: crate::sercom::pad::Pad
522//! [`IsPad`]: crate::sercom::pad::IsPad
523//! [`OptionalPad`]: crate::sercom::pad::OptionalPad
524
525use atsamd_hal_macros::{hal_cfg, hal_module};
526
527#[hal_module(
528 any("sercom0-d11", "sercom0-d21") => "uart/pads_thumbv6m.rs",
529 "sercom0-d5x" => "uart/pads_thumbv7em.rs",
530)]
531mod pads {}
532
533pub use pads::*;
534
535mod reg;
536use reg::Registers;
537
538mod charsize;
539pub use charsize::*;
540
541mod flags;
542pub use flags::*;
543
544mod config;
545pub use config::*;
546
547pub mod impl_ehal;
548
549#[cfg(feature = "async")]
550mod async_api;
551#[cfg(feature = "async")]
552pub use async_api::*;
553
554use crate::{
555 sercom::pad::SomePad,
556 typelevel::{NoneT, Sealed},
557};
558use core::marker::PhantomData;
559use num_traits::AsPrimitive;
560
561/// Size of the SERCOM's `DATA` register
562#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
563pub type DataReg = u16;
564
565/// Size of the SERCOM's `DATA` register
566#[hal_cfg("sercom0-d5x")]
567pub type DataReg = u32;
568
569//=============================================================================
570// Stop bits, parity, baud rate, bit order
571//=============================================================================
572
573/// Number of stop bits in a UART frame
574#[derive(Debug, Clone, Copy)]
575pub enum StopBits {
576 /// 1 stop bit
577 OneBit,
578 /// 2 stop bits
579 TwoBits,
580}
581
582/// Parity setting of a UART frame
583#[repr(u8)]
584#[derive(Debug, Clone, Copy)]
585pub enum Parity {
586 /// No parity
587 None,
588 /// Even parity
589 Even,
590 /// Odd parity
591 Odd,
592}
593
594/// Bit order of a UART frame
595#[repr(u8)]
596#[derive(Debug, Clone, Copy)]
597pub enum BitOrder {
598 /// MSB-first
599 MsbFirst,
600 /// LSB-first
601 LsbFirst,
602}
603
604/// Baudrate oversampling values
605///
606/// *NOTE* 3x oversampling has been intentionally left out
607#[repr(u8)]
608#[derive(Debug, Clone, Copy)]
609pub enum Oversampling {
610 // 3 samples per bit
611 // Bits3 = 3,
612 /// 8 samples per bit
613 Bits8 = 8,
614 /// 16 samples per bit
615 Bits16 = 16,
616}
617
618/// Baudrate calculation in asynchronous mode
619#[derive(Debug, Clone, Copy)]
620pub enum BaudMode {
621 /// Asynchronous arithmetic baud calculation
622 Arithmetic(Oversampling),
623 /// Asynchronous fractional baud calculation
624 Fractional(Oversampling),
625}
626
627//=============================================================================
628// Capability
629//=============================================================================
630
631/// Type-level `enum` representing the capabilities of a UART peripheral
632pub trait Capability: Sealed {
633 /// Available interrupt flags for the specified capability
634 const FLAG_MASK: u8;
635 /// Available status flags for the specified capability
636 const STATUS_MASK: u16;
637 /// Enable `CTRLA.RXEN` field?
638 const RXEN: bool;
639 /// Enable `CTRLA.TXEN` field?
640 const TXEN: bool;
641}
642
643/// Type-level enum representing a UART that can transmit
644pub trait Transmit: Capability {}
645
646/// Type-level enum representing a UART that can receive
647pub trait Receive: Capability {}
648
649/// Type-level enum representing a UART that has transmit or receive
650/// capability, but not both
651pub trait Simplex: Capability {}
652
653/// Type-level enum representing a UART that is *not* half of a split
654/// [`Duplex`]
655pub trait SingleOwner: Capability {}
656
657/// Marker type representing a UART that has both transmit and receive
658/// capability
659pub enum Duplex {}
660impl Sealed for Duplex {}
661impl Capability for Duplex {
662 // All flags are valid for a Duplex UART
663 const FLAG_MASK: u8 = DUPLEX_FLAG_MASK;
664
665 // All status flags are valid for a Duplex UART
666 const STATUS_MASK: u16 = DUPLEX_STATUS_MASK;
667
668 const RXEN: bool = true;
669 const TXEN: bool = true;
670}
671impl Receive for Duplex {}
672impl Transmit for Duplex {}
673impl SingleOwner for Duplex {}
674
675/// Marker type representing a UART that can only receive
676pub enum Rx {}
677impl Sealed for Rx {}
678impl Capability for Rx {
679 // Available interrupt flags for a RX half-UART
680 const FLAG_MASK: u8 = RX_FLAG_MASK;
681
682 // Available status flags for a RX half-UART
683 const STATUS_MASK: u16 = RX_STATUS_MASK;
684
685 const RXEN: bool = true;
686 const TXEN: bool = false;
687}
688impl Receive for Rx {}
689impl Simplex for Rx {}
690impl SingleOwner for Rx {}
691
692/// Marker type representing a UART that can only transmit
693pub enum Tx {}
694impl Sealed for Tx {}
695impl Capability for Tx {
696 // Available interrupt flags for a TX half-UART
697 const FLAG_MASK: u8 = TX_FLAG_MASK;
698
699 // There are no settable/clearable status flags for TX half-UARTs
700 const STATUS_MASK: u16 = 0;
701
702 const RXEN: bool = false;
703 const TXEN: bool = true;
704}
705impl Transmit for Tx {}
706impl Simplex for Tx {}
707impl SingleOwner for Tx {}
708
709/// Marker type representing the Rx half of a [`Duplex`] UART
710pub enum RxDuplex {}
711impl Sealed for RxDuplex {}
712impl Capability for RxDuplex {
713 // Available interrupt flags for a RX half-UART
714 const FLAG_MASK: u8 = RX_FLAG_MASK;
715
716 // Available status flags for a RX half-UART
717 const STATUS_MASK: u16 = RX_STATUS_MASK;
718
719 const RXEN: bool = true;
720 const TXEN: bool = false;
721}
722impl Receive for RxDuplex {}
723
724/// Marker type representing a the Tx half of a [`Duplex`] UART
725pub enum TxDuplex {}
726impl Sealed for TxDuplex {}
727impl Capability for TxDuplex {
728 // Available interrupt flags for a TX half-UART
729 const FLAG_MASK: u8 = TX_FLAG_MASK;
730
731 // There are no settable/clearable status flags for TX half-UARTs
732 const STATUS_MASK: u16 = 0;
733
734 const RXEN: bool = false;
735 const TXEN: bool = true;
736}
737
738impl Transmit for TxDuplex {}
739
740//=============================================================================
741// Uart
742//=============================================================================
743
744/// Abstraction over a UART peripheral, allowing to perform UART transactions.
745/// The second type parameter, `D`, denotes what the struct's [`Capability`] is.
746///
747/// * [`Rx`] or [`RxDuplex`]: Can perform receive transactions
748/// * [`Tx`] or [`TxDuplex`]: Can perform transmit transactions
749/// * [`Duplex`]: Can perform receive and transmit transactions. Additionally,
750/// you can call [`split`](Uart::split) to return a `(Uart<C, RxDuplex>,
751/// Uart<C, TxDuplex>)` tuple.
752pub struct Uart<C, D, RxDma = NoneT, TxDma = NoneT>
753where
754 C: ValidConfig,
755 D: Capability,
756{
757 config: C,
758 capability: PhantomData<D>,
759 rx_channel: RxDma,
760 tx_channel: TxDma,
761}
762
763impl<C, D, R, T> Uart<C, D, R, T>
764where
765 C: ValidConfig,
766 D: Capability,
767{
768 /// Obtain a pointer to the `DATA` register. Necessary for DMA transfers.
769 #[cfg(feature = "dma")]
770 #[inline]
771 pub(crate) fn data_ptr(&self) -> *mut C::Word {
772 self.config.as_ref().registers.data_ptr()
773 }
774
775 /// Helper method to remove the interrupt flags not pertinent to `Self`'s
776 /// `Capability`
777 #[inline]
778 fn capability_flags(flags: Flags) -> Flags {
779 flags & Flags::from_bits_retain(D::FLAG_MASK)
780 }
781
782 /// Helper method to remove the status flags not pertinent to `Self`'s
783 /// `Capability`
784 #[inline]
785 fn capability_status(status: Status) -> Status {
786 status & Status::from_bits_retain(D::STATUS_MASK)
787 }
788
789 /// Read the interrupt flags
790 #[inline]
791 pub fn read_flags(&self) -> Flags {
792 self.config.as_ref().registers.read_flags()
793 }
794
795 /// Clear interrupt status flags
796 ///
797 /// Setting the `ERROR`, `RXBRK`, `CTSIC`, `RXS`, or `TXC` flag will clear
798 /// the interrupts. This function has no effect on the `DRE` or
799 /// `RXC` flags.
800 ///
801 /// Note that only the flags pertinent to `Self`'s [`Capability`]
802 /// will be cleared. The other flags will be **SILENTLY IGNORED**.
803 ///
804 /// * Available flags for [`Receive`] capability: `RXC`, `RXS`, `RXBRK` and
805 /// `ERROR`
806 /// * Available flags for [`Transmit`] capability: `DRE` and `TXC`.
807 /// **Note**: The `CTSIC` flag can only be cleared if a `CTS` Pad was
808 /// specified in the [`Config`] via the [`clear_ctsic`](Uart::clear_ctsic)
809 /// method.
810 /// * Since [`Duplex`] [`Uart`]s are [`Receive`] + [`Transmit`] they have
811 /// all flags available.
812 ///
813 /// **Warning:** The implementations of of
814 /// [`Write::flush`](embedded_hal_nb::serial::Write::flush) waits on and
815 /// clears the `TXC` flag. Manually clearing this flag could cause it to
816 /// hang indefinitely.
817 #[inline]
818 pub fn clear_flags(&mut self, flags: Flags) {
819 // Remove flags not pertinent to Self's Capability
820 let flags = Self::capability_flags(flags);
821 self.config.as_mut().registers.clear_flags(flags);
822 }
823
824 /// Enable interrupts for the specified flags.
825 ///
826 /// Note that only the flags pertinent to `Self`'s [`Capability`]
827 /// will be cleared. The other flags will be **SILENTLY IGNORED**.
828 ///
829 /// * Available flags for [`Receive`] capability: `RXC`, `RXS`, `RXBRK` and
830 /// `ERROR`
831 /// * Available flags for [`Transmit`] capability: `DRE` and `TXC`.
832 /// **Note**: The `CTSIC` interrupt can only be enabled if a `CTS` Pad was
833 /// specified in the [`Config`] via the
834 /// [`enable_ctsic`](Uart::enable_ctsic) method.
835 /// * Since [`Duplex`] [`Uart`]s are [`Receive`] + [`Transmit`] they have
836 /// all flags available.
837 #[inline]
838 pub fn enable_interrupts(&mut self, flags: Flags) {
839 // Remove flags not pertinent to Self's Capability
840 let flags = Self::capability_flags(flags);
841 self.config.as_mut().registers.enable_interrupts(flags);
842 }
843
844 /// Disable interrupts for the specified flags.
845 ///
846 /// Note that only the flags pertinent to `Self`'s [`Capability`]
847 /// will be cleared. The other flags will be **SILENTLY IGNORED**
848 ///
849 /// * Available flags for [`Receive`] capability: `RXC`, `RXS`, `RXBRK` and
850 /// `ERROR`
851 /// * Available flags for [`Transmit`] capability: `DRE` and `TXC`.
852 /// **Note**: The `CTSIC` interrupt can only be disabled if a `CTS` Pad
853 /// was specified in the [`Config`] via the
854 /// [`disable_ctsic`](Uart::disable_ctsic) method.
855 /// * Since [`Duplex`] [`Uart`]s are [`Receive`] + [`Transmit`] they have
856 /// all flags available.
857 #[inline]
858 pub fn disable_interrupts(&mut self, flags: Flags) {
859 // Remove flags not pertinent to Self's Capability
860 let flags = Self::capability_flags(flags);
861 self.config.as_mut().registers.disable_interrupts(flags);
862 }
863
864 /// Read the status flags
865 #[inline]
866 pub fn read_status(&self) -> Status {
867 self.config.as_ref().registers.read_status()
868 }
869
870 /// Clear the status flags
871 ///
872 /// Note that only the status flags pertinent to `Self`'s [`Capability`]
873 /// will be cleared. The other stattus flags will be **SILENTLY IGNORED**.
874 ///
875 /// * Available status flags for [`Receive`] capability: `PERR`, `FERR`,
876 /// `BUFOVF`, `ISF` and `COLL`
877 /// * [`Transmit`]-only [`Uart`]s have no clearable status flags.
878 /// * Since [`Duplex`] [`Uart`]s are [`Receive`] + [`Transmit`] they have
879 /// all status flags available.
880 #[inline]
881 pub fn clear_status(&mut self, status: Status) {
882 // Remove status flags not pertinent to Self's Capability
883 let flags = Self::capability_status(status);
884 self.config.as_mut().registers.clear_status(flags);
885 }
886
887 #[inline]
888 pub(super) fn _reconfigure<F>(&mut self, update: F)
889 where
890 F: FnOnce(&mut SpecificConfig<C>),
891 {
892 self.config.as_mut().registers.enable_peripheral(false);
893 update(self.config.as_mut());
894 self.config.as_mut().registers.enable_peripheral(true);
895 }
896}
897
898impl<C, D, R, T> Uart<C, D, R, T>
899where
900 C: ValidConfig,
901 <C::Pads as PadSet>::Cts: SomePad,
902 D: Transmit,
903{
904 /// Clear the `CTSIC` interrupt flag
905 #[inline]
906 pub fn clear_ctsic(&mut self) {
907 let bit = CTSIC;
908 self.config
909 .as_mut()
910 .registers
911 .clear_flags(Flags::from_bits_retain(bit));
912 }
913
914 /// Enable the `CTSIC` interrupt
915 #[inline]
916 pub fn enable_ctsic(&mut self) {
917 let bit = CTSIC;
918 self.config
919 .as_mut()
920 .registers
921 .enable_interrupts(Flags::from_bits_retain(bit));
922 }
923
924 /// Disable the `CTSIC` interrupt
925 #[inline]
926 pub fn disable_ctsic(&mut self) {
927 let bit = CTSIC;
928 self.config
929 .as_mut()
930 .registers
931 .disable_interrupts(Flags::from_bits_retain(bit));
932 }
933}
934
935impl<C, D, R, T> Uart<C, D, R, T>
936where
937 C: ValidConfig,
938 D: Simplex,
939{
940 /// Disable the UART peripheral and return the underlying [`Config`]
941 #[inline]
942 pub fn disable(self) -> C {
943 let mut config = self.config;
944 config.as_mut().registers.disable();
945 config
946 }
947
948 /// Reconfigure the UART.
949 ///
950 /// Calling this method will temporarily disable the SERCOM peripheral, as
951 /// some registers are enable-protected. This may interrupt any ongoing
952 /// transactions.
953 ///
954 /// ```
955 /// use atsamd_hal::sercom::uart::{BaudMode, Oversampling, Uart};
956 /// uart.reconfigure(|c| c.set_run_in_standby(false));
957 /// ```
958 #[inline]
959 pub fn reconfigure<U>(&mut self, update: U)
960 where
961 U: FnOnce(&mut SpecificConfig<C>),
962 {
963 self._reconfigure(update);
964 }
965}
966
967#[cfg(feature = "dma")]
968impl<C, D, T> Uart<C, D, NoneT, T>
969where
970 C: ValidConfig,
971 D: Capability,
972{
973 /// Attach a DMA channel to this [`Uart`] for RX transactions. Its
974 /// [`Read`](embedded_io::Read) implementation will use DMA to
975 /// carry out its transactions.
976 pub fn with_rx_channel<R: crate::dmac::AnyChannel<Status = crate::dmac::Ready>>(
977 self,
978 rx_channel: R,
979 ) -> Uart<C, D, R, T> {
980 Uart {
981 config: self.config,
982 capability: self.capability,
983 tx_channel: self.tx_channel,
984 rx_channel,
985 }
986 }
987}
988
989#[cfg(feature = "dma")]
990impl<C, D, R> Uart<C, D, R, NoneT>
991where
992 C: ValidConfig,
993 D: Capability,
994{
995 /// Attach a DMA channel to this [`Uart`] for TX transactions. Its
996 /// [`Write`](embedded_io::Write) implementation will use DMA to
997 /// carry out its transactions.
998 pub fn with_tx_channel<T: crate::dmac::AnyChannel<Status = crate::dmac::Ready>>(
999 self,
1000 tx_channel: T,
1001 ) -> Uart<C, D, R, T> {
1002 Uart {
1003 config: self.config,
1004 capability: self.capability,
1005 rx_channel: self.rx_channel,
1006 tx_channel,
1007 }
1008 }
1009}
1010
1011#[cfg(feature = "dma")]
1012impl<C, D, R, T, S> Uart<C, D, R, T>
1013where
1014 C: ValidConfig,
1015 D: Capability,
1016 R: crate::dmac::AnyChannel<Status = S>,
1017 S: crate::dmac::ReadyChannel,
1018{
1019 /// Reclaim the RX DMA channel. Subsequent RX operations will no longer use
1020 /// DMA.
1021 pub fn take_rx_channel(self) -> (Uart<C, D, NoneT, T>, R) {
1022 (
1023 Uart {
1024 config: self.config,
1025 capability: self.capability,
1026 tx_channel: self.tx_channel,
1027 rx_channel: NoneT,
1028 },
1029 self.rx_channel,
1030 )
1031 }
1032}
1033
1034#[cfg(feature = "dma")]
1035impl<C, D, R, T, S> Uart<C, D, R, T>
1036where
1037 C: ValidConfig,
1038 D: Capability,
1039 T: crate::dmac::AnyChannel<Status = S>,
1040 S: crate::dmac::ReadyChannel,
1041{
1042 /// Reclaim the TX DMA channel. Subsequent TX operations will no longer use
1043 /// DMA.
1044 pub fn take_tx_channel(self) -> (Uart<C, D, R, NoneT>, T) {
1045 (
1046 Uart {
1047 config: self.config,
1048 capability: self.capability,
1049 rx_channel: self.rx_channel,
1050 tx_channel: NoneT,
1051 },
1052 self.tx_channel,
1053 )
1054 }
1055}
1056
1057impl<C, R, T> Uart<C, Duplex, R, T>
1058where
1059 C: ValidConfig,
1060{
1061 /// Split the [`Uart`] into [`RxDuplex`] and [`TxDuplex`] halves
1062 #[allow(clippy::type_complexity)]
1063 #[inline]
1064 pub fn split(self) -> (Uart<C, RxDuplex, R, NoneT>, Uart<C, TxDuplex, NoneT, T>) {
1065 let config = unsafe { core::ptr::read(&self.config) };
1066 (
1067 Uart {
1068 config: self.config,
1069 capability: PhantomData,
1070 rx_channel: self.rx_channel,
1071 tx_channel: NoneT,
1072 },
1073 Uart {
1074 config,
1075 capability: PhantomData,
1076 rx_channel: NoneT,
1077 tx_channel: self.tx_channel,
1078 },
1079 )
1080 }
1081
1082 /// Disable the UART peripheral and return the underlying [`Config`]
1083 #[inline]
1084 pub fn disable(self) -> C {
1085 let mut config = self.config;
1086 config.as_mut().registers.disable();
1087 config
1088 }
1089
1090 /// Update the UART [`Config`]uration.
1091 ///
1092 /// Calling this method will temporarily disable the SERCOM peripheral, as
1093 /// some registers are enable-protected. This may interrupt any ongoing
1094 /// transactions.
1095 ///
1096 /// ```
1097 /// use atsamd_hal::sercom::uart::{BaudMode, Oversampling, Uart};
1098 /// uart.reconfigure(|c| c.set_run_in_standby(false));
1099 /// ```
1100 #[inline]
1101 pub fn reconfigure<F>(&mut self, update: F)
1102 where
1103 F: FnOnce(&mut SpecificConfig<C>),
1104 {
1105 self._reconfigure(update);
1106 }
1107
1108 /// Join [`RxDuplex`] and [`TxDuplex`] halves back into a full `Uart<C,
1109 /// Duplex>`
1110 pub fn join(rx: Uart<C, RxDuplex, R, NoneT>, tx: Uart<C, TxDuplex, NoneT, T>) -> Self {
1111 Self {
1112 config: rx.config,
1113 capability: PhantomData,
1114 rx_channel: rx.rx_channel,
1115 tx_channel: tx.tx_channel,
1116 }
1117 }
1118}
1119
1120impl<C: ValidConfig, R, T> AsMut<Uart<C, Duplex, R, T>>
1121 for (
1122 &mut Uart<C, RxDuplex, R, NoneT>,
1123 &mut Uart<C, TxDuplex, NoneT, T>,
1124 )
1125{
1126 #[inline]
1127 fn as_mut(&mut self) -> &mut Uart<C, Duplex, R, T> {
1128 // SAFETY: Pointer casting &mut Uart<C, RxDuplex> into &mut
1129 // Uart<C, Duplex> should be safe as long as RxDuplex, TxDuplex, R and T are all
1130 // zero-sized types
1131 unsafe { &mut *(self.0 as *mut _ as *mut Uart<C, Duplex, R, T>) }
1132 }
1133}
1134
1135impl<C, D> AsRef<SpecificConfig<C>> for Uart<C, D>
1136where
1137 C: ValidConfig,
1138 D: Capability,
1139{
1140 #[inline]
1141 fn as_ref(&self) -> &SpecificConfig<C> {
1142 self.config.as_ref()
1143 }
1144}
1145
1146//=============================================================================
1147// Rx/Tx specific functionality
1148//=============================================================================
1149
1150impl<C, D, R, T> Uart<C, D, R, T>
1151where
1152 C: ValidConfig,
1153 D: Receive,
1154 DataReg: AsPrimitive<C::Word>,
1155{
1156 /// Read from the DATA register
1157 ///
1158 /// # Safety
1159 ///
1160 /// Reading from the data register directly is `unsafe`, because it will
1161 /// clear the RXC flag, which could break assumptions made elsewhere in
1162 /// this module.
1163 #[inline]
1164 pub unsafe fn read_data(&mut self) -> DataReg {
1165 self.config.as_mut().registers.read_data()
1166 }
1167
1168 /// Read the status register and convert into a [`Result`]
1169 /// containing the corresponding [`Flags`] or [`Error`]
1170 #[inline]
1171 fn read_flags_errors(&self) -> Result<Flags, Error> {
1172 self.read_status().check_bus_error()?;
1173 Ok(self.read_flags())
1174 }
1175
1176 /// Flush the RX buffer and clear RX errors.
1177 ///
1178 /// **Note**: The datasheet states that disabling the receiver (RXEN) clears
1179 /// the RX buffer, and clears the BUFOVF, PERR and FERR bits.
1180 /// However, in practice, it seems like BUFOVF errors still pop
1181 /// up after a disable/enable cycle of the receiver, then immediately begin
1182 /// reading bytes from the DATA register. Instead, this method uses a
1183 /// workaround, which reads a few bytes to clear the RX buffer (3 bytes
1184 /// seems to be the trick), then manually clear the error bits.
1185 #[inline]
1186 pub fn flush_rx_buffer(&mut self) {
1187 // TODO Is this a hardware bug???
1188
1189 // usart.ctrlb.modify(|_, w| w.rxen().clear_bit());
1190 // while usart.syncbusy.read().ctrlb().bit() ||
1191 // usart.ctrlb.read().rxen().bit_is_set() {}
1192
1193 // usart.ctrlb.modify(|_, w| w.rxen().set_bit());
1194 // while usart.syncbusy.read().ctrlb().bit() ||
1195 // usart.ctrlb.read().rxen().bit_is_clear() {}
1196
1197 for _ in 0..=2 {
1198 let _data = unsafe { self.config.as_mut().registers.read_data() };
1199 }
1200
1201 // Clear all errors
1202 self.clear_status(
1203 Status::BUFOVF | Status::FERR | Status::PERR | Status::ISF | Status::COLL,
1204 );
1205 }
1206}
1207
1208impl<C, D, R, T> Uart<C, D, R, T>
1209where
1210 C: ValidConfig,
1211 D: Transmit,
1212{
1213 /// Write to the DATA register
1214 ///
1215 /// # Safety
1216 ///
1217 /// Writing to the data register directly is `unsafe`, because it will clear
1218 /// the DRE flag, which could break assumptions made elsewhere in this
1219 /// module.
1220 #[inline]
1221 pub unsafe fn write_data(&mut self, data: DataReg) {
1222 self.config.as_mut().registers.write_data(data);
1223 }
1224}