stm32_hal2/
usart.rs

1//! This module allows for serial communication using the STM32 U(S)ART peripheral
2//! It provides APIs to configure, read, and write from
3//! U(S)ART, with blocking, nonblocking, and DMA functionality.
4
5// todo: Synchronous mode.
6// todo: Auto baud
7
8// todo: Missing some features (like additional interrupts) on the USARTv3 peripheral . (L5, G etc)
9
10use core::ops::Deref;
11
12use cfg_if::cfg_if;
13
14#[cfg(not(any(feature = "f4", feature = "l552", feature = "h5")))]
15use crate::dma::{self, ChannelCfg, DmaChannel};
16#[cfg(any(feature = "c0", feature = "h5"))]
17use crate::pac::DMA as DMA1;
18#[cfg(not(any(feature = "h5", feature = "c0")))]
19use crate::pac::DMA1;
20// use crate::util::{cr1, isr};
21use crate::{
22    clocks::Clocks,
23    error::{Error, Result},
24    pac::{self, RCC},
25    util::{BaudPeriph, RccPeriph, bounded_loop, cr1, isr},
26};
27
28// todo: Prescaler (USART_PRESC) register on v3 (L5, G, H etc)
29
30/// Serial error
31#[non_exhaustive]
32#[derive(Debug, Clone, Copy, Eq, PartialEq, defmt::Format)]
33pub enum UsartError {
34    /// Framing error
35    Framing,
36    /// Noise error
37    Noise,
38    /// RX buffer overrun
39    Overrun,
40    /// Parity check error
41    Parity,
42}
43
44#[derive(Clone, Copy)]
45#[repr(u8)]
46/// The number of stop bits. (USART_CR2, STOP)
47pub enum StopBits {
48    S1 = 0b00,
49    S0_5 = 0b01,
50    S2 = 0b10,
51    S1_5 = 0b11,
52}
53
54#[derive(Clone, Copy, PartialEq)]
55/// Parity control enable/disable, and even/odd selection (USART_CR1, PCE and PS)
56pub enum Parity {
57    EnabledEven,
58    EnabledOdd,
59    Disabled,
60}
61
62#[derive(Clone, Copy)]
63/// The length of word to transmit and receive. (USART_CR1, M)
64pub enum WordLen {
65    W8,
66    W9,
67    W7,
68}
69
70impl WordLen {
71    /// We use this function due to the M field being split into 2 separate bits.
72    /// Returns M1 val, M0 val
73    pub fn bits(&self) -> (u8, u8) {
74        match self {
75            Self::W8 => (0, 0),
76            Self::W9 => (0, 1),
77            Self::W7 => (1, 0),
78        }
79    }
80}
81
82#[derive(Clone, Copy)]
83#[repr(u8)]
84/// Set Oversampling16 or Oversampling8 modes.
85pub enum OverSampling {
86    O16 = 0,
87    O8 = 1,
88}
89
90#[derive(Clone, Copy, PartialEq)]
91pub enum IrdaMode {
92    /// "IrDA mode disabled
93    None,
94    /// "IrDA SIR rx/tx enabled in 'normal' mode"
95    Normal,
96    /// "IrDA SIR 'low-power' mode"
97    LowPower,
98}
99
100#[cfg(not(feature = "f4"))]
101#[derive(Clone, Copy)]
102/// The type of USART interrupt to configure. Reference the USART_ISR register.
103pub enum UsartInterrupt {
104    /// If the inner value of this is `Some`, its inner value will set
105    /// the character to match on `enable_interrupt`. The option's value doesn't
106    /// affect anything when stopping or clearing interrupts.
107    CharDetect(Option<u8>),
108    Cts,
109    EndOfBlock,
110    Idle,
111    FramingError,
112    LineBreak,
113    Overrun,
114    ParityError,
115    ReadNotEmpty,
116    ReceiverTimeout,
117    #[cfg(not(any(feature = "f3", feature = "l4")))] // todo: PAC ommission?
118    Tcbgt,
119    TransmissionComplete,
120    TransmitEmpty,
121}
122
123/// Configuration for U(S)ART. and LpUart. Can be used with default::Default.
124pub struct UsartConfig {
125    /// Word length. Defaults to 8-bits.
126    pub word_len: WordLen,
127    /// Stop bits: Defaults to 1.
128    pub stop_bits: StopBits,
129    /// Oversampling rate. Defaults to 16x. N/A for LpUart.
130    pub oversampling: OverSampling,
131    /// Enable or disable parity control. Defaults to disabled.
132    pub parity: Parity,
133    /// IrDA mode: Enables this protocol, which is used to communicate with IR devices.
134    /// N/A for LpUart.
135    pub irda_mode: IrdaMode,
136    #[cfg(any(feature = "g4", feature = "h7"))]
137    /// The first-in, first-out buffer is enabled. Defaults to enabled.
138    pub fifo_enabled: bool,
139    #[cfg(not(feature = "f4"))]
140    /// Optionally, disable the overrun functionality. Defaults to `false`.
141    pub overrun_disabled: bool,
142}
143
144impl Default for UsartConfig {
145    fn default() -> Self {
146        Self {
147            word_len: WordLen::W8,
148            stop_bits: StopBits::S1,
149            oversampling: OverSampling::O16,
150            parity: Parity::Disabled,
151            irda_mode: IrdaMode::None,
152            #[cfg(any(feature = "g4", feature = "h7"))]
153            fifo_enabled: true,
154            #[cfg(not(feature = "f4"))]
155            overrun_disabled: false,
156        }
157    }
158}
159
160// Sep macros due to too many feature-gates.
161// todo: Use functions?
162
163// todo: Support fifo_disabled regs.
164
165/// Represents the USART peripheral, for serial communications.
166pub struct Usart<R> {
167    pub regs: R,
168    baud: u32,
169    config: UsartConfig,
170}
171
172impl<R> Usart<R>
173where
174    R: Deref<Target = pac::usart1::RegisterBlock> + RccPeriph + BaudPeriph,
175{
176    /// Initialize a U(S)ART peripheral, including configuration register writes, and enabling and
177    /// resetting its RCC peripheral clock. `baud` is the baud rate, in bytes-per-second.
178    pub fn new(regs: R, baud: u32, config: UsartConfig, clock_cfg: &Clocks) -> Result<Self> {
179        let rcc = unsafe { &(*RCC::ptr()) };
180        R::en_reset(rcc);
181
182        let mut usart = Self { regs, baud, config };
183
184        // This should already be disabled on power up, but disable here just in case;
185        // some bits can't be set with USART enabled.
186
187        usart.disable()?;
188
189        // Set up transmission. See L44 RM, section 38.5.2: "Character Transmission Procedures".
190        // 1. Program the M bits in USART_CR1 to define the word length.
191
192        let word_len_bits = usart.config.word_len.bits();
193        cr1!(usart.regs).modify(|_, w| {
194            w.over8().bit(usart.config.oversampling as u8 != 0);
195            w.pce().bit(usart.config.parity != Parity::Disabled);
196            cfg_if! {
197                if #[cfg(not(any(feature = "f", feature = "wl")))] {
198                    w.m1().bit(word_len_bits.0 != 0);
199                    w.m0().bit(word_len_bits.1 != 0);
200                    return w.ps().bit(usart.config.parity == Parity::EnabledOdd);
201                } else if #[cfg(feature = "f")] {
202                    // todo: QC this.
203                    w.m().bit(word_len_bits.0 != 0);
204                    return w.ps().bit(usart.config.parity == Parity::EnabledOdd);
205                } else {
206                    return w.ps().bit(usart.config.parity == Parity::EnabledOdd);
207                }
208            }
209        });
210
211        #[cfg(not(feature = "f4"))]
212        usart
213            .regs
214            .cr3()
215            .modify(|_, w| w.ovrdis().bit(usart.config.overrun_disabled));
216
217        // Must be done before enabling.
218        #[cfg(any(feature = "g4", feature = "h7"))]
219        usart
220            .regs
221            .cr1()
222            .modify(|_, w| w.fifoen().bit(usart.config.fifo_enabled));
223
224        // 2. Select the desired baud rate using the USART_BRR register.
225        usart.set_baud(baud, clock_cfg).ok();
226        // 3. Program the number of stop bits in USART_CR2.
227        usart
228            .regs
229            .cr2()
230            .modify(|_, w| unsafe { w.stop().bits(usart.config.stop_bits as u8) });
231        // 4. Enable the USART by writing the UE bit in USART_CR1 register to 1.
232        usart.enable()?;
233
234        // 5. Select DMA enable (DMAT[R]] in USART_CR3 if multibuffer communication is to take
235        // place. Configure the DMA register as explained in multibuffer communication.
236        // (Handled in `read_dma()` and `write_dma()`)
237        // 6. Set the TE bit in USART_CR1 to send an idle frame as first transmission.
238        // 6. Set the RE bit USART_CR1. This enables the receiver which begins searching for a
239        // start bit.
240
241        cr1!(usart.regs).modify(|_, w| {
242            w.te().bit(true);
243            w.re().bit(true)
244        });
245
246        match usart.config.irda_mode {
247            // See G4 RM, section 37.5.18: USART IrDA SIR ENDEC block
248            // " IrDA mode is selected by setting the IREN bit in the USART_CR3 register. In IrDA mode,
249            // the following bits must be kept cleared:
250            // • LINEN, STOP and CLKEN bits in the USART_CR2 register,
251            IrdaMode::None => (),
252            _ => {
253                usart.regs.cr2().modify(|_, w| unsafe {
254                    w.linen().clear_bit();
255                    w.stop().bits(0);
256                    w.clken().clear_bit()
257                });
258
259                // • SCEN and HDSEL bits in the USART_CR3 register."
260                usart.regs.cr3().modify(|_, w| {
261                    w.scen().clear_bit();
262                    w.hdsel().clear_bit();
263                    w.irlp().bit(usart.config.irda_mode == IrdaMode::LowPower);
264                    w.iren().bit(true)
265                });
266            }
267        }
268
269        Ok(usart)
270    }
271}
272
273impl<R> Usart<R>
274where
275    R: Deref<Target = pac::usart1::RegisterBlock> + BaudPeriph,
276{
277    /// Set the BAUD rate. Called during init, and can be called later to change BAUD
278    /// during program execution.
279    pub fn set_baud(&mut self, baud: u32, clock_cfg: &Clocks) -> Result<()> {
280        let originally_enabled = cr1!(self.regs).read().ue().bit_is_set();
281
282        if originally_enabled {
283            cr1!(self.regs).modify(|_, w| w.ue().clear_bit());
284            bounded_loop!(
285                cr1!(self.regs).read().ue().bit_is_set(),
286                Error::RegisterUnchanged
287            );
288        }
289
290        // To set BAUD rate, see L4 RM section 38.5.4: "USART baud rate generation".
291        // todo: This assumes the USART clock is APB1 or 2 depending on which USART.
292        // todo: Take into account the selectable USART clock in both
293        // todo util::baud implementation, and `clocks` module.
294        let fclk = R::baud(clock_cfg);
295
296        let usart_div = match self.config.oversampling {
297            OverSampling::O16 => fclk / baud,
298            OverSampling::O8 => 2 * fclk / baud,
299        };
300
301        // USARTDIV is an unsigned fixed point number that is coded on the USART_BRR register.
302        // • When OVER8 = 0, BRR = USARTDIV.
303        // • When OVER8 = 1
304        // – BRR[2:0] = USARTDIV[3:0] shifted 1 bit to the right.
305        // – BRR[3] must be kept cleared.
306        // – BRR[15:4] = USARTDIV[15:4]
307        // todo: BRR needs to be modified per the above if on oversampling 8.
308
309        #[cfg(feature = "f4")]
310        let div = usart_div as u16;
311        #[cfg(not(feature = "f4"))]
312        // let div = usart_div as u32;
313        let div = usart_div;
314
315        self.regs.brr().write(|w| unsafe { w.bits(div) });
316
317        self.baud = baud;
318
319        if originally_enabled {
320            cr1!(self.regs).modify(|_, w| w.ue().bit(true));
321        }
322
323        Ok(())
324    }
325}
326
327impl<R> Usart<R>
328where
329    R: Deref<Target = pac::usart1::RegisterBlock> + RccPeriph,
330{
331    /// Enable this U(S)ART peripheral.
332    pub fn enable(&mut self) -> Result<()> {
333        cr1!(self.regs).modify(|_, w| w.ue().bit(true));
334        bounded_loop!(
335            cr1!(self.regs).read().ue().bit_is_clear(),
336            Error::RegisterUnchanged
337        );
338
339        Ok(())
340    }
341
342    /// Disable this U(S)ART peripheral.
343    pub fn disable(&mut self) -> Result<()> {
344        cr1!(self.regs).modify(|_, w| w.ue().clear_bit());
345        bounded_loop!(
346            cr1!(self.regs).read().ue().bit_is_set(),
347            Error::RegisterUnchanged
348        );
349        Ok(())
350    }
351
352    /// Transmit data, as a sequence of u8. See L44 RM, section 38.5.2: "Character transmission procedure"
353    pub fn write(&mut self, data: &[u8]) -> Result<()> {
354        // todo: how does this work with a 9 bit words? Presumably you'd need to make `data`
355        // todo take `&u16`.
356
357        // 7. Write the data to send in the USART_TDR register (this clears the TXE bit). Repeat this
358        // for each data to be transmitted in case of single buffer.
359
360        for word in data {
361            cfg_if! {
362                if #[cfg(any(
363                    feature = "h5",
364                    feature = "c0",
365                    feature = "g050", feature = "g051", feature = "g061", feature = "g0b0", feature = "g0b1", feature = "g0c1")
366                )] {
367                    bounded_loop!(
368                        isr!(self.regs).read().txfe().bit_is_clear(),
369                        Error::RegisterUnchanged
370                    );
371                } else if #[cfg(feature = "f4")] {
372                    bounded_loop!(
373                        isr!(self.regs).read().tc().bit_is_clear(),
374                        Error::RegisterUnchanged
375                    );
376                    bounded_loop!(
377                        isr!(self.regs).read().txe().bit_is_clear(),
378                        Error::RegisterUnchanged
379                    );
380                } else {
381                    bounded_loop!(
382                        isr!(self.regs).read().txe().bit_is_clear(),
383                        Error::RegisterUnchanged
384                    );
385                }
386            }
387
388            // 8. After writing the last data into the USART_TDR register, wait until TC=1. This indicates
389            // that the transmission of the last frame is complete. This is required for instance when
390            // the USART is disabled or enters the Halt mode to avoid corrupting the last
391            // transmission
392            cfg_if! {
393                if #[cfg(feature = "f4")] {
394                    self.regs
395                        .dr()
396                        .modify(|_, w| unsafe { w.dr().bits(*word as u16) });
397                    bounded_loop!(
398                        self.regs.sr().read().tc().bit_is_clear(),
399                        Error::RegisterUnchanged
400                    );
401                } else {
402                    // Note: Per these PACs, TXFNF and TXE are on the same field, so this is actually
403                    // checking txfnf if the fifo is enabled.
404                    self.regs
405                        .tdr()
406                        .modify(|_, w| unsafe { w.tdr().bits(*word as u16) });
407                }
408            }
409        }
410
411        Ok(())
412    }
413
414    /// Write a single word, without waiting until ready for the next. Compared to the `write()` function, this
415    /// does not block.
416    pub fn write_one(&mut self, word: u8) {
417        // todo: how does this work with a 9 bit words? Presumably you'd need to make `data`
418        // todo take `&u16`.
419        cfg_if! {
420            if #[cfg(not(feature = "f4"))] {
421            self.regs
422                .tdr()
423                .modify(|_, w| unsafe { w.tdr().bits(word as u16) });
424            } else {
425                self.regs
426                    .dr()
427                    .modify(|_, w| unsafe { w.dr().bits(word as u16) });
428            }
429        }
430    }
431
432    /// Receive data into a u8 buffer. See L44 RM, section 38.5.3: "Character reception procedure"
433    pub fn read(&mut self, buf: &mut [u8]) -> Result<()> {
434        for i in 0..buf.len() {
435            // Wait for the next bit
436
437            cfg_if! {
438                if #[cfg(any(
439                    feature = "h5",
440                    feature = "c0",
441                    feature = "g050", feature = "g051", feature = "g061", feature = "g0b0", feature = "g0b1", feature = "g0c1")
442                )] {
443                    bounded_loop!(
444                        isr!(self.regs).read().rxfne().bit_is_clear(),
445                        Error::RegisterUnchanged
446                    );
447                } else {
448                    bounded_loop!(
449                        isr!(self.regs).read().rxne().bit_is_clear(),
450                        Error::RegisterUnchanged
451                    );
452                }
453            }
454
455            #[cfg(not(feature = "f4"))]
456            {
457                buf[i] = self.regs.rdr().read().rdr().bits() as u8;
458            }
459            #[cfg(feature = "f4")]
460            {
461                buf[i] = self.regs.dr().read().dr().bits() as u8;
462            }
463        }
464
465        // When a character is received:
466        // • The RXNE bit is set to indicate that the content of the shift register is transferred to the
467        // RDR. In other words, data has been received and can be read (as well as its
468        // associated error flags).
469        // • An interrupt is generated if the RXNEIE bit is set.
470        // • The error flags can be set if a frame error, noise or an overrun error has been detected
471        // during reception. PE flag can also be set with RXNE.
472        // • In multibuffer, RXNE is set after every byte received and is cleared by the DMA read of
473        // the Receive data Register.
474        // • In single buffer mode, clearing the RXNE bit is performed by a software read to the
475        // USART_RDR register. The RXNE flag can also be cleared by writing 1 to the RXFRQ
476        // in the USART_RQR register. The RXNE bit must be cleared before the end of the
477        // reception of the next character to avoid an overrun error
478
479        Ok(())
480    }
481
482    /// Read a single word, without waiting until ready for the next. Compared to the `read()` function, this
483    /// does not block.
484    pub fn read_one(&mut self) -> u8 {
485        cfg_if! {
486            if #[cfg(not(feature = "f4"))] {
487                self.regs.rdr().read().rdr().bits() as u8
488            } else {
489                self.regs.dr().read().dr().bits() as u8
490            }
491        }
492    }
493
494    #[cfg(not(any(feature = "f4", feature = "l552", feature = "h5")))]
495    /// Transmit data using DMA. (L44 RM, section 38.5.15)
496    /// Note that the `channel` argument is unused on F3 and L4, since it is hard-coded,
497    /// and can't be configured using the DMAMUX peripheral. (`dma::mux()` fn).
498    pub unsafe fn write_dma(
499        &mut self,
500        buf: &[u8],
501        channel: DmaChannel,
502        channel_cfg: ChannelCfg,
503        dma_periph: dma::DmaPeriph,
504    ) -> Result<()> {
505        let (ptr, len) = (buf.as_ptr(), buf.len());
506
507        // To map a DMA channel for USART transmission, use
508        // the following procedure (x denotes the channel number):
509
510        #[cfg(any(feature = "f3", feature = "l4"))]
511        let channel = R::write_chan();
512        #[cfg(feature = "l4")]
513        let mut dma_regs = unsafe { &(*DMA1::ptr()) }; // todo: Hardcoded DMA1
514        #[cfg(feature = "l4")]
515        R::write_sel(&mut dma_regs);
516
517        let num_data = len as u32;
518
519        // "DMA mode can be enabled for transmission by setting DMAT bit in the USART_CR3
520        // register. Data is loaded from a SRAM area configured using the DMA peripheral (refer to
521        // Section 11: Direct memory access controller (DMA) on page 295) to the USART_TDR
522        // register whenever the TXE bit is set."
523        self.regs.cr3().modify(|_, w| w.dmat().bit(true));
524
525        // 6. Clear the TC flag in the USART_ISR register by setting the TCCF bit in the
526        // USART_ICR register.
527        self.regs.icr().write(|w| w.tccf().bit(true));
528
529        match dma_periph {
530            dma::DmaPeriph::Dma1 => {
531                let mut regs = unsafe { &(*DMA1::ptr()) };
532                dma::cfg_channel(
533                    &mut regs,
534                    channel,
535                    // 1. Write the USART_TDR register address in the DMA control register to configure it as
536                    // the destination of the transfer. The data is moved to this address from memory after
537                    // each TXE event.
538                    self.regs.tdr().as_ptr() as u32,
539                    // 2. Write the memory address in the DMA control register to configure it as the source of
540                    // the transfer. The data is loaded into the USART_TDR register from this memory area
541                    // after each TXE event.
542                    ptr as u32,
543                    // 3. Configure the total number of bytes to be transferred to the DMA control register.
544                    num_data,
545                    dma::Direction::ReadFromMem,
546                    // 4. Configure the channel priority in the DMA control register
547                    // (Handled by `ChannelCfg::default())`
548                    dma::DataSize::S8,
549                    dma::DataSize::S8,
550                    channel_cfg,
551                )
552            }
553            #[cfg(dma2)]
554            dma::DmaPeriph::Dma2 => {
555                let mut regs = unsafe { &(*pac::DMA2::ptr()) };
556                dma::cfg_channel(
557                    &mut regs,
558                    channel,
559                    self.regs.tdr().as_ptr() as u32,
560                    ptr as u32,
561                    num_data,
562                    dma::Direction::ReadFromMem,
563                    dma::DataSize::S8,
564                    dma::DataSize::S8,
565                    channel_cfg,
566                )
567            }
568        }
569
570        // 5. Configure DMA interrupt generation after half/ full transfer as required by the
571        // application.
572        // (Handled in `cfg_channel`)
573
574        // 7. Activate the channel in the DMA register.
575        // When the number of data transfers programmed in the DMA Controller is reached, the DMA
576        // controller generates an interrupt on the DMA channel interrupt vector.
577        // (Handled in `cfg_channel`)
578
579        // In transmission mode, once the DMA has written all the data to be transmitted (the TCIF flag
580        // is set in the DMA_ISR register), the TC flag can be monitored to make sure that the USART
581        // communication is complete. This is required to avoid corrupting the last transmission before
582        // disabling the USART or entering Stop mode. Software must wait until TC=1. The TC flag
583        // remains cleared during all data transfers and it is set by hardware at the end of transmission
584        // of the last frame.
585    }
586
587    #[cfg(not(any(feature = "f4", feature = "l552", feature = "h5")))]
588    /// Receive data using DMA. (L44 RM, section 38.5.15; G4 RM section 37.5.19.
589    /// Note that the `channel` argument is unused on F3 and L4, since it is hard-coded,
590    /// and can't be configured using the DMAMUX peripheral. (`dma::mux()` fn).
591    pub unsafe fn read_dma(
592        &mut self,
593        buf: &mut [u8],
594        channel: DmaChannel,
595        channel_cfg: ChannelCfg,
596        dma_periph: dma::DmaPeriph,
597    ) -> Result<()> {
598        let (ptr, len) = (buf.as_mut_ptr(), buf.len());
599
600        #[cfg(any(feature = "f3", feature = "l4"))]
601        let channel = R::read_chan();
602        #[cfg(feature = "l4")]
603        let mut dma_regs = unsafe { &(*DMA1::ptr()) }; // todo: Hardcoded DMA1
604        #[cfg(feature = "l4")]
605        R::write_sel(&mut dma_regs);
606
607        let num_data = len as u32;
608
609        // DMA mode can be enabled for reception by setting the DMAR bit in USART_CR3 register.
610        self.regs.cr3().modify(|_, w| w.dmar().bit(true));
611
612        match dma_periph {
613            dma::DmaPeriph::Dma1 => {
614                let mut regs = unsafe { &(*DMA1::ptr()) };
615                dma::cfg_channel(
616                    &mut regs,
617                    channel,
618                    // 1. Write the USART_RDR register address in the DMA control register to configure it as
619                    // the source of the transfer. The data is moved from this address to the memory after
620                    // each RXNE event.
621                    self.regs.rdr().as_ptr() as u32,
622                    // 2. Write the memory address in the DMA control register to configure it as the destination
623                    // of the transfer. The data is loaded from USART_RDR to this memory area after each
624                    // RXNE event.
625                    ptr as u32,
626                    // 3. Configure the total number of bytes to be transferred to the DMA control register.
627                    num_data,
628                    dma::Direction::ReadFromPeriph,
629                    dma::DataSize::S8,
630                    dma::DataSize::S8,
631                    channel_cfg,
632                )
633            }
634            #[cfg(dma2)]
635            dma::DmaPeriph::Dma2 => {
636                let mut regs = unsafe { &(*pac::DMA2::ptr()) };
637                dma::cfg_channel(
638                    &mut regs,
639                    channel,
640                    self.regs.rdr().as_ptr() as u32,
641                    ptr as u32,
642                    num_data,
643                    dma::Direction::ReadFromPeriph,
644                    dma::DataSize::S8,
645                    dma::DataSize::S8,
646                    channel_cfg,
647                )
648            }
649        }
650
651        // 4. Configure the channel priority in the DMA control register
652        // (Handled in cfg)
653
654        // 5. Configure interrupt generation after half/ full transfer as required by the application.
655        // (Handled by user code))
656
657        // 6. Activate the channel in the DMA control register. (Handled by `cfg_channel` above).
658        // When the number of data transfers programmed in the DMA Controller is reached, the DMA
659        // controller generates an interrupt on the DMA channel interrupt vector.
660        // (Handled in above fn call)
661
662        // When the number of data transfers programmed in the DMA Controller is reached, the DMA
663        // controller generates an interrupt on the DMA channel interrupt vector.
664    }
665
666    // /// Flush the transmit buffer.
667    // pub fn flush(&self) {
668    //     #[cfg(not(feature = "f4"))]
669    //     while isr!(self.regs).read().tc().bit_is_clear() {}
670    //     #[cfg(feature = "f4")]
671    //     while self.regs.sr().read().tc().bit_is_clear() {}
672    // }
673
674    #[cfg(not(feature = "f4"))]
675    /// Enable a specific type of interrupt. See G4 RM, Table 349: USART interrupt requests.
676    /// If `Some`, the inner value of `CharDetect` sets the address of the char to match.
677    /// If `None`, the interrupt is enabled without changing the char to match.
678    pub fn enable_interrupt(&mut self, interrupt: UsartInterrupt) -> Result<()> {
679        match interrupt {
680            UsartInterrupt::CharDetect(char_wrapper) => {
681                if let Some(char) = char_wrapper {
682                    // Disable the UART to allow writing the `add` and `addm7` bits
683                    cr1!(self.regs).modify(|_, w| w.ue().clear_bit());
684                    bounded_loop!(
685                        cr1!(self.regs).read().ue().bit_is_set(),
686                        Error::RegisterUnchanged
687                    );
688
689                    // Enable character-detecting UART interrupt
690                    cr1!(self.regs).modify(|_, w| w.cmie().bit(true));
691
692                    // Allow an 8-bit address to be set in `add`.
693                    self.regs.cr2().modify(|_, w| unsafe {
694                        w.addm7().bit(true);
695                        // Set the character to detect
696                        w.add().bits(char)
697                    });
698
699                    cr1!(self.regs).modify(|_, w| w.ue().bit(true));
700                    bounded_loop!(
701                        cr1!(self.regs).read().ue().bit_is_clear(),
702                        Error::RegisterUnchanged
703                    );
704                }
705
706                cr1!(self.regs).modify(|_, w| w.cmie().bit(true));
707            }
708            UsartInterrupt::Cts => {
709                self.regs.cr3().modify(|_, w| w.ctsie().bit(true));
710            }
711            UsartInterrupt::EndOfBlock => {
712                cr1!(self.regs).modify(|_, w| w.eobie().bit(true));
713            }
714            UsartInterrupt::Idle => {
715                cr1!(self.regs).modify(|_, w| w.idleie().bit(true));
716            }
717            UsartInterrupt::FramingError => {
718                self.regs.cr3().modify(|_, w| w.eie().bit(true));
719            }
720            UsartInterrupt::LineBreak => {
721                self.regs.cr2().modify(|_, w| w.lbdie().bit(true));
722            }
723            UsartInterrupt::Overrun => {
724                self.regs.cr3().modify(|_, w| w.eie().bit(true));
725            }
726            UsartInterrupt::ParityError => {
727                cr1!(self.regs).modify(|_, w| w.peie().bit(true));
728            }
729            UsartInterrupt::ReadNotEmpty => {
730                #[cfg(feature = "h5")]
731                cr1!(self.regs).modify(|_, w| w.rxfneie().bit(true));
732                #[cfg(not(feature = "h5"))]
733                cr1!(self.regs).modify(|_, w| w.rxneie().bit(true));
734            }
735            UsartInterrupt::ReceiverTimeout => {
736                cr1!(self.regs).modify(|_, w| w.rtoie().bit(true));
737            }
738            #[cfg(not(any(feature = "f3", feature = "l4")))]
739            UsartInterrupt::Tcbgt => {
740                self.regs.cr3().modify(|_, w| w.tcbgtie().bit(true));
741                self.regs.cr3().modify(|_, w| w.tcbgtie().bit(true));
742            }
743            UsartInterrupt::TransmissionComplete => {
744                cr1!(self.regs).modify(|_, w| w.tcie().bit(true));
745            }
746            UsartInterrupt::TransmitEmpty => {
747                #[cfg(feature = "h5")]
748                cr1!(self.regs).modify(|_, w| w.txfeie().bit(true));
749                #[cfg(not(feature = "h5"))]
750                cr1!(self.regs).modify(|_, w| w.txeie().bit(true));
751            }
752        }
753        Ok(())
754    }
755
756    #[cfg(not(feature = "f4"))]
757    /// Disable a specific type of interrupt. See G4 RM, Table 349: USART interrupt requests.
758    /// Note that the inner value of `CharDetect` doesn't do anything here.
759    pub fn disable_interrupt(&mut self, interrupt: UsartInterrupt) {
760        match interrupt {
761            UsartInterrupt::CharDetect(_) => {
762                cr1!(self.regs).modify(|_, w| w.cmie().clear_bit());
763            }
764            UsartInterrupt::Cts => {
765                self.regs.cr3().modify(|_, w| w.ctsie().clear_bit());
766            }
767            UsartInterrupt::EndOfBlock => {
768                cr1!(self.regs).modify(|_, w| w.eobie().clear_bit());
769            }
770            UsartInterrupt::Idle => {
771                cr1!(self.regs).modify(|_, w| w.idleie().clear_bit());
772            }
773            UsartInterrupt::FramingError => {
774                self.regs.cr3().modify(|_, w| w.eie().clear_bit());
775            }
776            UsartInterrupt::LineBreak => {
777                self.regs.cr2().modify(|_, w| w.lbdie().clear_bit());
778            }
779            UsartInterrupt::Overrun => {
780                self.regs.cr3().modify(|_, w| w.eie().clear_bit());
781            }
782            UsartInterrupt::ParityError => {
783                cr1!(self.regs).modify(|_, w| w.peie().clear_bit());
784            }
785            UsartInterrupt::ReadNotEmpty => {
786                #[cfg(feature = "h5")]
787                cr1!(self.regs).modify(|_, w| w.rxfneie().clear_bit());
788                #[cfg(not(feature = "h5"))]
789                cr1!(self.regs).modify(|_, w| w.rxneie().clear_bit());
790            }
791            UsartInterrupt::ReceiverTimeout => {
792                cr1!(self.regs).modify(|_, w| w.rtoie().clear_bit());
793            }
794            #[cfg(not(any(feature = "f3", feature = "l4")))]
795            UsartInterrupt::Tcbgt => {
796                self.regs.cr3().modify(|_, w| w.tcbgtie().clear_bit());
797                self.regs.cr3().modify(|_, w| w.tcbgtie().clear_bit());
798            }
799            UsartInterrupt::TransmissionComplete => {
800                cr1!(self.regs).modify(|_, w| w.tcie().clear_bit());
801            }
802            UsartInterrupt::TransmitEmpty => {
803                #[cfg(feature = "h5")]
804                cr1!(self.regs).modify(|_, w| w.txfeie().clear_bit());
805                #[cfg(not(feature = "h5"))]
806                cr1!(self.regs).modify(|_, w| w.txeie().clear_bit());
807            }
808        }
809    }
810
811    #[cfg(not(feature = "f4"))]
812    /// Print the (raw) contents of the status register.
813    pub fn read_status(&self) -> u32 {
814        unsafe { isr!(self.regs).read().bits() }
815    }
816
817    #[cfg(not(feature = "f4"))]
818    /// Clears the interrupt pending flag for a specific type of interrupt. Note that
819    /// it can also clear error flags, like Overrun and framing errors. See G4 RM,
820    /// Table 349: USART interrupt requests.
821    /// Note that the inner value of `CharDetect` doesn't do anything here.
822    pub fn clear_interrupt(&mut self, interrupt: UsartInterrupt) {
823        match interrupt {
824            UsartInterrupt::CharDetect(_) => self.regs.icr().write(|w| w.cmcf().bit(true)),
825            UsartInterrupt::Cts => self.regs.icr().write(|w| w.ctscf().bit(true)),
826            UsartInterrupt::EndOfBlock => self.regs.icr().write(|w| w.eobcf().bit(true)),
827            UsartInterrupt::Idle => self.regs.icr().write(|w| w.idlecf().bit(true)),
828            UsartInterrupt::FramingError => self.regs.icr().write(|w| w.fecf().bit(true)),
829            UsartInterrupt::LineBreak => self.regs.icr().write(|w| w.lbdcf().bit(true)),
830            UsartInterrupt::Overrun => self.regs.icr().write(|w| w.orecf().bit(true)),
831            UsartInterrupt::ParityError => self.regs.icr().write(|w| w.pecf().bit(true)),
832            UsartInterrupt::ReadNotEmpty => self.regs.rqr().write(|w| w.rxfrq().bit(true)),
833            UsartInterrupt::ReceiverTimeout => self.regs.icr().write(|w| w.rtocf().bit(true)),
834            #[cfg(not(any(feature = "f3", feature = "l4", feature = "h7")))]
835            UsartInterrupt::Tcbgt => self.regs.icr().write(|w| w.tcbgtcf().bit(true)),
836            #[cfg(feature = "h7")]
837            UsartInterrupt::Tcbgt => self.regs.icr().write(|w| w.tcbgtcf().bit(true)),
838            UsartInterrupt::TransmissionComplete => self.regs.icr().write(|w| w.tccf().bit(true)),
839            UsartInterrupt::TransmitEmpty => self.regs.rqr().write(|w| w.txfrq().bit(true)),
840        };
841    }
842
843    #[cfg(not(feature = "f4"))]
844    /// Checks if a given status flag is set. Returns `true` if the status flag is set. Note that this preforms
845    /// a read each time called. If checking multiple flags, this isn't optimal.
846    pub fn check_status_flag(&mut self, flag: UsartInterrupt) -> bool {
847        let status = isr!(self.regs).read();
848
849        match flag {
850            UsartInterrupt::CharDetect(_) => status.cmf().bit_is_set(),
851            UsartInterrupt::Cts => status.cts().bit_is_set(),
852            UsartInterrupt::EndOfBlock => status.eobf().bit_is_set(),
853            UsartInterrupt::Idle => status.idle().bit_is_set(),
854            UsartInterrupt::FramingError => status.fe().bit_is_set(),
855            UsartInterrupt::LineBreak => status.lbdf().bit_is_set(),
856            UsartInterrupt::Overrun => status.ore().bit_is_set(),
857            UsartInterrupt::ParityError => status.pe().bit_is_set(),
858            #[cfg(any(
859                feature = "h5",
860                feature = "c0",
861                feature = "g050",
862                feature = "g051",
863                feature = "g061",
864                feature = "g0b0",
865                feature = "g0b1",
866                feature = "g0c1"
867            ))]
868            UsartInterrupt::ReadNotEmpty => status.rxfne().bit_is_set(),
869            #[cfg(not(any(
870                feature = "h5",
871                feature = "c0",
872                feature = "g050",
873                feature = "g051",
874                feature = "g061",
875                feature = "g0b0",
876                feature = "g0b1",
877                feature = "g0c1"
878            )))]
879            UsartInterrupt::ReadNotEmpty => status.rxne().bit_is_set(),
880            UsartInterrupt::ReceiverTimeout => status.rtof().bit_is_set(),
881            #[cfg(not(any(feature = "f3", feature = "l4")))]
882            UsartInterrupt::Tcbgt => status.tcbgt().bit_is_set(),
883            UsartInterrupt::TransmissionComplete => status.tc().bit_is_set(),
884            #[cfg(any(
885                feature = "h5",
886                feature = "c0",
887                feature = "g050",
888                feature = "g051",
889                feature = "g061",
890                feature = "g0b0",
891                feature = "g0b1",
892                feature = "g0c1"
893            ))]
894            UsartInterrupt::TransmitEmpty => status.txfe().bit_is_set(),
895            #[cfg(not(any(
896                feature = "h5",
897                feature = "c0",
898                feature = "g050",
899                feature = "g051",
900                feature = "g061",
901                feature = "g0b0",
902                feature = "g0b1",
903                feature = "g0c1"
904            )))]
905            UsartInterrupt::TransmitEmpty => status.txe().bit_is_set(),
906        }
907    }
908
909    fn check_status(&mut self) -> core::result::Result<(), UsartError> {
910        cfg_if! {
911            if #[cfg(feature = "f4")] {
912                let status = self.regs.sr().read();
913            } else {
914                let status = self.regs.isr().read();
915            }
916        }
917        let mut result = if status.pe().bit_is_set() {
918            Err(UsartError::Parity)
919        } else if status.fe().bit_is_set() {
920            Err(UsartError::Framing)
921        } else if status.ore().bit_is_set() {
922            Err(UsartError::Overrun)
923        } else {
924            Ok(())
925        };
926
927        #[cfg(not(any(
928            feature = "wl",
929            feature = "c0",
930            feature = "g050",
931            feature = "g051",
932            feature = "g061",
933            feature = "g0b0",
934            feature = "g0b1",
935            feature = "g0c1"
936        )))]
937        if status.nf().bit_is_set() {
938            result = Err(UsartError::Noise);
939        }
940
941        #[cfg(any(
942            feature = "c0",
943            feature = "g050",
944            feature = "g051",
945            feature = "g061",
946            feature = "g0b0",
947            feature = "g0b1",
948            feature = "g0c1"
949        ))]
950        if status.ne().bit_is_set() {
951            result = Err(UsartError::Noise);
952        }
953
954        if result.is_err() {
955            // For F4, clear error flags by reading SR and DR
956            // For others, clear error flags by reading ISR, clearing ICR, then reading RDR
957            cfg_if! {
958                if #[cfg(feature = "f4")] {
959                    let _ = self.regs.dr().read();
960                } else {
961                    self.regs.icr().write(|w| {
962                        w.pecf().bit(true);
963                        w.fecf().bit(true);
964                        #[cfg(not(any(feature = "c0", feature = "g050", feature = "g051", feature = "g061", feature = "g0b0", feature = "g0b1", feature = "g0c1")))]
965                        w.ncf().bit(true);
966                        #[cfg(any(feature = "c0", feature = "g050", feature = "g051", feature = "g061", feature = "g0b0", feature = "g0b1", feature = "g0c1"))]
967                        w.necf().bit(true);
968                        w.orecf().bit(true)
969                    });
970                    let _ = self.regs.rdr().read();
971                }
972            }
973        }
974        result
975    }
976}
977
978#[cfg(feature = "embedded_hal")]
979mod embedded_io_impl {
980    use embedded_io::{ErrorType, Read, ReadReady, Write, WriteReady};
981
982    use super::*;
983
984    impl<R> ErrorType for Usart<R> {
985        type Error = crate::error::Error;
986    }
987
988    impl<R> Read for Usart<R>
989    where
990        R: Deref<Target = pac::usart1::RegisterBlock> + RccPeriph + BaudPeriph,
991        Usart<R>: ReadReady,
992    {
993        fn read(&mut self, mut buf: &mut [u8]) -> core::result::Result<usize, Self::Error> {
994            // Block until at least one byte can be read:
995            while !self.read_ready()? {
996                cortex_m::asm::nop();
997            }
998
999            let buf_len = buf.len();
1000            while !buf.is_empty() && self.read_ready()? {
1001                let (first, remaining) = buf.split_first_mut().unwrap();
1002                *first = self.read_one();
1003                buf = remaining;
1004            }
1005            Ok(buf_len - buf.len())
1006        }
1007    }
1008
1009    impl<R> ReadReady for Usart<R>
1010    where
1011        R: Deref<Target = pac::usart1::RegisterBlock> + RccPeriph + BaudPeriph,
1012    {
1013        fn read_ready(&mut self) -> core::result::Result<bool, Self::Error> {
1014            self.check_status()?;
1015            cfg_if! {
1016                if #[cfg(any(
1017                    feature = "h5",
1018                    feature = "c0",
1019                    feature = "g050", feature = "g051", feature = "g061", feature = "g0b0", feature = "g0b1", feature = "g0c1")
1020                )] {
1021                    let ready = self.regs.isr().read().rxfne().bit_is_set();
1022                } else if #[cfg(feature = "f4")] {
1023                    let ready = self.regs.sr().read().rxne().bit_is_set();
1024                } else {
1025                    let ready = self.regs.isr().read().rxne().bit_is_set();
1026                }
1027            };
1028            Ok(ready)
1029        }
1030    }
1031
1032    impl<R> Write for Usart<R>
1033    where
1034        R: Deref<Target = pac::usart1::RegisterBlock> + RccPeriph + BaudPeriph,
1035    {
1036        fn write(&mut self, mut buf: &[u8]) -> core::result::Result<usize, Self::Error> {
1037            // Block until at least one byte can be written:
1038            while !self.write_ready()? {
1039                cortex_m::asm::nop();
1040            }
1041
1042            let buf_len = buf.len();
1043            while !buf.is_empty() && self.write_ready()? {
1044                let (byte, remaining) = buf.split_first().unwrap();
1045                self.write_one(*byte);
1046                buf = remaining;
1047            }
1048            Ok(buf_len - buf.len())
1049        }
1050
1051        fn flush(&mut self) -> core::result::Result<(), Self::Error> {
1052            #[cfg(not(feature = "f4"))]
1053            while isr!(self.regs).read().tc().bit_is_clear() {}
1054            #[cfg(feature = "f4")]
1055            while self.regs.sr().read().tc().bit_is_clear() {}
1056            Ok(())
1057        }
1058    }
1059
1060    impl<R> WriteReady for Usart<R>
1061    where
1062        R: Deref<Target = pac::usart1::RegisterBlock> + RccPeriph + BaudPeriph,
1063    {
1064        fn write_ready(&mut self) -> core::result::Result<bool, Self::Error> {
1065            cfg_if! {
1066                if #[cfg(any(
1067                    feature = "h5",
1068                    feature = "c0",
1069                    feature = "g050", feature = "g051", feature = "g061", feature = "g0b0", feature = "g0b1", feature = "g0c1")
1070                )] {
1071                    let ready = self.regs.isr().read().txfe().bit_is_set();
1072                } else if #[cfg(feature = "f4")] {
1073                    let ready = self.regs.sr().read().txe().bit_is_set();
1074                } else {
1075                    let ready = self.regs.isr().read().txe().bit_is_set();
1076                }
1077            };
1078            Ok(ready)
1079        }
1080    }
1081}