stm32f042_hal/
serial.rs

1use core::fmt::{Result, Write};
2use core::marker::PhantomData;
3use core::ptr;
4
5use hal;
6use hal::prelude::*;
7use nb;
8use void::Void;
9
10use stm32::{RCC, USART1, USART2};
11
12use gpio::gpioa::{PA10, PA14, PA15, PA2, PA3, PA9};
13use gpio::gpiob::{PB6, PB7};
14use gpio::{Alternate, AF0, AF1};
15use rcc::Clocks;
16use time::Bps;
17
18/// Interrupt event
19pub enum Event {
20    /// New data has been received
21    Rxne,
22    /// New data can be sent
23    Txe,
24}
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
41pub trait Pins<USART> {}
42
43impl Pins<USART1> for (PA9<Alternate<AF1>>, PA10<Alternate<AF1>>) {}
44impl Pins<USART1> for (PB6<Alternate<AF0>>, PB7<Alternate<AF0>>) {}
45impl Pins<USART1> for (PA9<Alternate<AF1>>, PB7<Alternate<AF0>>) {}
46impl Pins<USART1> for (PB6<Alternate<AF0>>, PA10<Alternate<AF1>>) {}
47
48impl Pins<USART2> for (PA2<Alternate<AF1>>, PA3<Alternate<AF1>>) {}
49impl Pins<USART2> for (PA2<Alternate<AF1>>, PA15<Alternate<AF1>>) {}
50impl Pins<USART2> for (PA14<Alternate<AF1>>, PA15<Alternate<AF1>>) {}
51impl Pins<USART2> for (PA14<Alternate<AF1>>, PA3<Alternate<AF1>>) {}
52
53/// Serial abstraction
54pub struct Serial<USART, PINS> {
55    usart: USART,
56    pins: PINS,
57}
58
59/// Serial receiver
60pub struct Rx<USART> {
61    _usart: PhantomData<USART>,
62}
63
64/// Serial transmitter
65pub struct Tx<USART> {
66    _usart: PhantomData<USART>,
67}
68
69/// USART1
70impl<PINS> Serial<USART1, PINS> {
71    pub fn usart1(usart: USART1, pins: PINS, baud_rate: Bps, clocks: Clocks) -> Self
72    where
73        PINS: Pins<USART1>,
74    {
75        // NOTE(unsafe) This executes only during initialisation
76        let rcc = unsafe { &(*RCC::ptr()) };
77
78        /* Enable clock for USART */
79        rcc.apb2enr.modify(|_, w| w.usart1en().set_bit());
80
81        // Calculate correct baudrate divisor on the fly
82        let brr = clocks.pclk().0 / baud_rate.0;
83        usart.brr.write(|w| unsafe { w.bits(brr) });
84
85        /* Reset other registers to disable advanced USART features */
86        usart.cr2.reset();
87        usart.cr3.reset();
88
89        /* Enable transmission and receiving */
90        usart.cr1.modify(|_, w| unsafe { w.bits(0xD) });
91
92        Serial { usart, pins }
93    }
94
95    pub fn split(self) -> (Tx<USART1>, Rx<USART1>) {
96        (
97            Tx {
98                _usart: PhantomData,
99            },
100            Rx {
101                _usart: PhantomData,
102            },
103        )
104    }
105    pub fn release(self) -> (USART1, PINS) {
106        (self.usart, self.pins)
107    }
108}
109
110impl hal::serial::Read<u8> for Rx<USART1> {
111    type Error = Error;
112
113    fn read(&mut self) -> nb::Result<u8, Error> {
114        // NOTE(unsafe) atomic read with no side effects
115        let isr = unsafe { (*USART1::ptr()).isr.read() };
116
117        Err(if isr.pe().bit_is_set() {
118            nb::Error::Other(Error::Parity)
119        } else if isr.fe().bit_is_set() {
120            nb::Error::Other(Error::Framing)
121        } else if isr.nf().bit_is_set() {
122            nb::Error::Other(Error::Noise)
123        } else if isr.ore().bit_is_set() {
124            nb::Error::Other(Error::Overrun)
125        } else if isr.rxne().bit_is_set() {
126            // NOTE(read_volatile) see `write_volatile` below
127            return Ok(unsafe { ptr::read_volatile(&(*USART1::ptr()).rdr as *const _ as *const _) });
128        } else {
129            nb::Error::WouldBlock
130        })
131    }
132}
133
134impl hal::serial::Write<u8> for Tx<USART1> {
135    type Error = Void;
136
137    fn flush(&mut self) -> nb::Result<(), Self::Error> {
138        // NOTE(unsafe) atomic read with no side effects
139        let isr = unsafe { (*USART1::ptr()).isr.read() };
140
141        if isr.tc().bit_is_set() {
142            Ok(())
143        } else {
144            Err(nb::Error::WouldBlock)
145        }
146    }
147
148    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
149        // NOTE(unsafe) atomic read with no side effects
150        let isr = unsafe { (*USART1::ptr()).isr.read() };
151
152        if isr.txe().bit_is_set() {
153            // NOTE(unsafe) atomic write to stateless register
154            // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
155            unsafe { ptr::write_volatile(&(*USART1::ptr()).tdr as *const _ as *mut _, byte) }
156            Ok(())
157        } else {
158            Err(nb::Error::WouldBlock)
159        }
160    }
161}
162
163/// USART2
164impl<PINS> Serial<USART2, PINS> {
165    pub fn usart2(usart: USART2, pins: PINS, baud_rate: Bps, clocks: Clocks) -> Self
166    where
167        PINS: Pins<USART2>,
168    {
169        // NOTE(unsafe) This executes only during initialisation
170        let rcc = unsafe { &(*RCC::ptr()) };
171
172        /* Enable clock for USART */
173        rcc.apb1enr.modify(|_, w| w.usart2en().set_bit());
174
175        // Calculate correct baudrate divisor on the fly
176        let brr = clocks.pclk().0 / baud_rate.0;
177        usart.brr.write(|w| unsafe { w.bits(brr) });
178
179        /* Reset other registers to disable advanced USART features */
180        usart.cr2.reset();
181        usart.cr3.reset();
182
183        /* Enable transmission and receiving */
184        usart.cr1.modify(|_, w| unsafe { w.bits(0xD) });
185
186        Serial { usart, pins }
187    }
188
189    pub fn split(self) -> (Tx<USART2>, Rx<USART2>) {
190        (
191            Tx {
192                _usart: PhantomData,
193            },
194            Rx {
195                _usart: PhantomData,
196            },
197        )
198    }
199    pub fn release(self) -> (USART2, PINS) {
200        (self.usart, self.pins)
201    }
202}
203
204impl hal::serial::Read<u8> for Rx<USART2> {
205    type Error = Error;
206
207    fn read(&mut self) -> nb::Result<u8, Error> {
208        // NOTE(unsafe) atomic read with no side effects
209        let isr = unsafe { (*USART2::ptr()).isr.read() };
210
211        Err(if isr.pe().bit_is_set() {
212            nb::Error::Other(Error::Parity)
213        } else if isr.fe().bit_is_set() {
214            nb::Error::Other(Error::Framing)
215        } else if isr.nf().bit_is_set() {
216            nb::Error::Other(Error::Noise)
217        } else if isr.ore().bit_is_set() {
218            nb::Error::Other(Error::Overrun)
219        } else if isr.rxne().bit_is_set() {
220            // NOTE(read_volatile) see `write_volatile` below
221            return Ok(unsafe { ptr::read_volatile(&(*USART2::ptr()).rdr as *const _ as *const _) });
222        } else {
223            nb::Error::WouldBlock
224        })
225    }
226}
227
228impl hal::serial::Write<u8> for Tx<USART2> {
229    type Error = Void;
230
231    fn flush(&mut self) -> nb::Result<(), Self::Error> {
232        // NOTE(unsafe) atomic read with no side effects
233        let isr = unsafe { (*USART2::ptr()).isr.read() };
234
235        if isr.tc().bit_is_set() {
236            Ok(())
237        } else {
238            Err(nb::Error::WouldBlock)
239        }
240    }
241
242    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
243        // NOTE(unsafe) atomic read with no side effects
244        let isr = unsafe { (*USART2::ptr()).isr.read() };
245
246        if isr.txe().bit_is_set() {
247            // NOTE(unsafe) atomic write to stateless register
248            // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
249            unsafe { ptr::write_volatile(&(*USART2::ptr()).tdr as *const _ as *mut _, byte) }
250            Ok(())
251        } else {
252            Err(nb::Error::WouldBlock)
253        }
254    }
255}
256
257impl<USART> Write for Tx<USART>
258where
259    Tx<USART>: hal::serial::Write<u8>,
260{
261    fn write_str(&mut self, s: &str) -> Result {
262        let _ = s
263            .as_bytes()
264            .iter()
265            .map(|c| block!(self.write(*c)))
266            .last();
267        Ok(())
268    }
269}