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. All [`Pin`]s must be mapped to
15//! the same `Sercom` (see the datasheet). SAMx5x chips also require that
16//! [`Pin`]s must be in the same [`IoSet`]. This HAL makes it impossible to use
17//! invalid [`Pin`]/[`Pad`] combinations, and the [`Pads`] struct is responsible
18//! for enforcing these constraints.
19//!
20//!
21//! A `Pads` type takes five type parameters, the first type specifies the
22//! `Sercom`, `DI`, `DO`, `CK` and `SS`, represent the Data In, Data Out, Sclk
23//! and SS pads respectively. Each of the pad type parameters is an
24//! [`OptionalPad`] and defaults to [`NoneT`]. A [`Pad`] is just a [`Pin`]
25//! configured in the correct [`PinMode`] that implements [`IsPad`]. The
26//! [`bsp_pins!`](crate::bsp_pins) macro can be used to define convenient type
27//! 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_rx_dma_channel` or
409//!   `with_tx_dma_channel` . The DMA channel itself must also be configured in
410//!   async mode by using
411//!   [`DmaController::into_future`](crate::dmac::DmaController::into_future).
412//!   If a DMA channel is added to the [`Uart`] struct before it is turned into
413//!   an [`UartFuture`], it will not be able to use DMA in async mode.
414//!
415//! ```
416//! // This will work
417//! let uart = uart.into_future().with_rx_dma_channel(rx_channel);
418//!
419//! // This won't
420//! let uart = uart.with_rx_dma_channel(rx_channel).into_future();
421//! ```
422//!
423//! ### Safety considerations
424//!
425//! In `async` mode, an SPI+DMA transfer does not require `'static` source and
426//! destination buffers. This, in theory, makes its use `unsafe`. However it is
427//! marked as safe for better ergonomics.
428//!
429//! This means that, as an user, you **must** ensure that the [`Future`]s
430//! returned by the [`read`](UartFuture::read) and [`write`](UartFuture::write)
431//! methods may never be forgotten through [`forget`] or by wrapping them with a
432//! [`ManuallyDrop`].
433//!
434//! The returned futures implement [`Drop`] and will automatically stop any
435//! ongoing transfers; this guarantees that the memory occupied by the
436//! now-dropped buffers may not be corrupted by running transfers.
437//!
438//! This means that using functions like [`futures::select_biased`] to implement
439//! timeouts is safe; transfers will be safely cancelled if the timeout expires.
440//!
441//! This also means that should you [`forget`] this [`Future`] after its first
442//! [`poll`] call, the transfer will keep running, ruining the now-reclaimed
443//! memory, as well as the rest of your day.
444//!
445//! * `await`ing is fine: the [`Future`] will run to completion.
446//! * Dropping an incomplete transfer is also fine. Dropping can happen, for
447//!   example, if the transfer doesn't complete before a timeout expires.
448//! * Dropping an incomplete transfer *without running its destructor* is
449//!   **unsound** and will trigger undefined behavior.
450//!
451//! ```ignore
452//! async fn always_ready() {}
453//!
454//! let mut buffer = [0x00; 10];
455//!
456//! // This is completely safe
457//! uart.read(&mut buffer).await?;
458//!
459//! // This is also safe: we launch a transfer, which is then immediately cancelled
460//! futures::select_biased! {
461//!     _ = uart.read(&mut buffer)?,
462//!     _ = always_ready(),
463//! }
464//!
465//! // This, while contrived, is also safe.
466//! {
467//!     use core::future::Future;
468//!
469//!     let future = uart.read(&mut buffer);
470//!     futures::pin_mut!(future);
471//!     // Assume ctx is a `core::task::Context` given out by the executor.
472//!     // The future is polled, therefore starting the transfer
473//!     future.as_mut().poll(ctx);
474//!
475//!     // Future is dropped here - transfer is cancelled.
476//! }
477//!
478//! // DANGER: This is an example of undefined behavior
479//! {
480//!     use core::future::Future;
481//!     use core::ops::DerefMut;
482//!
483//!     let future = core::mem::ManuallyDrop::new(uart.read(&mut buffer));
484//!     futures::pin_mut!(future);
485//!     // To actually make this example compile, we would need to wrap the returned
486//!     // future from `i2c.read()` in a newtype that implements Future, because we
487//!     // can't actually call as_mut() without being able to name the type we want
488//!     // to deref to.
489//!     let future_ref: &mut SomeNewTypeFuture = &mut future.as_mut();
490//!     future.as_mut().poll(ctx);
491//!
492//!     // Future is NOT dropped here - transfer is not cancelled, resulting un UB.
493//! }
494//! ```
495//!
496//! As you can see, unsoundness is relatively hard to come by - however, caution
497//! should still be exercised.
498//!
499//! [`enable`]: Config::enable
500//! [`disable`]: Uart::disable
501//! [`reconfigure`]: Uart::reconfigure
502//! [`bsp_pins`]: crate::bsp_pins
503//! [`IoSet`]: crate::sercom::pad::IoSet
504//! [`Pin`]: crate::gpio::pin::Pin
505//! [`PinId`]: crate::gpio::pin::PinId
506//! [`PinMode`]: crate::gpio::pin::PinMode
507//! [`split`]: Uart::split
508//! [`join`]: Uart::join
509//! [`NoneT`]: crate::typelevel::NoneT
510//! [`receive_with_dma`]: Uart::receive_with_dma
511//! [`send_with_dma`]: Uart::send_with_dma
512//! [`Transfer`]: crate::dmac::Transfer
513//! [`Channel`]: crate::dmac::Channel
514//! [`async_hal`]: crate::async_hal
515//! [`forget`]: core::mem::forget
516//! [`ManuallyDrop`]: core::mem::ManuallyDrop
517//! [`Future`]: core::future::Future
518//! [`poll`]: core::future::Future::poll
519//! [`Sercom`]: crate::sercom::Sercom
520//! [`Sercom0`]: crate::pac::Sercom0
521//! [`PadNum`]: crate::sercom::pad::PadNum
522//! [`Pad`]: crate::sercom::pad::Pad
523//! [`IsPad`]: crate::sercom::pad::IsPad
524//! [`OptionalPad`]: crate::sercom::pad::OptionalPad
525
526use atsamd_hal_macros::{hal_cfg, hal_module};
527
528#[hal_module(
529    any("sercom0-d11", "sercom0-d21") => "uart/pads_thumbv6m.rs",
530    "sercom0-d5x" => "uart/pads_thumbv7em.rs",
531)]
532mod pads {}
533
534pub use pads::*;
535
536mod reg;
537use reg::Registers;
538
539mod charsize;
540pub use charsize::*;
541
542mod flags;
543pub use flags::*;
544
545mod config;
546pub use config::*;
547
548pub mod impl_ehal;
549
550#[cfg(feature = "async")]
551mod async_api;
552#[cfg(feature = "async")]
553pub use async_api::*;
554
555use crate::{
556    sercom::pad::SomePad,
557    typelevel::{NoneT, Sealed},
558};
559use core::marker::PhantomData;
560use num_traits::AsPrimitive;
561
562/// Size of the SERCOM's `DATA` register
563#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
564pub type DataReg = u16;
565
566/// Size of the SERCOM's `DATA` register
567#[hal_cfg("sercom0-d5x")]
568pub type DataReg = u32;
569
570//=============================================================================
571// Stop bits, parity, baud rate, bit order
572//=============================================================================
573
574/// Number of stop bits in a UART frame
575#[derive(Debug, Clone, Copy)]
576pub enum StopBits {
577    /// 1 stop bit
578    OneBit,
579    /// 2 stop bits
580    TwoBits,
581}
582
583/// Parity setting of a UART frame
584#[repr(u8)]
585#[derive(Debug, Clone, Copy)]
586pub enum Parity {
587    /// No parity
588    None,
589    /// Even parity
590    Even,
591    /// Odd parity
592    Odd,
593}
594
595/// Bit order of a UART frame
596#[repr(u8)]
597#[derive(Debug, Clone, Copy)]
598pub enum BitOrder {
599    /// MSB-first
600    MsbFirst,
601    /// LSB-first
602    LsbFirst,
603}
604
605/// Baudrate oversampling values
606///
607/// *NOTE* 3x oversampling has been intentionally left out
608#[repr(u8)]
609#[derive(Debug, Clone, Copy)]
610pub enum Oversampling {
611    // 3 samples per bit
612    // Bits3 = 3,
613    /// 8 samples per bit
614    Bits8 = 8,
615    /// 16 samples per bit
616    Bits16 = 16,
617}
618
619/// Baudrate calculation in asynchronous mode
620#[derive(Debug, Clone, Copy)]
621pub enum BaudMode {
622    /// Asynchronous arithmetic baud calculation
623    Arithmetic(Oversampling),
624    /// Asynchronous fractional baud calculation
625    Fractional(Oversampling),
626}
627
628//=============================================================================
629// Capability
630//=============================================================================
631
632/// Type-level `enum` representing the capabilities of a UART peripheral
633pub trait Capability: Sealed {
634    /// Available interrupt flags for the specified capability
635    const FLAG_MASK: u8;
636    /// Available status flags for the specified capability
637    const STATUS_MASK: u16;
638    /// Enable `CTRLA.RXEN` field?
639    const RXEN: bool;
640    /// Enable `CTRLA.TXEN` field?
641    const TXEN: bool;
642}
643
644/// Type-level enum representing a UART that can transmit
645pub trait Transmit: Capability {}
646
647/// Type-level enum representing a UART that can receive
648pub trait Receive: Capability {}
649
650/// Type-level enum representing a UART that has transmit or receive
651/// capability, but not both
652pub trait Simplex: Capability {}
653
654/// Type-level enum representing a UART that is *not* half of a split
655/// [`Duplex`]
656pub trait SingleOwner: Capability {}
657
658/// Marker type representing a UART that has both transmit and receive
659/// capability
660pub enum Duplex {}
661impl Sealed for Duplex {}
662impl Capability for Duplex {
663    // All flags are valid for a Duplex UART
664    const FLAG_MASK: u8 = DUPLEX_FLAG_MASK;
665
666    // All status flags are valid for a Duplex UART
667    const STATUS_MASK: u16 = DUPLEX_STATUS_MASK;
668
669    const RXEN: bool = true;
670    const TXEN: bool = true;
671}
672impl Receive for Duplex {}
673impl Transmit for Duplex {}
674impl SingleOwner for Duplex {}
675
676/// Marker type representing a UART that can only receive
677pub enum Rx {}
678impl Sealed for Rx {}
679impl Capability for Rx {
680    // Available interrupt flags for a RX half-UART
681    const FLAG_MASK: u8 = RX_FLAG_MASK;
682
683    // Available status flags for a RX half-UART
684    const STATUS_MASK: u16 = RX_STATUS_MASK;
685
686    const RXEN: bool = true;
687    const TXEN: bool = false;
688}
689impl Receive for Rx {}
690impl Simplex for Rx {}
691impl SingleOwner for Rx {}
692
693/// Marker type representing a UART that can only transmit
694pub enum Tx {}
695impl Sealed for Tx {}
696impl Capability for Tx {
697    // Available interrupt flags for a TX half-UART
698    const FLAG_MASK: u8 = TX_FLAG_MASK;
699
700    // There are no settable/clearable status flags for TX half-UARTs
701    const STATUS_MASK: u16 = 0;
702
703    const RXEN: bool = false;
704    const TXEN: bool = true;
705}
706impl Transmit for Tx {}
707impl Simplex for Tx {}
708impl SingleOwner for Tx {}
709
710/// Marker type representing the Rx half of a  [`Duplex`] UART
711pub enum RxDuplex {}
712impl Sealed for RxDuplex {}
713impl Capability for RxDuplex {
714    // Available interrupt flags for a RX half-UART
715    const FLAG_MASK: u8 = RX_FLAG_MASK;
716
717    // Available status flags for a RX half-UART
718    const STATUS_MASK: u16 = RX_STATUS_MASK;
719
720    const RXEN: bool = true;
721    const TXEN: bool = false;
722}
723impl Receive for RxDuplex {}
724
725/// Marker type representing a the Tx half of a [`Duplex`] UART
726pub enum TxDuplex {}
727impl Sealed for TxDuplex {}
728impl Capability for TxDuplex {
729    // Available interrupt flags for a TX half-UART
730    const FLAG_MASK: u8 = TX_FLAG_MASK;
731
732    // There are no settable/clearable status flags for TX half-UARTs
733    const STATUS_MASK: u16 = 0;
734
735    const RXEN: bool = false;
736    const TXEN: bool = true;
737}
738
739impl Transmit for TxDuplex {}
740
741//=============================================================================
742// Uart
743//=============================================================================
744
745/// Abstraction over a UART peripheral, allowing to perform UART transactions.
746/// The second type parameter, `D`, denotes what the struct's [`Capability`] is.
747///
748/// * [`Rx`] or [`RxDuplex`]: Can perform receive transactions
749/// * [`Tx`] or [`TxDuplex`]: Can perform transmit transactions
750/// * [`Duplex`]: Can perform receive and transmit transactions. Additionally,
751///   you can call [`split`](Uart::split) to return a `(Uart<C, RxDuplex>,
752///   Uart<C, TxDuplex>)` tuple.
753pub struct Uart<C, D, RxDma = NoneT, TxDma = NoneT>
754where
755    C: ValidConfig,
756    D: Capability,
757{
758    config: C,
759    capability: PhantomData<D>,
760    rx_channel: RxDma,
761    tx_channel: TxDma,
762}
763
764impl<C, D, R, T> Uart<C, D, R, T>
765where
766    C: ValidConfig,
767    D: Capability,
768{
769    /// Obtain a pointer to the `DATA` register. Necessary for DMA transfers.
770    #[cfg(feature = "dma")]
771    #[inline]
772    pub(crate) fn data_ptr(&self) -> *mut C::Word {
773        self.config.as_ref().registers.data_ptr()
774    }
775
776    /// Helper method to remove the interrupt flags not pertinent to `Self`'s
777    /// `Capability`
778    #[inline]
779    fn capability_flags(flags: Flags) -> Flags {
780        flags & Flags::from_bits_retain(D::FLAG_MASK)
781    }
782
783    /// Helper method to remove the status flags not pertinent to `Self`'s
784    /// `Capability`
785    #[inline]
786    fn capability_status(status: Status) -> Status {
787        status & Status::from_bits_retain(D::STATUS_MASK)
788    }
789
790    /// Read the interrupt flags
791    #[inline]
792    pub fn read_flags(&self) -> Flags {
793        self.config.as_ref().registers.read_flags()
794    }
795
796    /// Clear interrupt status flags
797    ///
798    /// Setting the `ERROR`, `RXBRK`, `CTSIC`, `RXS`, or `TXC` flag will clear
799    /// the interrupts. This function has no effect on the `DRE` or
800    /// `RXC` flags.
801    ///
802    /// Note that only the flags pertinent to `Self`'s [`Capability`]
803    /// will be cleared. The other flags will be **SILENTLY IGNORED**.
804    ///
805    /// * Available flags for [`Receive`] capability: `RXC`, `RXS`, `RXBRK` and
806    ///   `ERROR`
807    /// * Available flags for [`Transmit`] capability: `DRE` and `TXC`.
808    ///   **Note**: The `CTSIC` flag can only be cleared if a `CTS` Pad was
809    ///   specified in the [`Config`] via the [`clear_ctsic`](Uart::clear_ctsic)
810    ///   method.
811    /// * Since [`Duplex`] [`Uart`]s are [`Receive`] + [`Transmit`] they have
812    ///   all flags available.
813    ///
814    /// **Warning:** The implementations of of
815    /// [`Write::flush`](embedded_hal_nb::serial::Write::flush) waits on and
816    /// clears the `TXC` flag. Manually clearing this flag could cause it to
817    /// hang indefinitely.
818    #[inline]
819    pub fn clear_flags(&mut self, flags: Flags) {
820        // Remove flags not pertinent to Self's Capability
821        let flags = Self::capability_flags(flags);
822        self.config.as_mut().registers.clear_flags(flags);
823    }
824
825    /// Enable interrupts for the specified flags.
826    ///
827    /// Note that only the flags pertinent to `Self`'s [`Capability`]
828    /// will be cleared. The other flags will be **SILENTLY IGNORED**.
829    ///
830    /// * Available flags for [`Receive`] capability: `RXC`, `RXS`, `RXBRK` and
831    ///   `ERROR`
832    /// * Available flags for [`Transmit`] capability: `DRE` and `TXC`.
833    ///   **Note**: The `CTSIC` interrupt can only be enabled if a `CTS` Pad was
834    ///   specified in the [`Config`] via the
835    ///   [`enable_ctsic`](Uart::enable_ctsic) method.
836    /// * Since [`Duplex`] [`Uart`]s are [`Receive`] + [`Transmit`] they have
837    ///   all flags available.
838    #[inline]
839    pub fn enable_interrupts(&mut self, flags: Flags) {
840        // Remove flags not pertinent to Self's Capability
841        let flags = Self::capability_flags(flags);
842        self.config.as_mut().registers.enable_interrupts(flags);
843    }
844
845    /// Disable interrupts for the specified flags.
846    ///
847    /// Note that only the flags pertinent to `Self`'s [`Capability`]
848    /// will be cleared. The other flags will be **SILENTLY IGNORED**
849    ///
850    /// * Available flags for [`Receive`] capability: `RXC`, `RXS`, `RXBRK` and
851    ///   `ERROR`
852    /// * Available flags for [`Transmit`] capability: `DRE` and `TXC`.
853    ///   **Note**: The `CTSIC` interrupt can only be disabled if a `CTS` Pad
854    ///   was specified in the [`Config`] via the
855    ///   [`disable_ctsic`](Uart::disable_ctsic) method.
856    /// * Since [`Duplex`] [`Uart`]s are [`Receive`] + [`Transmit`] they have
857    ///   all flags available.
858    #[inline]
859    pub fn disable_interrupts(&mut self, flags: Flags) {
860        // Remove flags not pertinent to Self's Capability
861        let flags = Self::capability_flags(flags);
862        self.config.as_mut().registers.disable_interrupts(flags);
863    }
864
865    /// Read the status flags
866    #[inline]
867    pub fn read_status(&self) -> Status {
868        self.config.as_ref().registers.read_status()
869    }
870
871    /// Clear the status flags
872    ///
873    /// Note that only the status flags pertinent to `Self`'s [`Capability`]
874    /// will be cleared. The other stattus flags will be **SILENTLY IGNORED**.
875    ///
876    /// * Available status flags for [`Receive`] capability: `PERR`, `FERR`,
877    ///   `BUFOVF`, `ISF` and `COLL`
878    /// * [`Transmit`]-only [`Uart`]s have no clearable status flags.
879    /// * Since [`Duplex`] [`Uart`]s are [`Receive`] + [`Transmit`] they have
880    ///   all status flags available.
881    #[inline]
882    pub fn clear_status(&mut self, status: Status) {
883        // Remove status flags not pertinent to Self's Capability
884        let flags = Self::capability_status(status);
885        self.config.as_mut().registers.clear_status(flags);
886    }
887
888    #[inline]
889    pub(super) fn _reconfigure<F>(&mut self, update: F)
890    where
891        F: FnOnce(&mut SpecificConfig<C>),
892    {
893        self.config.as_mut().registers.enable_peripheral(false);
894        update(self.config.as_mut());
895        self.config.as_mut().registers.enable_peripheral(true);
896    }
897}
898
899impl<C, D, R, T> Uart<C, D, R, T>
900where
901    C: ValidConfig,
902    <C::Pads as PadSet>::Cts: SomePad,
903    D: Transmit,
904{
905    /// Clear the `CTSIC` interrupt flag
906    #[inline]
907    pub fn clear_ctsic(&mut self) {
908        let bit = CTSIC;
909        self.config
910            .as_mut()
911            .registers
912            .clear_flags(Flags::from_bits_retain(bit));
913    }
914
915    /// Enable the `CTSIC` interrupt
916    #[inline]
917    pub fn enable_ctsic(&mut self) {
918        let bit = CTSIC;
919        self.config
920            .as_mut()
921            .registers
922            .enable_interrupts(Flags::from_bits_retain(bit));
923    }
924
925    /// Disable the `CTSIC` interrupt
926    #[inline]
927    pub fn disable_ctsic(&mut self) {
928        let bit = CTSIC;
929        self.config
930            .as_mut()
931            .registers
932            .disable_interrupts(Flags::from_bits_retain(bit));
933    }
934}
935
936impl<C, D, R, T> Uart<C, D, R, T>
937where
938    C: ValidConfig,
939    D: Simplex,
940{
941    /// Disable the UART peripheral and return the underlying [`Config`]
942    #[inline]
943    pub fn disable(self) -> C {
944        let mut config = self.config;
945        config.as_mut().registers.disable();
946        config
947    }
948
949    /// Reconfigure the UART.
950    ///
951    /// Calling this method will temporarily disable the SERCOM peripheral, as
952    /// some registers are enable-protected. This may interrupt any ongoing
953    /// transactions.
954    ///
955    /// ```
956    /// use atsamd_hal::sercom::uart::{BaudMode, Oversampling, Uart};
957    /// uart.reconfigure(|c| c.set_run_in_standby(false));
958    /// ```
959    #[inline]
960    pub fn reconfigure<U>(&mut self, update: U)
961    where
962        U: FnOnce(&mut SpecificConfig<C>),
963    {
964        self._reconfigure(update);
965    }
966}
967
968#[cfg(feature = "dma")]
969impl<C, D, T> Uart<C, D, NoneT, T>
970where
971    C: ValidConfig,
972    D: Capability,
973{
974    /// Attach a DMA channel to this [`Uart`] for RX transactions. Its
975    /// [`Read`](embedded_io::Read) implementation will use DMA to
976    /// carry out its transactions.
977    pub fn with_rx_channel<R: crate::dmac::AnyChannel<Status = crate::dmac::Ready>>(
978        self,
979        rx_channel: R,
980    ) -> Uart<C, D, R, T> {
981        Uart {
982            config: self.config,
983            capability: self.capability,
984            tx_channel: self.tx_channel,
985            rx_channel,
986        }
987    }
988}
989
990#[cfg(feature = "dma")]
991impl<C, D, R> Uart<C, D, R, NoneT>
992where
993    C: ValidConfig,
994    D: Capability,
995{
996    /// Attach a DMA channel to this [`Uart`] for TX transactions. Its
997    /// [`Write`](embedded_io::Write) implementation will use DMA to
998    /// carry out its transactions.
999    pub fn with_tx_channel<T: crate::dmac::AnyChannel<Status = crate::dmac::Ready>>(
1000        self,
1001        tx_channel: T,
1002    ) -> Uart<C, D, R, T> {
1003        Uart {
1004            config: self.config,
1005            capability: self.capability,
1006            rx_channel: self.rx_channel,
1007            tx_channel,
1008        }
1009    }
1010}
1011
1012#[cfg(feature = "dma")]
1013impl<C, D, R, T, S> Uart<C, D, R, T>
1014where
1015    C: ValidConfig,
1016    D: Capability,
1017    R: crate::dmac::AnyChannel<Status = S>,
1018    S: crate::dmac::ReadyChannel,
1019{
1020    /// Reclaim the RX DMA channel. Subsequent RX operations will no longer use
1021    /// DMA.
1022    pub fn take_rx_channel(self) -> (Uart<C, D, NoneT, T>, R) {
1023        (
1024            Uart {
1025                config: self.config,
1026                capability: self.capability,
1027                tx_channel: self.tx_channel,
1028                rx_channel: NoneT,
1029            },
1030            self.rx_channel,
1031        )
1032    }
1033}
1034
1035#[cfg(feature = "dma")]
1036impl<C, D, R, T, S> Uart<C, D, R, T>
1037where
1038    C: ValidConfig,
1039    D: Capability,
1040    T: crate::dmac::AnyChannel<Status = S>,
1041    S: crate::dmac::ReadyChannel,
1042{
1043    /// Reclaim the TX DMA channel. Subsequent TX operations will no longer use
1044    /// DMA.
1045    pub fn take_tx_channel(self) -> (Uart<C, D, R, NoneT>, T) {
1046        (
1047            Uart {
1048                config: self.config,
1049                capability: self.capability,
1050                rx_channel: self.rx_channel,
1051                tx_channel: NoneT,
1052            },
1053            self.tx_channel,
1054        )
1055    }
1056}
1057
1058impl<C, R, T> Uart<C, Duplex, R, T>
1059where
1060    C: ValidConfig,
1061{
1062    /// Split the [`Uart`] into [`RxDuplex`] and [`TxDuplex`] halves
1063    #[allow(clippy::type_complexity)]
1064    #[inline]
1065    pub fn split(self) -> (Uart<C, RxDuplex, R, NoneT>, Uart<C, TxDuplex, NoneT, T>) {
1066        let config = unsafe { core::ptr::read(&self.config) };
1067        (
1068            Uart {
1069                config: self.config,
1070                capability: PhantomData,
1071                rx_channel: self.rx_channel,
1072                tx_channel: NoneT,
1073            },
1074            Uart {
1075                config,
1076                capability: PhantomData,
1077                rx_channel: NoneT,
1078                tx_channel: self.tx_channel,
1079            },
1080        )
1081    }
1082
1083    /// Disable the UART peripheral and return the underlying [`Config`]
1084    #[inline]
1085    pub fn disable(self) -> C {
1086        let mut config = self.config;
1087        config.as_mut().registers.disable();
1088        config
1089    }
1090
1091    /// Update the UART [`Config`]uration.
1092    ///
1093    /// Calling this method will temporarily disable the SERCOM peripheral, as
1094    /// some registers are enable-protected. This may interrupt any ongoing
1095    /// transactions.
1096    ///
1097    /// ```
1098    /// use atsamd_hal::sercom::uart::{BaudMode, Oversampling, Uart};
1099    /// uart.reconfigure(|c| c.set_run_in_standby(false));
1100    /// ```
1101    #[inline]
1102    pub fn reconfigure<F>(&mut self, update: F)
1103    where
1104        F: FnOnce(&mut SpecificConfig<C>),
1105    {
1106        self._reconfigure(update);
1107    }
1108
1109    /// Join [`RxDuplex`] and [`TxDuplex`] halves back into a full `Uart<C,
1110    /// Duplex>`
1111    pub fn join(rx: Uart<C, RxDuplex, R, NoneT>, tx: Uart<C, TxDuplex, NoneT, T>) -> Self {
1112        Self {
1113            config: rx.config,
1114            capability: PhantomData,
1115            rx_channel: rx.rx_channel,
1116            tx_channel: tx.tx_channel,
1117        }
1118    }
1119}
1120
1121impl<C: ValidConfig, R, T> AsMut<Uart<C, Duplex, R, T>>
1122    for (
1123        &mut Uart<C, RxDuplex, R, NoneT>,
1124        &mut Uart<C, TxDuplex, NoneT, T>,
1125    )
1126{
1127    #[inline]
1128    fn as_mut(&mut self) -> &mut Uart<C, Duplex, R, T> {
1129        // SAFETY: Pointer casting &mut Uart<C, RxDuplex> into &mut
1130        // Uart<C, Duplex> should be safe as long as RxDuplex, TxDuplex, R and T are all
1131        // zero-sized types
1132        unsafe { &mut *(self.0 as *mut _ as *mut Uart<C, Duplex, R, T>) }
1133    }
1134}
1135
1136impl<C, D> AsRef<SpecificConfig<C>> for Uart<C, D>
1137where
1138    C: ValidConfig,
1139    D: Capability,
1140{
1141    #[inline]
1142    fn as_ref(&self) -> &SpecificConfig<C> {
1143        self.config.as_ref()
1144    }
1145}
1146
1147//=============================================================================
1148// Rx/Tx specific functionality
1149//=============================================================================
1150
1151impl<C, D, R, T> Uart<C, D, R, T>
1152where
1153    C: ValidConfig,
1154    D: Receive,
1155    DataReg: AsPrimitive<C::Word>,
1156{
1157    /// Read from the DATA register
1158    ///
1159    /// # Safety
1160    ///
1161    /// Reading from the data register directly is `unsafe`, because it will
1162    /// clear the RXC flag, which could break assumptions made elsewhere in
1163    /// this module.
1164    #[inline]
1165    pub unsafe fn read_data(&mut self) -> DataReg {
1166        self.config.as_mut().registers.read_data()
1167    }
1168
1169    /// Read the status register and convert into a [`Result`]
1170    /// containing the corresponding [`Flags`] or [`Error`]
1171    #[inline]
1172    fn read_flags_errors(&self) -> Result<Flags, Error> {
1173        self.read_status().check_bus_error()?;
1174        Ok(self.read_flags())
1175    }
1176
1177    /// Flush the RX buffer and clear RX errors.
1178    ///
1179    /// **Note**: The datasheet states that disabling the receiver (RXEN) clears
1180    /// the RX buffer, and clears the BUFOVF, PERR and FERR bits.
1181    /// However, in practice, it seems like BUFOVF errors still pop
1182    /// up after a disable/enable cycle of the receiver, then immediately begin
1183    /// reading bytes from the DATA register. Instead, this method uses a
1184    /// workaround, which reads a few bytes to clear the RX buffer (3 bytes
1185    /// seems to be the trick), then manually clear the error bits.
1186    #[inline]
1187    pub fn flush_rx_buffer(&mut self) {
1188        // TODO Is this a hardware bug???
1189
1190        // usart.ctrlb.modify(|_, w| w.rxen().clear_bit());
1191        // while usart.syncbusy.read().ctrlb().bit() ||
1192        // usart.ctrlb.read().rxen().bit_is_set() {}
1193
1194        // usart.ctrlb.modify(|_, w| w.rxen().set_bit());
1195        // while usart.syncbusy.read().ctrlb().bit() ||
1196        // usart.ctrlb.read().rxen().bit_is_clear() {}
1197
1198        for _ in 0..=2 {
1199            let _data = unsafe { self.config.as_mut().registers.read_data() };
1200        }
1201
1202        // Clear all errors
1203        self.clear_status(
1204            Status::BUFOVF | Status::FERR | Status::PERR | Status::ISF | Status::COLL,
1205        );
1206    }
1207}
1208
1209impl<C, D, R, T> Uart<C, D, R, T>
1210where
1211    C: ValidConfig,
1212    D: Transmit,
1213{
1214    /// Write to the DATA register
1215    ///
1216    /// # Safety
1217    ///
1218    /// Writing to the data register directly is `unsafe`, because it will clear
1219    /// the DRE flag, which could break assumptions made elsewhere in this
1220    /// module.
1221    #[inline]
1222    pub unsafe fn write_data(&mut self, data: DataReg) {
1223        self.config.as_mut().registers.write_data(data);
1224    }
1225}