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