stm32f0xx_hal/
serial.rs

1//! API for the integrated USART ports
2//!
3//! This only implements the usual asynchronous bidirectional 8-bit transfers.
4//!
5//! It's possible to use a read-only/write-only serial implementation with
6//! `usartXrx`/`usartXtx`.
7//!
8//! # Examples
9//! Echo
10//! ``` no_run
11//! use stm32f0xx_hal as hal;
12//!
13//! use crate::hal::prelude::*;
14//! use crate::hal::serial::Serial;
15//! use crate::hal::pac;
16//!
17//! use nb::block;
18//!
19//! cortex_m::interrupt::free(|cs| {
20//!     let rcc = p.RCC.configure().sysclk(48.mhz()).freeze();
21//!
22//!     let gpioa = p.GPIOA.split(&mut rcc);
23//!
24//!     let tx = gpioa.pa9.into_alternate_af1(cs);
25//!     let rx = gpioa.pa10.into_alternate_af1(cs);
26//!
27//!     let mut serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc);
28//!
29//!     loop {
30//!         let received = block!(serial.read()).unwrap();
31//!         block!(serial.write(received)).ok();
32//!     }
33//! });
34//! ```
35//!
36//! Hello World
37//! ``` no_run
38//! use stm32f0xx_hal as hal;
39//!
40//! use crate::hal::prelude::*;
41//! use crate::hal::serial::Serial;
42//! use crate::hal::pac;
43//!
44//! use nb::block;
45//!
46//! cortex_m::interrupt::free(|cs| {
47//!     let rcc = p.RCC.configure().sysclk(48.mhz()).freeze();
48//!
49//!     let gpioa = p.GPIOA.split(&mut rcc);
50//!
51//!     let tx = gpioa.pa9.into_alternate_af1(cs);
52//!
53//!     let mut serial = Serial::usart1tx(p.USART1, tx, 115_200.bps(), &mut rcc);
54//!
55//!     loop {
56//!         serial.write_str("Hello World!\r\n");
57//!     }
58//! });
59//! ```
60
61use core::{
62    convert::Infallible,
63    fmt::{Result, Write},
64    ops::Deref,
65};
66
67use embedded_hal::prelude::*;
68
69use crate::{gpio::*, rcc::Rcc, time::Bps};
70
71use core::marker::PhantomData;
72
73/// Serial error
74#[non_exhaustive]
75#[derive(Debug)]
76pub enum Error {
77    /// Framing error
78    Framing,
79    /// Noise error
80    Noise,
81    /// RX buffer overrun
82    Overrun,
83    /// Parity check error
84    Parity,
85}
86
87/// Interrupt event
88pub enum Event {
89    /// New data has been received
90    Rxne,
91    /// New data can be sent
92    Txe,
93    /// Idle line state detected
94    Idle,
95}
96
97pub trait TxPin<USART> {}
98pub trait RxPin<USART> {}
99
100macro_rules! usart_pins {
101    ($($USART:ident => {
102        tx => [$($tx:ty),+ $(,)*],
103        rx => [$($rx:ty),+ $(,)*],
104    })+) => {
105        $(
106            $(
107                impl TxPin<crate::pac::$USART> for $tx {}
108            )+
109            $(
110                impl RxPin<crate::pac::$USART> for $rx {}
111            )+
112        )+
113    }
114}
115
116#[cfg(any(
117    feature = "stm32f030",
118    feature = "stm32f031",
119    feature = "stm32f038",
120    feature = "stm32f042",
121    feature = "stm32f048",
122    feature = "stm32f051",
123    feature = "stm32f058",
124    feature = "stm32f070",
125    feature = "stm32f071",
126    feature = "stm32f072",
127    feature = "stm32f078",
128    feature = "stm32f091",
129    feature = "stm32f098",
130))]
131usart_pins! {
132    USART1 => {
133        tx => [gpioa::PA9<Alternate<AF1>>, gpiob::PB6<Alternate<AF0>>],
134        rx => [gpioa::PA10<Alternate<AF1>>, gpiob::PB7<Alternate<AF0>>],
135    }
136}
137#[cfg(any(
138    feature = "stm32f030x4",
139    feature = "stm32f030x6",
140    feature = "stm32f031",
141    feature = "stm32f038",
142))]
143usart_pins! {
144    USART1 => {
145        tx => [gpioa::PA2<Alternate<AF1>>, gpioa::PA14<Alternate<AF1>>],
146        rx => [gpioa::PA3<Alternate<AF1>>, gpioa::PA15<Alternate<AF1>>],
147    }
148}
149
150#[cfg(any(
151    feature = "stm32f030x8",
152    feature = "stm32f030xc",
153    feature = "stm32f042",
154    feature = "stm32f048",
155    feature = "stm32f051",
156    feature = "stm32f058",
157    feature = "stm32f070",
158    feature = "stm32f071",
159    feature = "stm32f072",
160    feature = "stm32f078",
161    feature = "stm32f091",
162    feature = "stm32f098",
163))]
164usart_pins! {
165    USART2 => {
166        tx => [gpioa::PA2<Alternate<AF1>>, gpioa::PA14<Alternate<AF1>>],
167        rx => [gpioa::PA3<Alternate<AF1>>, gpioa::PA15<Alternate<AF1>>],
168    }
169}
170#[cfg(any(
171    feature = "stm32f071",
172    feature = "stm32f072",
173    feature = "stm32f078",
174    feature = "stm32f091",
175    feature = "stm32f098",
176))]
177usart_pins! {
178    USART2 => {
179        tx => [gpiod::PD5<Alternate<AF0>>],
180        rx => [gpiod::PD6<Alternate<AF0>>],
181    }
182}
183
184#[cfg(any(
185    feature = "stm32f030xc",
186    feature = "stm32f070xb",
187    feature = "stm32f071",
188    feature = "stm32f072",
189    feature = "stm32f078",
190    feature = "stm32f091",
191    feature = "stm32f098",
192))]
193usart_pins! {
194    USART3 => {
195        // According to the datasheet PB10 is both tx and rx, but in stm32cubemx it's only tx
196        tx => [gpiob::PB10<Alternate<AF4>>, gpioc::PC4<Alternate<AF1>>, gpioc::PC10<Alternate<AF1>>],
197        rx => [gpiob::PB11<Alternate<AF4>>, gpioc::PC5<Alternate<AF1>>, gpioc::PC11<Alternate<AF1>>],
198    }
199    USART4 => {
200        tx => [gpioa::PA0<Alternate<AF4>>, gpioc::PC10<Alternate<AF0>>],
201        rx => [gpioa::PA1<Alternate<AF4>>, gpioc::PC11<Alternate<AF0>>],
202    }
203}
204#[cfg(any(
205    feature = "stm32f071",
206    feature = "stm32f072",
207    feature = "stm32f078",
208    feature = "stm32f091",
209    feature = "stm32f098",
210))]
211usart_pins! {
212    USART3 => {
213        tx => [gpiod::PD8<Alternate<AF0>>],
214        rx => [gpiod::PD9<Alternate<AF0>>],
215    }
216}
217// TODO: The ST SVD files are missing the entire PE enable register.
218//       Re-enable as soon as this gets fixed.
219// #[cfg(any(feature = "stm32f091", feature = "stm32f098"))]
220// usart_pins! {
221//     USART4 => {
222//         tx => [gpioe::PE8<Alternate<AF1>>],
223//         rx => [gpioe::PE9<Alternate<AF1>>],
224//     }
225// }
226
227#[cfg(any(feature = "stm32f030xc", feature = "stm32f091", feature = "stm32f098"))]
228usart_pins! {
229    USART5 => {
230        tx => [gpioc::PC12<Alternate<AF2>>],
231        rx => [gpiod::PD2<Alternate<AF2>>],
232    }
233    USART6 => {
234        tx => [gpioa::PA4<Alternate<AF5>>, gpioc::PC0<Alternate<AF2>>],
235        rx => [gpioa::PA5<Alternate<AF5>>, gpioc::PC1<Alternate<AF2>>],
236    }
237}
238#[cfg(any(feature = "stm32f030xc", feature = "stm32f091"))]
239usart_pins! {
240    USART5 => {
241        tx => [gpiob::PB3<Alternate<AF4>>],
242        rx => [gpiob::PB4<Alternate<AF4>>],
243    }
244}
245// TODO: The ST SVD files are missing the entire PE enable register.
246//       Re-enable as soon as this gets fixed.
247#[cfg(any(feature = "stm32f091", feature = "stm32f098"))]
248usart_pins! {
249    // USART5 => {
250    //     tx => [gpioe::PE10<Alternate<AF1>>],
251    //     rx => [gpioe::PE11<Alternate<AF1>>],
252    // }
253    USART6 => {
254        tx => [gpiof::PF9<Alternate<AF1>>],
255        rx => [gpiof::PF10<Alternate<AF1>>],
256    }
257}
258
259/// Serial abstraction
260pub struct Serial<USART, TXPIN, RXPIN> {
261    usart: USART,
262    pins: (TXPIN, RXPIN),
263}
264
265// Common register
266type SerialRegisterBlock = crate::pac::usart1::RegisterBlock;
267
268/// Serial receiver
269pub struct Rx<USART> {
270    usart: *const SerialRegisterBlock,
271    _instance: PhantomData<USART>,
272}
273
274// NOTE(unsafe) Required to allow protected shared access in handlers
275unsafe impl<USART> Send for Rx<USART> {}
276
277/// Serial transmitter
278pub struct Tx<USART> {
279    usart: *const SerialRegisterBlock,
280    _instance: PhantomData<USART>,
281}
282
283// NOTE(unsafe) Required to allow protected shared access in handlers
284unsafe impl<USART> Send for Tx<USART> {}
285
286macro_rules! usart {
287    ($($USART:ident: ($usart:ident, $usarttx:ident, $usartrx:ident, $usartXen:ident, $apbenr:ident),)+) => {
288        $(
289            use crate::pac::$USART;
290            impl<TXPIN, RXPIN> Serial<$USART, TXPIN, RXPIN>
291            where
292                TXPIN: TxPin<$USART>,
293                RXPIN: RxPin<$USART>,
294            {
295                /// Creates a new serial instance
296                pub fn $usart(usart: $USART, pins: (TXPIN, RXPIN), baud_rate: Bps, rcc: &mut Rcc) -> Self
297                {
298                    let mut serial = Serial { usart, pins };
299                    serial.configure(baud_rate, rcc);
300                    // Enable transmission and receiving
301                    serial.usart.cr1.modify(|_, w| w.te().set_bit().re().set_bit().ue().set_bit());
302                    serial
303                }
304            }
305
306            impl<TXPIN> Serial<$USART, TXPIN, ()>
307            where
308                TXPIN: TxPin<$USART>,
309            {
310                /// Creates a new tx-only serial instance
311                pub fn $usarttx(usart: $USART, txpin: TXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self
312                {
313                    let rxpin = ();
314                    let mut serial = Serial { usart, pins: (txpin, rxpin) };
315                    serial.configure(baud_rate, rcc);
316                    // Enable transmission
317                    serial.usart.cr1.modify(|_, w| w.te().set_bit().ue().set_bit());
318                    serial
319                }
320            }
321
322            impl<RXPIN> Serial<$USART, (), RXPIN>
323            where
324                RXPIN: RxPin<$USART>,
325            {
326                /// Creates a new rx-only serial instance
327                pub fn $usartrx(usart: $USART, rxpin: RXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self
328                {
329                    let txpin = ();
330                    let mut serial = Serial { usart, pins: (txpin, rxpin) };
331                    serial.configure(baud_rate, rcc);
332                    // Enable receiving
333                    serial.usart.cr1.modify(|_, w| w.re().set_bit().ue().set_bit());
334                    serial
335                }
336            }
337
338            impl<TXPIN, RXPIN> Serial<$USART, TXPIN, RXPIN> {
339                fn configure(&mut self, baud_rate: Bps, rcc: &mut Rcc) {
340                    // Enable clock for USART
341                    rcc.regs.$apbenr.modify(|_, w| w.$usartXen().set_bit());
342
343                    // Calculate correct baudrate divisor on the fly
344                    let brr = rcc.clocks.pclk().0 / baud_rate.0;
345                    self.usart.brr.write(|w| unsafe { w.bits(brr) });
346
347                    // Reset other registers to disable advanced USART features
348                    self.usart.cr2.reset();
349                    self.usart.cr3.reset();
350                }
351
352                /// Starts listening for an interrupt event
353                pub fn listen(&mut self, event: Event) {
354                    match event {
355                        Event::Rxne => {
356                            self.usart.cr1.modify(|_, w| w.rxneie().set_bit())
357                        },
358                        Event::Txe => {
359                            self.usart.cr1.modify(|_, w| w.txeie().set_bit())
360                        },
361                        Event::Idle => {
362                            self.usart.cr1.modify(|_, w| w.idleie().set_bit())
363                        },
364                    }
365                }
366
367                /// Stop listening for an interrupt event
368                pub fn unlisten(&mut self, event: Event) {
369                    match event {
370                        Event::Rxne => {
371                            self.usart.cr1.modify(|_, w| w.rxneie().clear_bit())
372                        },
373                        Event::Txe => {
374                            self.usart.cr1.modify(|_, w| w.txeie().clear_bit())
375                        },
376                        Event::Idle => {
377                            self.usart.cr1.modify(|_, w| w.idleie().clear_bit())
378                        },
379                    }
380                }
381            }
382        )+
383    }
384}
385
386usart! {
387    USART1: (usart1, usart1tx, usart1rx, usart1en, apb2enr),
388}
389#[cfg(any(
390    feature = "stm32f030x8",
391    feature = "stm32f030xc",
392    feature = "stm32f042",
393    feature = "stm32f048",
394    feature = "stm32f051",
395    feature = "stm32f058",
396    feature = "stm32f070",
397    feature = "stm32f071",
398    feature = "stm32f072",
399    feature = "stm32f078",
400    feature = "stm32f091",
401    feature = "stm32f098",
402))]
403usart! {
404    USART2: (usart2, usart2tx, usart2rx,usart2en, apb1enr),
405}
406#[cfg(any(
407    feature = "stm32f030xc",
408    feature = "stm32f070xb",
409    feature = "stm32f071",
410    feature = "stm32f072",
411    feature = "stm32f078",
412    feature = "stm32f091",
413    feature = "stm32f098",
414))]
415usart! {
416    USART3: (usart3, usart3tx, usart3rx,usart3en, apb1enr),
417    USART4: (usart4, usart4tx, usart4rx,usart4en, apb1enr),
418}
419#[cfg(any(feature = "stm32f030xc", feature = "stm32f091", feature = "stm32f098"))]
420usart! {
421    USART5: (usart5, usart5tx, usart5rx,usart5en, apb1enr),
422    USART6: (usart6, usart6tx, usart6rx,usart6en, apb2enr),
423}
424
425impl<USART> embedded_hal::serial::Read<u8> for Rx<USART>
426where
427    USART: Deref<Target = SerialRegisterBlock>,
428{
429    type Error = Error;
430
431    /// Tries to read a byte from the uart
432    fn read(&mut self) -> nb::Result<u8, Error> {
433        read(self.usart)
434    }
435}
436
437impl<USART, TXPIN, RXPIN> embedded_hal::serial::Read<u8> for Serial<USART, TXPIN, RXPIN>
438where
439    USART: Deref<Target = SerialRegisterBlock>,
440    RXPIN: RxPin<USART>,
441{
442    type Error = Error;
443
444    /// Tries to read a byte from the uart
445    fn read(&mut self) -> nb::Result<u8, Error> {
446        read(&*self.usart)
447    }
448}
449
450impl<USART> embedded_hal::serial::Write<u8> for Tx<USART>
451where
452    USART: Deref<Target = SerialRegisterBlock>,
453{
454    type Error = Infallible;
455
456    /// Ensures that none of the previously written words are still buffered
457    fn flush(&mut self) -> nb::Result<(), Self::Error> {
458        flush(self.usart)
459    }
460
461    /// Tries to write a byte to the uart
462    /// Fails if the transmit buffer is full
463    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
464        write(self.usart, byte)
465    }
466}
467
468impl<USART, TXPIN, RXPIN> embedded_hal::serial::Write<u8> for Serial<USART, TXPIN, RXPIN>
469where
470    USART: Deref<Target = SerialRegisterBlock>,
471    TXPIN: TxPin<USART>,
472{
473    type Error = Infallible;
474
475    /// Ensures that none of the previously written words are still buffered
476    fn flush(&mut self) -> nb::Result<(), Self::Error> {
477        flush(&*self.usart)
478    }
479
480    /// Tries to write a byte to the uart
481    /// Fails if the transmit buffer is full
482    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
483        write(&*self.usart, byte)
484    }
485}
486
487impl<USART, TXPIN, RXPIN> Serial<USART, TXPIN, RXPIN>
488where
489    USART: Deref<Target = SerialRegisterBlock>,
490{
491    /// Splits the UART Peripheral in a Tx and an Rx part
492    /// This is required for sending/receiving
493    pub fn split(self) -> (Tx<USART>, Rx<USART>)
494    where
495        TXPIN: TxPin<USART>,
496        RXPIN: RxPin<USART>,
497    {
498        (
499            Tx {
500                usart: &*self.usart,
501                _instance: PhantomData,
502            },
503            Rx {
504                usart: &*self.usart,
505                _instance: PhantomData,
506            },
507        )
508    }
509
510    pub fn release(self) -> (USART, (TXPIN, RXPIN)) {
511        (self.usart, self.pins)
512    }
513}
514
515impl<USART> Write for Tx<USART>
516where
517    Tx<USART>: embedded_hal::serial::Write<u8>,
518{
519    fn write_str(&mut self, s: &str) -> Result {
520        s.as_bytes()
521            .iter()
522            .try_for_each(|c| nb::block!(self.write(*c)))
523            .map_err(|_| core::fmt::Error)
524    }
525}
526
527impl<USART, TXPIN, RXPIN> Write for Serial<USART, TXPIN, RXPIN>
528where
529    USART: Deref<Target = SerialRegisterBlock>,
530    TXPIN: TxPin<USART>,
531{
532    fn write_str(&mut self, s: &str) -> Result {
533        s.as_bytes()
534            .iter()
535            .try_for_each(|c| nb::block!(self.write(*c)))
536            .map_err(|_| core::fmt::Error)
537    }
538}
539
540/// Ensures that none of the previously written words are still buffered
541fn flush(usart: *const SerialRegisterBlock) -> nb::Result<(), Infallible> {
542    // NOTE(unsafe) atomic read with no side effects
543    let isr = unsafe { (*usart).isr.read() };
544
545    if isr.tc().bit_is_set() {
546        Ok(())
547    } else {
548        Err(nb::Error::WouldBlock)
549    }
550}
551
552/// Tries to write a byte to the UART
553/// Returns `Err(WouldBlock)` if the transmit buffer is full
554fn write(usart: *const SerialRegisterBlock, byte: u8) -> nb::Result<(), Infallible> {
555    // NOTE(unsafe) atomic read with no side effects
556    let isr = unsafe { (*usart).isr.read() };
557
558    if isr.txe().bit_is_set() {
559        // NOTE(unsafe) atomic write to stateless register
560        unsafe { (*usart).tdr.write(|w| w.tdr().bits(byte as u16)) }
561        Ok(())
562    } else {
563        Err(nb::Error::WouldBlock)
564    }
565}
566
567/// Tries to read a byte from the UART
568fn read(usart: *const SerialRegisterBlock) -> nb::Result<u8, Error> {
569    // NOTE(unsafe) atomic read with no side effects
570    let isr = unsafe { (*usart).isr.read() };
571
572    // NOTE(unsafe) write accessor for atomic writes with no side effects
573    let icr = unsafe { &(*usart).icr };
574
575    if isr.pe().bit_is_set() {
576        icr.write(|w| w.pecf().set_bit());
577        Err(nb::Error::Other(Error::Parity))
578    } else if isr.fe().bit_is_set() {
579        icr.write(|w| w.fecf().set_bit());
580        Err(nb::Error::Other(Error::Framing))
581    } else if isr.nf().bit_is_set() {
582        icr.write(|w| w.ncf().set_bit());
583        Err(nb::Error::Other(Error::Noise))
584    } else if isr.ore().bit_is_set() {
585        icr.write(|w| w.orecf().set_bit());
586        Err(nb::Error::Other(Error::Overrun))
587    } else if isr.rxne().bit_is_set() {
588        Ok(unsafe { (*usart).rdr.read().rdr().bits() as u8 })
589    } else {
590        Err(nb::Error::WouldBlock)
591    }
592}