tm4c_hal/
lib.rs

1//! Generic implementation code for both TM4C123 and TM4C129.
2
3#![no_std]
4#![deny(missing_docs, warnings)]
5#![allow(deprecated)]
6
7pub mod bb;
8pub mod delay;
9pub mod eeprom;
10pub mod gpio;
11pub mod i2c;
12pub mod serial;
13pub mod sysctl;
14pub mod time;
15
16///! An internal macro to implement the GPIO functionality for each port
17#[macro_export]
18macro_rules! gpio_macro {
19    ($chip_crate:ident, $GPIOX:ident, $gpiox:ident, $iopd:ident, $PXx:ident, [
20        $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+
21    ]) => {
22        /// GPIO
23        pub mod $gpiox {
24            use super::*;
25            use $chip_crate::$GPIOX;
26
27            /// Provides mutual-exclusion for certain GPIO operations (such as
28            /// selecting an alternate mode) that can't be done atomically.
29            pub struct GpioControl {
30                _0: (),
31            }
32
33            /// GPIO parts
34            pub struct Parts {
35                /// Pass an &mut reference to methods that require it.
36                pub control: GpioControl,
37                $(
38                    /// Pin
39                    pub $pxi: $PXi<$MODE>,
40                )+
41            }
42
43            impl GpioExt for $GPIOX {
44                type Parts = Parts;
45
46                /// Break this GPIO port into separate pins
47                fn split(self, pc: &sysctl::PowerControl) -> Parts {
48                    sysctl::control_power(
49                        pc, sysctl::Domain::$iopd,
50                        sysctl::RunMode::Run, sysctl::PowerState::On);
51                    sysctl::reset(pc, sysctl::Domain::$iopd);
52
53                    Parts {
54                        control: GpioControl { _0: () },
55                        $(
56                            $pxi: $PXi { _mode: PhantomData },
57                        )+
58                    }
59                }
60            }
61
62            /// Partially erased pin
63            pub struct $PXx<MODE> {
64                i: u8,
65                _mode: PhantomData<MODE>,
66            }
67
68            impl<MODE> StatefulOutputPin for $PXx<Output<MODE>> where MODE: OutputMode {
69                fn is_set_high(&self) -> bool {
70                    let p = unsafe { &*$GPIOX::ptr() };
71                    bb::read_bit(&p.data, self.i)
72                }
73
74                fn is_set_low(&self) -> bool {
75                    !self.is_set_high()
76                }
77            }
78
79            impl<MODE> OutputPin for $PXx<Output<MODE>> where MODE: OutputMode {
80                fn set_high(&mut self) {
81                    let p = unsafe { &*$GPIOX::ptr() };
82                    unsafe { bb::change_bit(&p.data, self.i, true); }
83                }
84
85                fn set_low(&mut self) {
86                    let p = unsafe { &*$GPIOX::ptr() };
87                    unsafe { bb::change_bit(&p.data, self.i, false); }
88                }
89            }
90
91            impl<MODE> InputPin for $PXx<Input<MODE>> where MODE: InputMode {
92                fn is_high(&self) -> bool {
93                    let p = unsafe { &*$GPIOX::ptr() };
94                    bb::read_bit(&p.data, self.i)
95                }
96
97                fn is_low(&self) -> bool {
98                    !self.is_high()
99                }
100            }
101
102            impl<MODE> $PXx<Input<MODE>> where MODE: InputMode {
103                /// Enables or disables interrupts on this GPIO pin.
104                pub fn set_interrupt_mode(&mut self, mode: InterruptMode) {
105                    let p = unsafe { &*$GPIOX::ptr() };
106                    unsafe { bb::change_bit(&p.im, self.i, false); }
107                    match mode {
108                        InterruptMode::LevelHigh => {
109                            // IM &= ~self.i;
110                            unsafe { bb::change_bit(&p.im, self.i, false); }
111                            // IS |= self.i;
112                            unsafe { bb::change_bit(&p.is, self.i, true); }
113                            // IBE &= ~self.i;
114                            unsafe { bb::change_bit(&p.ibe, self.i, false); }
115                            // IEV |= self.i;
116                            unsafe { bb::change_bit(&p.iev, self.i, true); }
117                            // IM |= self.i;
118                            unsafe { bb::change_bit(&p.im, self.i, true); }
119                        },
120                        InterruptMode::LevelLow => {
121                            // IM &= ~self.i;
122                            unsafe { bb::change_bit(&p.im, self.i, false); }
123                            // IS |= self.i;
124                            unsafe { bb::change_bit(&p.is, self.i, true); }
125                            // IBE &= ~self.i;
126                            unsafe { bb::change_bit(&p.ibe, self.i, false); }
127                            // IEV &= ~self.i;
128                            unsafe { bb::change_bit(&p.iev, self.i, false); }
129                            // IM |= self.i;
130                            unsafe { bb::change_bit(&p.im, self.i, true); }
131                        },
132                        InterruptMode::EdgeRising => {
133                            // IM &= ~self.i;
134                            unsafe { bb::change_bit(&p.im, self.i, false); }
135                            // IS &= ~self.i;
136                            unsafe { bb::change_bit(&p.is, self.i, false); }
137                            // IBE &= ~self.i;
138                            unsafe { bb::change_bit(&p.ibe, self.i, false); }
139                            // IEV |= self.i;
140                            unsafe { bb::change_bit(&p.iev, self.i, true); }
141                            // IM |= self.i;
142                            unsafe { bb::change_bit(&p.im, self.i, true); }
143                        },
144                        InterruptMode::EdgeFalling => {
145                            // IM &= ~self.i;
146                            unsafe { bb::change_bit(&p.im, self.i, false); }
147                            // IS &= ~self.i;
148                            unsafe { bb::change_bit(&p.is, self.i, false); }
149                            // IBE &= ~self.i;
150                            unsafe { bb::change_bit(&p.ibe, self.i, false); }
151                            // IEV &= ~self.i;
152                            unsafe { bb::change_bit(&p.iev, self.i, false); }
153                            // IM |= self.i;
154                            unsafe { bb::change_bit(&p.im, self.i, true); }
155                        },
156                        InterruptMode::EdgeBoth => {
157                            // IM &= ~self.i;
158                            unsafe { bb::change_bit(&p.im, self.i, false); }
159                            // IS &= ~self.i;
160                            unsafe { bb::change_bit(&p.is, self.i, false); }
161                            // IBE |= self.i;
162                            unsafe { bb::change_bit(&p.ibe, self.i, true); }
163                            // IEV |= self.i;
164                            unsafe { bb::change_bit(&p.iev, self.i, true); }
165                            // IM |= self.i;
166                            unsafe { bb::change_bit(&p.im, self.i, true); }
167                        },
168                        InterruptMode::Disabled => {
169                            // IM &= ~self.i;
170                            unsafe { bb::change_bit(&p.im, self.i, false); }
171                        },
172                    }
173                }
174
175                /// Returns the current interrupt status for this pin.
176                pub fn get_interrupt_status(&self) -> bool {
177                    let p = unsafe { &*$GPIOX::ptr() };
178                    bb::read_bit(&p.mis, self.i)
179                }
180
181                /// Marks the interrupt for this pin as handled. You should
182                /// call this (or perform its functionality) from the ISR.
183                pub fn clear_interrupt(&self) {
184                    let p = unsafe { &*$GPIOX::ptr() };
185                    unsafe { bb::change_bit(&p.icr, self.i, true); }
186                }
187            }
188
189            $(
190                /// Pin
191                pub struct $PXi<MODE> {
192                    _mode: PhantomData<MODE>,
193                }
194
195                impl<MODE> crate::Sealed for $PXi<MODE> {}
196
197                impl<MODE> $PXi<MODE> where MODE: IsUnlocked {
198                    /// Configures the pin to serve as alternate function 1 through 15.
199                    /// Disables open-drain to make the output a push-pull.
200                    pub fn into_af_push_pull<AF>(
201                        self,
202                        _gpio_control: &mut GpioControl,
203                    ) -> $PXi<AlternateFunction<AF, PushPull>> where AF: AlternateFunctionChoice {
204                        let p = unsafe { &*$GPIOX::ptr() };
205                        let mask = 0xF << ($i * 4);
206                        let bits = AF::number() << ($i * 4);
207                        unsafe {
208                            p.pctl.modify(|r, w| w.bits((r.bits() & !mask) | bits));
209                        }
210                        unsafe { bb::change_bit(&p.afsel, $i, true); }
211                        unsafe { bb::change_bit(&p.dir, $i, false); }
212                        unsafe { bb::change_bit(&p.odr, $i, false); }
213                        unsafe { bb::change_bit(&p.pur, $i, false); }
214                        unsafe { bb::change_bit(&p.pdr, $i, false); }
215                        unsafe { bb::change_bit(&p.den, $i, true); }
216                        $PXi { _mode: PhantomData }
217                    }
218
219                    /// Configures the pin to serve as alternate function 1 through 15 with
220                    /// a weak pull-up resistor.
221                    pub fn into_af_pull_up<AF>(
222                        self,
223                        _gpio_control: &mut GpioControl,
224                    ) -> $PXi<AlternateFunction<AF, PullUp>> where AF: AlternateFunctionChoice {
225                        let p = unsafe { &*$GPIOX::ptr() };
226                        let mask = 0xF << ($i * 4);
227                        let bits = AF::number() << ($i * 4);
228                        unsafe {
229                            p.pctl.modify(|r, w| w.bits((r.bits() & !mask) | bits));
230                        }
231                        unsafe { bb::change_bit(&p.afsel, $i, true); }
232                        unsafe { bb::change_bit(&p.dir, $i, false); }
233                        unsafe { bb::change_bit(&p.odr, $i, false); }
234                        unsafe { bb::change_bit(&p.pur, $i, true); }
235                        unsafe { bb::change_bit(&p.pdr, $i, false); }
236                        unsafe { bb::change_bit(&p.den, $i, true); }
237                        $PXi { _mode: PhantomData }
238                    }
239
240                    /// Configures the pin to serve as alternate function 1 through 15 with
241                    /// a weak pull-down resistor.
242                    pub fn into_af_pull_down<AF>(
243                        self,
244                        _gpio_control: &mut GpioControl,
245                    ) -> $PXi<AlternateFunction<AF, PullDown>> where AF: AlternateFunctionChoice {
246                        let p = unsafe { &*$GPIOX::ptr() };
247                        let mask = 0xF << ($i * 4);
248                        let bits = AF::number() << ($i * 4);
249                        unsafe {
250                            p.pctl.modify(|r, w| w.bits((r.bits() & !mask) | bits));
251                        }
252                        unsafe { bb::change_bit(&p.afsel, $i, true); }
253                        unsafe { bb::change_bit(&p.dir, $i, false); }
254                        unsafe { bb::change_bit(&p.odr, $i, false); }
255                        unsafe { bb::change_bit(&p.pur, $i, false); }
256                        unsafe { bb::change_bit(&p.pdr, $i, true); }
257                        unsafe { bb::change_bit(&p.den, $i, true); }
258                        $PXi { _mode: PhantomData }
259                    }
260
261                    /// Configures the pin to serve as alternate function 1 through 15.
262                    /// Enables open-drain (useful for I2C SDA, for example).
263                    pub fn into_af_open_drain<AF, ODM>(
264                        self,
265                        _gpio_control: &mut GpioControl,
266                    ) -> $PXi<AlternateFunction<AF, OpenDrain<ODM>>> where AF: AlternateFunctionChoice, ODM: OpenDrainMode {
267                        let p = unsafe { &*$GPIOX::ptr() };
268                        let mask = 0xF << ($i * 4);
269                        let bits = AF::number() << ($i * 4);
270                        unsafe {
271                            p.pctl.modify(|r, w| w.bits((r.bits() & !mask) | bits));
272                        }
273                        unsafe { bb::change_bit(&p.afsel, $i, true); }
274                        unsafe { bb::change_bit(&p.dir, $i, false); }
275                        unsafe { bb::change_bit(&p.odr, $i, true); }
276                        unsafe { bb::change_bit(&p.pur, $i, ODM::pup()); }
277                        unsafe { bb::change_bit(&p.pdr, $i, false); }
278                        unsafe { bb::change_bit(&p.den, $i, true); }
279                        $PXi { _mode: PhantomData }
280                    }
281
282                    /// Configures the pin to operate as a floating input pin
283                    pub fn into_floating_input(
284                        self
285                    ) -> $PXi<Input<Floating>> {
286                        let p = unsafe { &*$GPIOX::ptr() };
287                        unsafe { bb::change_bit(&p.afsel, $i, false); }
288                        unsafe { bb::change_bit(&p.dir, $i, false); }
289                        unsafe { bb::change_bit(&p.odr, $i, false); }
290                        unsafe { bb::change_bit(&p.pur, $i, false); }
291                        unsafe { bb::change_bit(&p.pdr, $i, false); }
292                        unsafe { bb::change_bit(&p.den, $i, true); }
293                        $PXi { _mode: PhantomData }
294                    }
295
296                    /// Configures the pin to operate as a pulled down input pin
297                    pub fn into_pull_down_input(
298                        self
299                    ) -> $PXi<Input<PullDown>> {
300                        let p = unsafe { &*$GPIOX::ptr() };
301                        unsafe { bb::change_bit(&p.afsel, $i, false); }
302                        unsafe { bb::change_bit(&p.dir, $i, false); }
303                        unsafe { bb::change_bit(&p.odr, $i, false); }
304                        unsafe { bb::change_bit(&p.pur, $i, false); }
305                        unsafe { bb::change_bit(&p.pdr, $i, true); }
306                        unsafe { bb::change_bit(&p.den, $i, true); }
307                        $PXi { _mode: PhantomData }
308                    }
309
310                    /// Configures the pin to operate as a pulled up input pin
311                    pub fn into_pull_up_input(
312                        self
313                    ) -> $PXi<Input<PullUp>> {
314                        let p = unsafe { &*$GPIOX::ptr() };
315                        unsafe { bb::change_bit(&p.afsel, $i, false); }
316                        unsafe { bb::change_bit(&p.dir, $i, false); }
317                        unsafe { bb::change_bit(&p.odr, $i, false); }
318                        unsafe { bb::change_bit(&p.pur, $i, true); }
319                        unsafe { bb::change_bit(&p.pdr, $i, false); }
320                        unsafe { bb::change_bit(&p.den, $i, true); }
321                        $PXi { _mode: PhantomData }
322                    }
323
324                    /// Configures the pin to operate as an open drain output pin
325                    pub fn into_open_drain_output<ODM>(
326                        self
327                    ) -> $PXi<Output<OpenDrain<ODM>>> where ODM: OpenDrainMode {
328                        let p = unsafe { &*$GPIOX::ptr() };
329                        unsafe { bb::change_bit(&p.afsel, $i, false); }
330                        unsafe { bb::change_bit(&p.dir, $i, true); }
331                        unsafe { bb::change_bit(&p.odr, $i, true); }
332                        unsafe { bb::change_bit(&p.pur, $i, ODM::pup()); }
333                        unsafe { bb::change_bit(&p.pdr, $i, false); }
334                        unsafe { bb::change_bit(&p.den, $i, true); }
335                        $PXi { _mode: PhantomData }
336                    }
337
338                    /// Configures the pin to operate as an push pull output pin
339                    pub fn into_push_pull_output(
340                        self
341                    ) -> $PXi<Output<PushPull>> {
342                        let p = unsafe { &*$GPIOX::ptr() };
343                        unsafe { bb::change_bit(&p.afsel, $i, false); }
344                        unsafe { bb::change_bit(&p.dir, $i, true); }
345                        unsafe { bb::change_bit(&p.odr, $i, false); }
346                        unsafe { bb::change_bit(&p.pur, $i, false); }
347                        unsafe { bb::change_bit(&p.pdr, $i, false); }
348                        unsafe { bb::change_bit(&p.den, $i, true); }
349                        $PXi { _mode: PhantomData }
350                    }
351
352                    /// Configures the pin as tri-state
353                    pub fn into_tri_state(
354                        self
355                    ) -> $PXi<Tristate> {
356                        let p = unsafe { &*$GPIOX::ptr() };
357                        unsafe { bb::change_bit(&p.den, $i, false); }
358                        unsafe { bb::change_bit(&p.afsel, $i, false); }
359                        unsafe { bb::change_bit(&p.dir, $i, false); }
360                        unsafe { bb::change_bit(&p.odr, $i, false); }
361                        unsafe { bb::change_bit(&p.pur, $i, false); }
362                        unsafe { bb::change_bit(&p.pdr, $i, false); }
363                        $PXi { _mode: PhantomData }
364                    }
365
366                }
367
368                impl<MODE> $PXi<MODE> {
369                    /// Erases the pin number from the type
370                    ///
371                    /// This is useful when you want to collect the pins into an array where you
372                    /// need all the elements to have the same type
373                    pub fn downgrade(self) -> $PXx<MODE> {
374                        $PXx {
375                            i: $i,
376                            _mode: self._mode,
377                        }
378                    }
379                }
380
381                impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> where MODE: OutputMode {
382                    fn is_set_high(&self) -> bool {
383                        let p = unsafe { &*$GPIOX::ptr() };
384                        bb::read_bit(&p.data, $i)
385                    }
386
387                    fn is_set_low(&self) -> bool {
388                        !self.is_set_high()
389                    }
390                }
391
392                impl<MODE> OutputPin for $PXi<Output<MODE>> where MODE: OutputMode {
393                    fn set_high(&mut self) {
394                        let p = unsafe { &*$GPIOX::ptr() };
395                        unsafe { bb::change_bit(&p.data, $i, true); }
396                    }
397
398                    fn set_low(&mut self) {
399                        let p = unsafe { &*$GPIOX::ptr() };
400                        unsafe { bb::change_bit(&p.data, $i, false); }
401                    }
402                }
403
404                impl<MODE> InputPin for $PXi<Input<MODE>> where MODE: InputMode {
405                    fn is_high(&self) -> bool {
406                        let p = unsafe { &*$GPIOX::ptr() };
407                        bb::read_bit(&p.data, $i)
408                    }
409
410                    fn is_low(&self) -> bool {
411                        !self.is_high()
412                    }
413                }
414
415                impl<MODE> $PXi<Input<MODE>> where MODE: InputMode {
416                    /// Enables or disables interrupts on this GPIO pin.
417                    pub fn set_interrupt_mode(&mut self, mode: InterruptMode) {
418                        let p = unsafe { &*$GPIOX::ptr() };
419                        unsafe { bb::change_bit(&p.im, $i, false); }
420                        match mode {
421                            InterruptMode::LevelHigh => {
422                                // IM &= ~$i;
423                                unsafe { bb::change_bit(&p.im, $i, false); }
424                                // IS |= $i;
425                                unsafe { bb::change_bit(&p.is, $i, true); }
426                                // IBE &= ~$i;
427                                unsafe { bb::change_bit(&p.ibe, $i, false); }
428                                // IEV |= $i;
429                                unsafe { bb::change_bit(&p.iev, $i, true); }
430                                // IM |= $i;
431                                unsafe { bb::change_bit(&p.im, $i, true); }
432                            },
433                            InterruptMode::LevelLow => {
434                                // IM &= ~$i;
435                                unsafe { bb::change_bit(&p.im, $i, false); }
436                                // IS |= $i;
437                                unsafe { bb::change_bit(&p.is, $i, true); }
438                                // IBE &= ~$i;
439                                unsafe { bb::change_bit(&p.ibe, $i, false); }
440                                // IEV &= ~$i;
441                                unsafe { bb::change_bit(&p.iev, $i, false); }
442                                // IM |= $i;
443                                unsafe { bb::change_bit(&p.im, $i, true); }
444                            },
445                            InterruptMode::EdgeRising => {
446                                // IM &= ~$i;
447                                unsafe { bb::change_bit(&p.im, $i, false); }
448                                // IS &= ~$i;
449                                unsafe { bb::change_bit(&p.is, $i, false); }
450                                // IBE &= ~$i;
451                                unsafe { bb::change_bit(&p.ibe, $i, false); }
452                                // IEV |= $i;
453                                unsafe { bb::change_bit(&p.iev, $i, true); }
454                                // IM |= $i;
455                                unsafe { bb::change_bit(&p.im, $i, true); }
456                            },
457                            InterruptMode::EdgeFalling => {
458                                // IM &= ~$i;
459                                unsafe { bb::change_bit(&p.im, $i, false); }
460                                // IS &= ~$i;
461                                unsafe { bb::change_bit(&p.is, $i, false); }
462                                // IBE &= ~$i;
463                                unsafe { bb::change_bit(&p.ibe, $i, false); }
464                                // IEV &= ~$i;
465                                unsafe { bb::change_bit(&p.iev, $i, false); }
466                                // IM |= $i;
467                                unsafe { bb::change_bit(&p.im, $i, true); }
468                            },
469                            InterruptMode::EdgeBoth => {
470                                // IM &= ~$i;
471                                unsafe { bb::change_bit(&p.im, $i, false); }
472                                // IS &= ~$i;
473                                unsafe { bb::change_bit(&p.is, $i, false); }
474                                // IBE |= $i;
475                                unsafe { bb::change_bit(&p.ibe, $i, true); }
476                                // IEV |= $i;
477                                unsafe { bb::change_bit(&p.iev, $i, true); }
478                                // IM |= $i;
479                                unsafe { bb::change_bit(&p.im, $i, true); }
480                            },
481                            InterruptMode::Disabled => {
482                                // IM &= ~$i;
483                                unsafe { bb::change_bit(&p.im, $i, false); }
484                            },
485                        }
486                    }
487
488                    /// Returns the current interrupt status for this pin.
489                    pub fn get_interrupt_status(&self) -> bool {
490                        let p = unsafe { &*$GPIOX::ptr() };
491                        bb::read_bit(&p.mis, $i)
492                    }
493
494                    /// Marks the interrupt for this pin as handled. You should
495                    /// call this (or perform its functionality) from the ISR.
496                    pub fn clear_interrupt(&self) {
497                        let p = unsafe { &*$GPIOX::ptr() };
498                        unsafe { bb::change_bit(&p.icr, $i, true); }
499                    }
500                }
501
502                impl $PXi<Locked> {
503                    /// Unlock a GPIO so that it can be used. This is required
504                    /// on 'special' GPIOs that the manufacturer doesn't want
505                    /// you to change by accident - like NMI and JTAG pins.
506                    pub fn unlock(self, _gpio_control: &mut GpioControl) -> $PXi<Tristate> {
507                        let p = unsafe { &*$GPIOX::ptr() };
508                        p.lock.write(|w| w.lock().key());
509                        p.cr.modify(|_, w| unsafe { w.bits(1 << $i) });
510                        p.lock.write(|w| w.lock().unlocked());
511                        unsafe { bb::change_bit(&p.den, $i, false); }
512                        unsafe { bb::change_bit(&p.afsel, $i, false); }
513                        unsafe { bb::change_bit(&p.dir, $i, false); }
514                        unsafe { bb::change_bit(&p.odr, $i, false); }
515                        unsafe { bb::change_bit(&p.pur, $i, false); }
516                        unsafe { bb::change_bit(&p.pdr, $i, false); }
517                        $PXi { _mode: PhantomData }
518                    }
519                }
520            )+
521        }
522    }
523}
524
525///! An internal macro to implement the UART functionality for each peripheral
526#[macro_export]
527macro_rules! uart_hal_macro {
528    ($(
529        $UARTX:ident: ($powerDomain:ident, $uartX:ident),
530    )+) => {
531        $crate::uart_traits_macro!();
532
533        $(
534            impl<TX, RX, RTS, CTS> Serial<$UARTX, TX, RX, RTS, CTS> {
535                /// Configures a UART peripheral to provide serial communication
536                pub fn $uartX(
537                    mut uart: $UARTX,
538                    tx_pin: TX,
539                    rx_pin: RX,
540                    mut rts_pin: RTS,
541                    mut cts_pin: CTS,
542                    baud_rate: Bps,
543                    nl_mode: NewlineMode,
544                    clocks: &Clocks,
545                    pc: &sysctl::PowerControl
546                ) -> Self
547                where
548                    TX: TxPin<$UARTX>,
549                    RX: RxPin<$UARTX>,
550                    CTS: CtsPin<$UARTX>,
551                    RTS: RtsPin<$UARTX>,
552                {
553                    // Enable UART peripheral clocks
554                    sysctl::control_power(
555                        pc, sysctl::Domain::$powerDomain,
556                        sysctl::RunMode::Run, sysctl::PowerState::On);
557                    sysctl::reset(pc, sysctl::Domain::$powerDomain);
558
559                    // Reset UART
560                    uart.ctl.reset();
561
562                    // Calculate baud rate dividers
563                    // baud_int = 64 * (sys_clk / (16 * baud))
564                    // baud_int = 4 * (sys_clk / baud)
565                    // baud_int = ((8 * sys_clk) / baud) / 2, plus + 1 to round correctly
566                    let baud_int: u32 = (((clocks.sysclk.0 * 8) / baud_rate.0) + 1) / 2;
567
568                    // Set baud rate
569                    uart.ibrd.write(|w|
570                        unsafe { w.divint().bits((baud_int / 64) as u16) });
571                    uart.fbrd.write(|w|
572                        unsafe { w.divfrac().bits((baud_int % 64) as u8) });
573
574                    // Set data bits / parity / stop bits / enable fifo
575                    uart.lcrh.write(|w| w.wlen()._8().fen().bit(true));
576
577                    // Activate flow control (if desired)
578                    rts_pin.enable(&mut uart);
579                    cts_pin.enable(&mut uart);
580
581                    // Enable uart
582                    uart.ctl.modify(|_, w| w.rxe().bit(true).txe().bit(true).uarten().bit(true));
583
584                    Serial { uart, tx_pin, rx_pin, rts_pin, cts_pin, nl_mode }
585                }
586
587                /// Change the current baud rate for the UART. We need the
588                /// `clocks` object in order to calculate the magic baud rate
589                /// register values.
590                pub fn change_baud_rate(&mut self, baud_rate: Bps, clocks: &Clocks) {
591                    // Stop UART
592                    self.uart.ctl.modify(|_, w| w.uarten().bit(false));
593
594                    // Calculate baud rate dividers
595                    let baud_int: u32 = (((clocks.sysclk.0 * 8) / baud_rate.0) + 1) / 2;
596
597                    // Set baud rate
598                    self.uart.ibrd.write(|w|
599                        unsafe { w.divint().bits((baud_int / 64) as u16) });
600                    self.uart.fbrd.write(|w|
601                        unsafe { w.divfrac().bits((baud_int % 64) as u8) });
602
603                    // Set data bits / parity / stop bits / enable fifo
604                    // If you don't write to this register, the baud rate change doesn't take effect
605                    self.uart.lcrh.write(|w| w.wlen()._8().fen().bit(true));
606
607                    // Start UART again
608                    self.uart.ctl.modify(|_, w| w.uarten().bit(true));
609                }
610
611                /// Splits the `Serial` abstraction into a transmitter and a
612                /// receiver half. If you do this you can transmit and receive
613                /// in different threads.
614                pub fn split(self) -> (Tx<$UARTX, TX, RTS>, Rx<$UARTX, RX, CTS>) {
615                    (
616                        Tx {
617                            uart: self.uart,
618                            pin: self.tx_pin,
619                            nl_mode: self.nl_mode,
620                            flow_pin: self.rts_pin,
621                        },
622                        Rx {
623                            _uart: PhantomData,
624                            pin: self.rx_pin,
625                            flow_pin: self.cts_pin,
626                        },
627                    )
628                }
629
630                /// Write a complete string to the UART.
631                pub fn write_all<I: ?Sized>(&mut self, data: &I)
632                where
633                    I: AsRef<[u8]>,
634                {
635                    for octet in data.as_ref().iter() {
636                        block!(self.write(*octet)).unwrap(); // E = Void
637                    }
638                }
639
640                /// Re-combine a split UART
641                pub fn combine(tx: Tx<$UARTX, TX, RTS>, rx: Rx<$UARTX, RX, CTS>) -> Serial<$UARTX, TX, RX, RTS, CTS> {
642                    Serial {
643                        uart: tx.uart,
644                        nl_mode: tx.nl_mode,
645                        rx_pin: rx.pin,
646                        tx_pin: tx.pin,
647                        rts_pin: tx.flow_pin,
648                        cts_pin: rx.flow_pin,
649                    }
650                }
651
652                /// Releases the UART peripheral and associated pins
653                pub fn free(self) -> ($UARTX, TX, RX, RTS, CTS) {
654                    (self.uart, self.tx_pin, self.rx_pin, self.rts_pin, self.cts_pin)
655                }
656            }
657
658            impl<TX, RTS> Tx<$UARTX, TX, RTS> {
659                /// Write a complete string to the UART.
660                pub fn write_all<I: ?Sized>(&mut self, data: &I)
661                where
662                    I: AsRef<[u8]>,
663                {
664                    for octet in data.as_ref().iter() {
665                        block!(self.write(*octet)).unwrap(); // E = Void
666                    }
667                }
668            }
669
670            impl<TX, RX, RTS, CTS> serial::Read<u8> for Serial<$UARTX, TX, RX, RTS, CTS> {
671                type Error = Void;
672
673                fn read(&mut self) -> nb::Result<u8, Self::Error> {
674                    if self.uart.fr.read().rxfe().bit() {
675                        return Err(nb::Error::WouldBlock);
676                    }
677                    Ok(self.uart.dr.read().data().bits())
678                }
679            }
680
681            impl<RX, CTS> serial::Read<u8> for Rx<$UARTX, RX, CTS> {
682                type Error = Void;
683
684                fn read(&mut self) -> nb::Result<u8, Self::Error> {
685                    // We're only doing RX operations here so this is safe.
686                    let p = unsafe { &*$UARTX::ptr() };
687                    if p.fr.read().rxfe().bit() {
688                        return Err(nb::Error::WouldBlock);
689                    }
690                    Ok(p.dr.read().data().bits())
691                }
692            }
693
694            impl<TX, RX, RTS, CTS> serial::Write<u8> for Serial<$UARTX, TX, RX, RTS, CTS> {
695                type Error = Void;
696
697                fn flush(&mut self) -> nb::Result<(), Void> {
698                    if self.uart.fr.read().txff().bit() {
699                        return Err(nb::Error::WouldBlock);
700                    }
701                    Ok(())
702                }
703
704                fn write(&mut self, byte: u8) -> nb::Result<(), Void> {
705                    if self.uart.fr.read().txff().bit() {
706                        return Err(nb::Error::WouldBlock);
707                    }
708                    self.uart.dr.write(|w| unsafe { w.data().bits(byte) });
709                    Ok(())
710                }
711            }
712
713            impl<TX, RTS> serial::Write<u8> for Tx<$UARTX, TX, RTS> {
714                type Error = Void;
715
716                fn flush(&mut self) -> nb::Result<(), Void> {
717                    if self.uart.fr.read().txff().bit() {
718                        return Err(nb::Error::WouldBlock);
719                    }
720                    Ok(())
721                }
722
723                fn write(&mut self, byte: u8) -> nb::Result<(), Void> {
724                    if self.uart.fr.read().txff().bit() {
725                        return Err(nb::Error::WouldBlock);
726                    }
727                    self.uart.dr.write(|w| unsafe { w.data().bits(byte) });
728                    Ok(())
729                }
730            }
731
732            /// Allows the Uart to be passed to 'write!()' and friends.
733            impl<TX, RX, RTS, CTS> fmt::Write for Serial<$UARTX, TX, RX, RTS, CTS> {
734                fn write_str(&mut self, s: &str) -> fmt::Result {
735                    match self.nl_mode {
736                        NewlineMode::Binary => self.write_all(s),
737                        NewlineMode::SwapLFtoCRLF => {
738                            for byte in s.bytes() {
739                                if byte == 0x0A {
740                                    // Prefix every \n with a \r
741                                    block!(self.write(0x0D)).unwrap(); // E = Void
742                                }
743                                block!(self.write(byte)).unwrap(); // E = Void
744                            }
745                        }
746                    }
747                    Ok(())
748                }
749            }
750
751            /// Allows the Tx to be passed to 'write!()' and friends.
752            impl<TX, RTS> fmt::Write for Tx<$UARTX, TX, RTS> {
753                fn write_str(&mut self, s: &str) -> fmt::Result {
754                    match self.nl_mode {
755                        NewlineMode::Binary => self.write_all(s),
756                        NewlineMode::SwapLFtoCRLF => {
757                            for byte in s.bytes() {
758                                if byte == 0x0A {
759                                    // Prefix every \n with a \r
760                                    block!(self.write(0x0D)).unwrap(); // E = Void
761                                }
762                                block!(self.write(byte)).unwrap(); // E = Void
763                            }
764                        }
765                    }
766                    Ok(())
767                }
768            }
769
770        )+
771    }
772}
773
774///! An internal macro to help define all the different pin typestates
775#[macro_export]
776macro_rules! uart_pin_macro {
777    ($UARTn:ident,
778        cts: [$(($($ctsgpio: ident)::*, $ctsaf: ident)),*],
779        // dcd: [() $(, ($($dcdgpio: ident)::*, $dcdaf: ident))*],
780        // dsr: [() $(, ($($dsrgpio: ident)::*, $dsraf: ident))*],
781        // dtr: [() $(, ($($dtrgpio: ident)::*, $dtraf: ident))*],
782        // ri: [() $(, ($($rigpio: ident)::*, $riaf: ident))*],
783        rts: [$(($($rtsgpio: ident)::*, $rtsaf: ident)),*],
784        rx: [$(($($rxgpio: ident)::*, $rxaf: ident)),*],
785        tx: [$(($($txgpio: ident)::*, $txaf: ident)),*],
786    ) => {
787        $(
788            impl<T> CtsPin<$UARTn> for $($ctsgpio)::*<AlternateFunction<$ctsaf, T>>
789            where
790                T: OutputMode,
791            {
792                fn enable(&mut self, uart: &mut $UARTn) {
793                    uart.ctl.modify(|_, w| w.ctsen().set_bit());
794                }
795            }
796        )*
797
798        $(
799            impl<T> RtsPin<$UARTn> for $($rtsgpio)::*<AlternateFunction<$rtsaf, T>>
800            where
801                T: OutputMode,
802            {
803                fn enable(&mut self, uart: &mut $UARTn) {
804                    uart.ctl.modify(|_, w| w.rtsen().set_bit());
805                }
806            }
807        )*
808
809        $(
810            impl <T> RxPin<$UARTn> for $($rxgpio)::*<AlternateFunction<$rxaf, T>>
811            where
812                T: OutputMode,
813            {}
814        )*
815
816        $(
817            impl <T> TxPin<$UARTn> for $($txgpio)::*<AlternateFunction<$txaf, T>>
818            where
819                T: OutputMode,
820            {}
821        )*
822    }
823}