stm32f7x7_hal/
serial.rs

1//! Serial
2use core::fmt;
3use core::marker::PhantomData;
4use core::ptr;
5
6use embedded_hal::serial;
7use embedded_hal::prelude::*;
8use nb::block;
9
10use crate::hal::serial::Write;
11
12use crate::stm32::{RCC, UART4, UART5, USART1, USART2, USART3, USART6, UART7, UART8};
13
14use crate::gpio::gpioa::{PA0, PA1, PA2, PA3, PA8, PA9, PA10, PA11, PA12, PA15};
15use crate::gpio::gpiob::{PB3, PB4, PB10, PB11, PB12, PB13, PB5, PB6, PB7, PB8, PB9};
16use crate::gpio::gpioc::{PC5, PC10, PC11, PC12, PC6, PC7};
17use crate::gpio::gpiod::{PD0, PD1, PD2, PD5, PD6, PD8, PD9, PD10};
18use crate::gpio::gpioe::{PE0, PE1, PE7, PE8};
19use crate::gpio::gpiof::{PF6, PF7, PF8, PF9};
20use crate::gpio::gpiog::{PG0, PG1, PG11, PG12, PG14, PG9};
21use crate::gpio::gpioh::{PH13, PH14};
22use crate::gpio::{Alternate, AF7, AF8, AF11};
23use crate::rcc::Clocks;
24use crate::time::Bps;
25
26/// Serial error
27#[derive(Debug)]
28pub enum Error {
29    /// Framing error
30    Framing,
31    /// Noise error
32    Noise,
33    /// RX buffer overrun
34    Overrun,
35    /// Parity check error
36    Parity,
37    #[doc(hidden)]
38    _Extensible,
39}
40
41/// Interrupt event
42pub enum Event {
43    /// New data has been received
44    Rxne,
45    /// New data can be sent
46    Txe,
47    /// Idle line state detected
48    Idle,
49}
50
51pub mod config {
52    use crate::time::Bps;
53    use crate::time::U32Ext;
54
55    pub enum WordLength {
56        DataBits8,
57        DataBits9,
58    }
59
60    pub enum Parity {
61        ParityNone,
62        ParityEven,
63        ParityOdd,
64    }
65
66    pub enum StopBits {
67        #[doc = "1 stop bit"]
68        STOP1,
69        #[doc = "0.5 stop bits"]
70        STOP0P5,
71        #[doc = "2 stop bits"]
72        STOP2,
73        #[doc = "1.5 stop bits"]
74        STOP1P5,
75    }
76
77    pub struct Config {
78        pub baudrate: Bps,
79        pub wordlength: WordLength,
80        pub parity: Parity,
81        pub stopbits: StopBits,
82    }
83
84    impl Config {
85        pub fn baudrate(mut self, baudrate: Bps) -> Self {
86            self.baudrate = baudrate;
87            self
88        }
89
90        pub fn parity_none(mut self) -> Self {
91            self.parity = Parity::ParityNone;
92            self
93        }
94
95        pub fn parity_even(mut self) -> Self {
96            self.parity = Parity::ParityEven;
97            self
98        }
99
100        pub fn parity_odd(mut self) -> Self {
101            self.parity = Parity::ParityOdd;
102            self
103        }
104
105        pub fn wordlength_8(mut self) -> Self {
106            self.wordlength = WordLength::DataBits8;
107            self
108        }
109
110        pub fn wordlength_9(mut self) -> Self {
111            self.wordlength = WordLength::DataBits9;
112            self
113        }
114
115        pub fn stopbits(mut self, stopbits: StopBits) -> Self {
116            self.stopbits = stopbits;
117            self
118        }
119    }
120
121    #[derive(Debug)]
122    pub struct InvalidConfig;
123
124    impl Default for Config {
125        fn default() -> Config {
126            let baudrate = 19_200_u32.bps();
127            Config {
128                baudrate,
129                wordlength: WordLength::DataBits8,
130                parity: Parity::ParityNone,
131                stopbits: StopBits::STOP1,
132            }
133        }
134    }
135}
136
137pub trait Pins<USART> {}
138pub trait PinTx<USART> {}
139pub trait PinRx<USART> {}
140
141impl<USART, TX, RX> Pins<USART> for (TX, RX)
142where
143    TX: PinTx<USART>,
144    RX: PinRx<USART>,
145{}
146
147/// A filler type for when the Tx pin is unnecessary
148pub struct NoTx;
149/// A filler type for when the Rx pin is unnecessary
150pub struct NoRx;
151
152impl PinTx<USART1> for NoTx {}
153impl PinRx<USART1> for NoRx {}
154
155impl PinTx<USART1> for PA9<Alternate<AF7>> {}
156impl PinRx<USART1> for PA10<Alternate<AF7>> {}
157impl PinTx<USART1> for PA15<Alternate<AF7>> {}
158impl PinRx<USART1> for PB3<Alternate<AF7>> {}
159impl PinTx<USART1> for PB6<Alternate<AF7>> {}
160impl PinRx<USART1> for PB7<Alternate<AF7>> {}
161
162impl PinTx<USART2> for NoTx {}
163impl PinRx<USART2> for NoRx {}
164
165impl PinTx<USART2> for PA2<Alternate<AF7>> {}
166impl PinRx<USART2> for PA3<Alternate<AF7>> {}
167impl PinTx<USART2> for PD5<Alternate<AF7>> {}
168impl PinRx<USART2> for PD6<Alternate<AF7>> {}
169
170impl PinTx<USART3> for NoTx {}
171impl PinRx<USART3> for NoRx {}
172
173impl PinTx<USART3> for PB10<Alternate<AF7>> {}
174impl PinRx<USART3> for PB11<Alternate<AF7>> {}
175impl PinRx<USART3> for PC5<Alternate<AF7>> {}
176impl PinTx<USART3> for PC10<Alternate<AF7>> {}
177impl PinRx<USART3> for PC11<Alternate<AF7>> {}
178impl PinTx<USART3> for PD8<Alternate<AF7>> {}
179impl PinRx<USART3> for PD9<Alternate<AF7>> {}
180
181impl PinTx<UART4> for NoTx {}
182impl PinRx<UART4> for NoRx {}
183
184impl PinTx<UART4> for PA0<Alternate<AF8>> {}
185impl PinRx<UART4> for PA1<Alternate<AF8>> {}
186impl PinTx<UART4> for PA12<Alternate<AF11>> {}
187impl PinRx<UART4> for PA11<Alternate<AF11>> {}
188impl PinTx<UART4> for PC10<Alternate<AF8>> {}
189impl PinRx<UART4> for PC11<Alternate<AF8>> {}
190impl PinTx<UART4> for PD1<Alternate<AF11>> {}
191impl PinRx<UART4> for PD0<Alternate<AF11>> {}
192impl PinTx<UART4> for PD10<Alternate<AF8>> {}
193
194impl PinTx<UART5> for NoTx {}
195impl PinRx<UART5> for NoRx {}
196
197impl PinTx<UART5> for PB6<Alternate<AF11>> {}
198impl PinRx<UART5> for PB5<Alternate<AF11>> {}
199impl PinTx<UART5> for PB9<Alternate<AF11>> {}
200impl PinRx<UART5> for PB8<Alternate<AF11>> {}
201impl PinTx<UART5> for PB13<Alternate<AF11>> {}
202impl PinRx<UART5> for PB12<Alternate<AF11>> {}
203impl PinTx<UART5> for PC12<Alternate<AF8>> {}
204impl PinRx<UART5> for PD2<Alternate<AF8>> {}
205impl PinTx<UART5> for PE8<Alternate<AF8>> {}
206impl PinRx<UART5> for PE7<Alternate<AF8>> {}
207
208impl PinTx<USART6> for NoTx {}
209impl PinRx<USART6> for NoRx {}
210
211impl PinTx<USART6> for PA11<Alternate<AF8>> {}
212impl PinRx<USART6> for PA12<Alternate<AF8>> {}
213impl PinTx<USART6> for PC6<Alternate<AF8>> {}
214impl PinRx<USART6> for PC7<Alternate<AF8>> {}
215impl PinTx<USART6> for PG14<Alternate<AF8>> {}
216impl PinRx<USART6> for PG9<Alternate<AF8>> {}
217
218impl PinTx<UART7> for NoTx {}
219impl PinRx<UART7> for NoRx {}
220
221impl PinTx<UART7> for PA15<Alternate<AF8>> {}
222impl PinRx<UART7> for PA8<Alternate<AF8>> {}
223impl PinTx<UART7> for PB4<Alternate<AF8>> {}
224impl PinRx<UART7> for PB3<Alternate<AF8>> {}
225impl PinTx<UART7> for PE8<Alternate<AF8>> {}
226impl PinRx<UART7> for PE7<Alternate<AF8>> {}
227impl PinTx<UART7> for PF7<Alternate<AF8>> {}
228impl PinRx<UART7> for PF6<Alternate<AF8>> {}
229
230impl PinTx<UART8> for NoTx {}
231impl PinRx<UART8> for NoRx {}
232
233impl PinTx<UART8> for PE1<Alternate<AF8>> {}
234impl PinRx<UART8> for PE0<Alternate<AF8>> {}
235impl PinTx<UART8> for PF9<Alternate<AF8>> {}
236impl PinRx<UART8> for PF8<Alternate<AF8>> {}
237
238/// Serial abstraction
239pub struct Serial<USART, PINS> {
240    usart: USART,
241    pins: PINS,
242}
243
244/// Serial receiver
245pub struct Rx<USART> {
246    _usart: PhantomData<USART>,
247}
248
249/// Serial transmitter
250pub struct Tx<USART> {
251    _usart: PhantomData<USART>,
252}
253
254macro_rules! halUsartImpl {
255    ($(
256        $USARTX:ident: ($usartX:ident, $apbXenr:ident, $usartXen:ident,  $pclkX:ident),
257    )+) => {
258        $(
259            impl<PINS> Serial<$USARTX, PINS> {
260                pub fn $usartX(
261                    usart: $USARTX,
262                    pins: PINS,
263                    config: config::Config,
264                    clocks: Clocks,
265                ) -> Result<Self, config::InvalidConfig>
266                where
267                    PINS: Pins<$USARTX>,
268                {
269                    use self::config::*;
270
271                    // NOTE(unsafe) This executes only during initialisation
272                    let rcc = unsafe { &(*RCC::ptr()) };
273
274                    // Enable clock for USART
275                    rcc.$apbXenr.modify(|_, w| w.$usartXen().set_bit());
276
277                    // Calculate correct baudrate divisor on the fly
278                    let div = (clocks.$pclkX().0 + config.baudrate.0 / 2)
279                        / config.baudrate.0;
280                    usart.brr.write(|w| unsafe { w.bits(div) });
281
282                    // Reset other registers to disable advanced USART features
283                    usart.cr2.reset();
284                    usart.cr3.reset();
285
286                    // Enable transmission and receiving
287                    // and configure frame
288                    usart.cr1.write(|w| {
289                        w.ue()
290                            .set_bit()
291                            .te()
292                            .set_bit()
293                            .re()
294                            .set_bit()
295                            .m0()
296                            .bit(match config.wordlength {
297                                WordLength::DataBits8 => false,
298                                WordLength::DataBits9 => true,
299                            }).pce()
300                            .bit(match config.parity {
301                                Parity::ParityNone => false,
302                                _ => true,
303                            }).ps()
304                            .bit(match config.parity {
305                                Parity::ParityOdd => true,
306                                _ => false,
307                            })
308                    });
309
310                    Ok(Serial { usart, pins }.config_stop(config))
311                }
312
313                /// Starts listening for an interrupt event
314                pub fn listen(&mut self, event: Event) {
315                    match event {
316                        Event::Rxne => {
317                            self.usart.cr1.modify(|_, w| w.rxneie().set_bit())
318                        },
319                        Event::Txe => {
320                            self.usart.cr1.modify(|_, w| w.txeie().set_bit())
321                        },
322                        Event::Idle => {
323                            self.usart.cr1.modify(|_, w| w.idleie().set_bit())
324                        },
325                    }
326                }
327
328                /// Stop listening for an interrupt event
329                pub fn unlisten(&mut self, event: Event) {
330                    match event {
331                        Event::Rxne => {
332                            self.usart.cr1.modify(|_, w| w.rxneie().clear_bit())
333                        },
334                        Event::Txe => {
335                            self.usart.cr1.modify(|_, w| w.txeie().clear_bit())
336                        },
337                        Event::Idle => {
338                            self.usart.cr1.modify(|_, w| w.idleie().clear_bit())
339                        },
340                    }
341                }
342
343                /// Return true if the line idle status is set
344                pub fn is_idle(& self) -> bool {
345                    unsafe { (*$USARTX::ptr()).isr.read().idle().bit_is_set() }
346                }
347
348                /// Return true if the tx register is empty (and can accept data)
349                pub fn is_txe(& self) -> bool {
350                    unsafe { (*$USARTX::ptr()).isr.read().txe().bit_is_set() }
351                }
352
353                /// Return true if the rx register is not empty (and can be read)
354                pub fn is_rxne(& self) -> bool {
355                    unsafe { (*$USARTX::ptr()).isr.read().rxne().bit_is_set() }
356                }
357
358                pub fn split(self) -> (Tx<$USARTX>, Rx<$USARTX>) {
359                    (
360                        Tx {
361                            _usart: PhantomData,
362                        },
363                        Rx {
364                            _usart: PhantomData,
365                        },
366                    )
367                }
368                pub fn release(self) -> ($USARTX, PINS) {
369                    (self.usart, self.pins)
370                }
371            }
372
373            impl<PINS> serial::Read<u8> for Serial<$USARTX, PINS> {
374                type Error = Error;
375
376                fn read(&mut self) -> nb::Result<u8, Error> {
377                    let mut rx: Rx<$USARTX> = Rx {
378                        _usart: PhantomData,
379                    };
380                    rx.read()
381                }
382            }
383
384            impl serial::Read<u8> for Rx<$USARTX> {
385                type Error = Error;
386
387                fn read(&mut self) -> nb::Result<u8, Error> {
388                    // NOTE(unsafe) atomic read with no side effects
389                    let sr = unsafe { (*$USARTX::ptr()).isr.read() };
390
391                    // Any error requires the dr to be read to clear
392                    if sr.pe().bit_is_set()
393                        || sr.fe().bit_is_set()
394                        || sr.nf().bit_is_set()
395                        || sr.ore().bit_is_set()
396                    {
397                        unsafe { (*$USARTX::ptr()).rdr.read() };
398                    }
399
400                    Err(if sr.pe().bit_is_set() {
401                        nb::Error::Other(Error::Parity)
402                    } else if sr.fe().bit_is_set() {
403                        nb::Error::Other(Error::Framing)
404                    } else if sr.nf().bit_is_set() {
405                        nb::Error::Other(Error::Noise)
406                    } else if sr.ore().bit_is_set() {
407                        nb::Error::Other(Error::Overrun)
408                    } else if sr.rxne().bit_is_set() {
409                        // NOTE(read_volatile) see `write_volatile` below
410                        return Ok(unsafe { ptr::read_volatile(&(*$USARTX::ptr()).rdr as *const _ as *const _) });
411                    } else {
412                        nb::Error::WouldBlock
413                    })
414                }
415            }
416
417            impl<PINS> serial::Write<u8> for Serial<$USARTX, PINS> {
418                type Error = Error;
419
420                fn flush(&mut self) -> nb::Result<(), Self::Error> {
421                    let mut tx: Tx<$USARTX> = Tx {
422                        _usart: PhantomData,
423                    };
424                    tx.flush()
425                }
426
427                fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
428                    let mut tx: Tx<$USARTX> = Tx {
429                        _usart: PhantomData,
430                    };
431                    tx.write(byte)
432                }
433            }
434
435            impl serial::Write<u8> for Tx<$USARTX> {
436                type Error = Error;
437
438                fn flush(&mut self) -> nb::Result<(), Self::Error> {
439                    // NOTE(unsafe) atomic read with no side effects
440                    let sr = unsafe { (*$USARTX::ptr()).isr.read() };
441
442                    if sr.tc().bit_is_set() {
443                        Ok(())
444                    } else {
445                        Err(nb::Error::WouldBlock)
446                    }
447                }
448
449                fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
450                    // NOTE(unsafe) atomic read with no side effects
451                    let sr = unsafe { (*$USARTX::ptr()).isr.read() };
452
453                    if sr.txe().bit_is_set() {
454                        // NOTE(unsafe) atomic write to stateless register
455                        // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
456                        unsafe { ptr::write_volatile(&(*$USARTX::ptr()).tdr as *const _ as *mut _, byte) }
457                        Ok(())
458                    } else {
459                        Err(nb::Error::WouldBlock)
460                    }
461                }
462            }
463        )+
464    }
465}
466
467macro_rules! halUsart {
468    ($(
469        $USARTX:ident: ($usartX:ident, $apbXenr:ident, $usartXen:ident, $pclkX:ident),
470    )+) => {
471        $(
472        impl<PINS> Serial<$USARTX, PINS> {
473            fn config_stop(self, config: config::Config) -> Self {
474                use crate::stm32::usart1::cr2::STOPW;
475                use self::config::*;
476
477                self.usart.cr2.write(|w| {
478                    w.stop().variant(match config.stopbits {
479                        StopBits::STOP0P5 => STOPW::STOP0P5,
480                        StopBits::STOP1 => STOPW::STOP1,
481                        StopBits::STOP1P5 => STOPW::STOP1P5,
482                        StopBits::STOP2 => STOPW::STOP2,
483                    })
484                });
485                self
486            }
487        }
488        )+
489
490        halUsartImpl! {
491            $( $USARTX: ($usartX, $apbXenr, $usartXen, $pclkX), )+
492        }
493    }
494}
495
496macro_rules! halUart {
497    ($(
498        $USARTX:ident: ($usartX:ident, $apbXenr:ident, $usartXen:ident, $pclkX:ident),
499    )+) => {
500        $(
501        impl<PINS> Serial<$USARTX, PINS> {
502            fn config_stop(self, config: config::Config) -> Self {
503                use crate::stm32::usart1::cr2::STOPW;
504                use self::config::*;
505
506                self.usart.cr2.write(|w| {
507                    w.stop().variant(match config.stopbits {
508                        StopBits::STOP0P5 => STOPW::STOP0P5,
509                        StopBits::STOP1 => STOPW::STOP1,
510                        StopBits::STOP1P5 => STOPW::STOP1P5,
511                        StopBits::STOP2 => STOPW::STOP2,
512                    })
513                });
514                self
515            }
516        }
517        )+
518
519        halUsartImpl! {
520            $( $USARTX: ($usartX, $apbXenr, $usartXen, $pclkX), )+
521        }
522    }
523}
524
525halUsart! {
526    USART1: (usart1, apb2enr, usart1en, pclk2),
527    USART2: (usart2, apb1enr, usart2en, pclk1),
528    USART6: (usart6, apb2enr, usart6en, pclk2),
529}
530
531
532halUsart! {
533    USART3: (usart3, apb1enr, usart3en, pclk1),
534}
535
536halUart! {
537    UART4: (uart4, apb1enr, uart4en, pclk1),
538    UART5: (uart5, apb1enr, uart5en, pclk1),
539}
540
541halUsart! {
542    UART7: (uart7, apb1enr, uart7en, pclk1),
543    UART8: (uart8, apb1enr, uart8en, pclk1),
544}
545
546
547impl<USART> fmt::Write for Tx<USART>
548where
549    Tx<USART>: serial::Write<u8>,
550{
551    fn write_str(&mut self, s: &str) -> fmt::Result {
552        let _ = s
553            .as_bytes()
554            .iter()
555            .map(|c| block!(self.write(*c)))
556            .last();
557        Ok(())
558    }
559}
560