stm32l1xx_hal/
serial.rs

1use core::fmt;
2use core::marker::PhantomData;
3use core::ptr;
4
5use crate::gpio::gpioa::{PA10, PA2, PA3, PA9};
6use crate::gpio::gpiob::{PB10, PB11};
7use crate::gpio::{AltMode, Floating, Input};
8use crate::rcc::Rcc;
9use crate::stm32::{USART1, USART2, USART3};
10use hal;
11use hal::prelude::*;
12use nb::block;
13
14/// Serial error
15#[derive(Debug)]
16pub enum Error {
17    /// Framing error
18    Framing,
19    /// Noise error
20    Noise,
21    /// RX buffer overrun
22    Overrun,
23    /// Parity check error
24    Parity,
25    #[doc(hidden)]
26    _Extensible,
27}
28
29/// Interrupt event
30pub enum Event {
31    /// New data has been received
32    Rxne,
33    /// New data can be sent
34    Txe,
35    /// Idle line state detected
36    Idle,
37}
38
39use crate::time::Bps;
40use crate::time::U32Ext;
41
42pub enum WordLength {
43    DataBits8,
44    DataBits9,
45}
46
47pub enum Parity {
48    ParityNone,
49    ParityEven,
50    ParityOdd,
51}
52
53pub enum StopBits {
54    #[doc = "1 stop bit"]
55    STOP1,
56    #[doc = "0.5 stop bits"]
57    STOP0P5,
58    #[doc = "2 stop bits"]
59    STOP2,
60    #[doc = "1.5 stop bits"]
61    STOP1P5,
62}
63
64pub struct Config {
65    pub baudrate: Bps,
66    pub wordlength: WordLength,
67    pub parity: Parity,
68    pub stopbits: StopBits,
69}
70
71impl Config {
72    pub fn baudrate(mut self, baudrate: Bps) -> Self {
73        self.baudrate = baudrate;
74        self
75    }
76
77    pub fn parity_none(mut self) -> Self {
78        self.parity = Parity::ParityNone;
79        self
80    }
81
82    pub fn parity_even(mut self) -> Self {
83        self.parity = Parity::ParityEven;
84        self
85    }
86
87    pub fn parity_odd(mut self) -> Self {
88        self.parity = Parity::ParityOdd;
89        self
90    }
91
92    pub fn wordlength_8(mut self) -> Self {
93        self.wordlength = WordLength::DataBits8;
94        self
95    }
96
97    pub fn wordlength_9(mut self) -> Self {
98        self.wordlength = WordLength::DataBits9;
99        self
100    }
101
102    pub fn stopbits(mut self, stopbits: StopBits) -> Self {
103        self.stopbits = stopbits;
104        self
105    }
106}
107
108#[derive(Debug)]
109pub struct InvalidConfig;
110
111impl Default for Config {
112    fn default() -> Config {
113        let baudrate = 19_200_u32.bps();
114        Config {
115            baudrate,
116            wordlength: WordLength::DataBits8,
117            parity: Parity::ParityNone,
118            stopbits: StopBits::STOP1,
119        }
120    }
121}
122
123pub trait Pins<USART> {
124    fn setup(&self);
125}
126
127impl Pins<USART1> for (PA9<Input<Floating>>, PA10<Input<Floating>>) {
128    fn setup(&self) {
129        self.0.set_alt_mode(AltMode::USART1_3);
130        self.1.set_alt_mode(AltMode::USART1_3);
131    }
132}
133
134impl Pins<USART2> for (PA2<Input<Floating>>, PA3<Input<Floating>>) {
135    fn setup(&self) {
136        self.0.set_alt_mode(AltMode::USART1_3);
137        self.1.set_alt_mode(AltMode::USART1_3);
138    }
139}
140
141impl Pins<USART3> for (PB10<Input<Floating>>, PB11<Input<Floating>>) {
142    fn setup(&self) {
143        self.0.set_alt_mode(AltMode::USART1_3);
144        self.1.set_alt_mode(AltMode::USART1_3);
145    }
146}
147
148/// Serial abstraction
149pub struct Serial<USART> {
150    usart: USART,
151    rx: Rx<USART>,
152    tx: Tx<USART>,
153}
154
155/// Serial receiver
156pub struct Rx<USART> {
157    _usart: PhantomData<USART>,
158}
159
160/// Serial transmitter
161pub struct Tx<USART> {
162    _usart: PhantomData<USART>,
163}
164
165pub trait SerialExt<USART, PINS> {
166    fn usart(
167        self,
168        pins: PINS,
169        config: Config,
170        rcc: &mut Rcc,
171    ) -> Result<Serial<USART>, InvalidConfig>;
172}
173
174macro_rules! usart {
175    ($(
176        $USARTX:ident: ($usartX:ident, $apbXenr:ident, $usartXen:ident, $pclkX:ident, $SerialExt:ident),
177    )+) => {
178        $(
179            impl<PINS> SerialExt<$USARTX, PINS> for $USARTX
180                where
181                    PINS: Pins<$USARTX>,
182            {
183                fn usart(self, pins: PINS, config: Config, rcc: &mut Rcc) -> Result<Serial<$USARTX>, InvalidConfig> {
184                    Serial::$usartX(self, pins, config, rcc)
185                }
186            }
187
188            impl Serial<$USARTX> {
189                pub fn $usartX<PINS>(
190                    usart: $USARTX,
191                    pins: PINS,
192                    config: Config,
193                    rcc: &mut Rcc,
194                ) -> Result<Self, InvalidConfig>
195                where
196                    PINS: Pins<$USARTX>,
197                {
198                    pins.setup();
199
200                    // Enable clock for USART
201                    rcc.rb.$apbXenr.modify(|_, w| w.$usartXen().set_bit());
202
203                    // Calculate correct baudrate divisor on the fly
204                    let div = (rcc.clocks.$pclkX().0 * 25) / (4 * config.baudrate.0);
205                    let mantissa = div / 100;
206                    let fraction = ((div - mantissa * 100) * 16 + 50) / 100;
207                    usart
208                        .brr
209                        .write(|w| unsafe { w.bits(mantissa << 4 | fraction) });
210
211                    // Reset other registers to disable advanced USART features
212                    usart.cr2.reset();
213                    usart.cr3.reset();
214
215                    // Enable transmission and receiving
216                    // and configure frame
217                    usart.cr1.write(|w| {
218                        w.ue()
219                            .set_bit()
220                            .te()
221                            .set_bit()
222                            .re()
223                            .set_bit()
224                            .m()
225                            .bit(match config.wordlength {
226                                WordLength::DataBits8 => false,
227                                WordLength::DataBits9 => true,
228                            }).pce()
229                            .bit(match config.parity {
230                                Parity::ParityNone => false,
231                                _ => true,
232                            }).ps()
233                            .bit(match config.parity {
234                                Parity::ParityOdd => true,
235                                _ => false,
236                            })
237                    });
238
239                    usart.cr2.write(|w| unsafe {
240                        w.stop().bits(match config.stopbits {
241                            StopBits::STOP1 => 0b00,
242                            StopBits::STOP0P5 => 0b01,
243                            StopBits::STOP2 => 0b10,
244                            StopBits::STOP1P5 => 0b11,
245                        })
246                    });
247                    Ok(Serial {
248                        usart,
249                        tx: Tx { _usart: PhantomData },
250                        rx: Rx { _usart: PhantomData },
251                    })
252                }
253
254                /// Starts listening for an interrupt event
255                pub fn listen(&mut self, event: Event) {
256                    match event {
257                        Event::Rxne => {
258                            self.usart.cr1.modify(|_, w| w.rxneie().set_bit())
259                        },
260                        Event::Txe => {
261                            self.usart.cr1.modify(|_, w| w.txeie().set_bit())
262                        },
263                        Event::Idle => {
264                            self.usart.cr1.modify(|_, w| w.idleie().set_bit())
265                        },
266                    }
267                }
268
269                /// Stop listening for an interrupt event
270                pub fn unlisten(&mut self, event: Event) {
271                    match event {
272                        Event::Rxne => {
273                            self.usart.cr1.modify(|_, w| w.rxneie().clear_bit())
274                        },
275                        Event::Txe => {
276                            self.usart.cr1.modify(|_, w| w.txeie().clear_bit())
277                        },
278                        Event::Idle => {
279                            self.usart.cr1.modify(|_, w| w.idleie().clear_bit())
280                        },
281                    }
282                }
283
284                /// Clears interrupt flag
285                pub fn clear_irq(&mut self, event: Event) {
286                    if let Event::Rxne = event {
287                       self.usart.sr.modify(|_, w| w.rxne().clear_bit())
288                    }
289                }
290
291                pub fn split(self) -> (Tx<$USARTX>, Rx<$USARTX>) {
292                    (self.tx, self.rx)
293                }
294
295                pub fn release(self) -> $USARTX {
296                    self.usart
297                }
298            }
299
300            impl hal::serial::Read<u8> for Serial<$USARTX> {
301                type Error = Error;
302
303                fn read(&mut self) -> nb::Result<u8, Error> {
304                    self.rx.read()
305                }
306            }
307
308             impl hal::serial::Write<u8> for  Serial<$USARTX> {
309                type Error = Error;
310
311                fn flush(&mut self) -> nb::Result<(), Self::Error> {
312                    self.tx.flush()
313                }
314
315                fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
316                    self.tx.write(byte)
317                }
318            }
319
320            impl hal::serial::Read<u8> for Rx<$USARTX> {
321                type Error = Error;
322
323                fn read(&mut self) -> nb::Result<u8, Error> {
324                    // NOTE(unsafe) atomic read with no side effects
325                    let sr = unsafe { (*$USARTX::ptr()).sr.read() };
326
327                    Err(if sr.pe().bit_is_set() {
328                        nb::Error::Other(Error::Parity)
329                    } else if sr.fe().bit_is_set() {
330                        nb::Error::Other(Error::Framing)
331                    } else if sr.nf().bit_is_set() {
332                        nb::Error::Other(Error::Noise)
333                    } else if sr.ore().bit_is_set() {
334                        nb::Error::Other(Error::Overrun)
335                    } else if sr.rxne().bit_is_set() {
336                        // NOTE(read_volatile) see `write_volatile` below
337                        return Ok(unsafe { ptr::read_volatile(&(*$USARTX::ptr()).dr as *const _ as *const _) });
338                    } else {
339                        nb::Error::WouldBlock
340                    })
341                }
342            }
343
344            impl hal::serial::Write<u8> for Tx<$USARTX> {
345                type Error = Error;
346
347                fn flush(&mut self) -> nb::Result<(), Self::Error> {
348                    // NOTE(unsafe) atomic read with no side effects
349                    let sr = unsafe { (*$USARTX::ptr()).sr.read() };
350
351                    if sr.tc().bit_is_set() {
352                        Ok(())
353                    } else {
354                        Err(nb::Error::WouldBlock)
355                    }
356                }
357
358                fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
359                    // NOTE(unsafe) atomic read with no side effects
360                    let sr = unsafe { (*$USARTX::ptr()).sr.read() };
361
362                    if sr.txe().bit_is_set() {
363                        // NOTE(unsafe) atomic write to stateless register
364                        // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
365                        unsafe { ptr::write_volatile(&(*$USARTX::ptr()).dr as *const _ as *mut _, byte) }
366                        Ok(())
367                    } else {
368                        Err(nb::Error::WouldBlock)
369                    }
370                }
371            }
372        )+
373    }
374}
375
376usart! {
377    USART1: (usart1, apb2enr, usart1en, apb2_clk, Serial1Ext),
378    USART2: (usart2, apb1enr, usart2en, apb1_clk, Serial2Ext),
379    USART3: (usart3, apb1enr, usart3en, apb1_clk, Serial3Ext),
380}
381
382impl<USART> fmt::Write for Serial<USART>
383where
384    Serial<USART>: hal::serial::Write<u8>,
385{
386    fn write_str(&mut self, s: &str) -> fmt::Result {
387        let _ = s
388            .as_bytes()
389            .into_iter()
390            .map(|c| block!(self.write(*c)))
391            .last();
392        Ok(())
393    }
394}
395
396impl<USART> fmt::Write for Tx<USART>
397where
398    Tx<USART>: hal::serial::Write<u8>,
399{
400    fn write_str(&mut self, s: &str) -> fmt::Result {
401        let _ = s
402            .as_bytes()
403            .into_iter()
404            .map(|c| block!(self.write(*c)))
405            .last();
406        Ok(())
407    }
408}