nucleo_f446re/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(clippy::allow_attributes)]
3#![deny(missing_docs)]
4#![deny(unsafe_code)]
5#![no_std]
6
7/// Work with the on-board user button
8pub mod button;
9/// Work with the on-board user LED
10pub mod led;
11/// Work with the virtual serial port through the on-board ST-Link
12pub mod serial;
13
14use self::{
15    button::Button,
16    led::{LedBuilder, LedDigital},
17    serial::SerialPort,
18};
19use stm32f4xx_hal::{prelude::*, timer::SysDelay};
20
21/// The batteries-included way to work with the Nucleo board.
22///
23/// This struct is marked as `non_exhaustive` to make it unconstructable, thereby forcing the user to go through init().
24#[non_exhaustive]
25pub struct Nucleo<LED = LedDigital> {
26    /// The user LED.
27    pub user_led: LED,
28    /// The user button.
29    pub user_button: Button,
30    /// The virtual serial port through the on-board ST-Link debugger.
31    pub vcom: SerialPort,
32    /// Gives the ability to delay (blocking) with millisecond resolution.
33    pub delay: SysDelay,
34}
35
36impl<LED: LedBuilder> Nucleo<LED> {
37    /// Initialize the Nucleo board.
38    ///
39    /// Use this if you don't have any other hardware needs, since the peripheral struct is taken and dropped
40    /// internally and can't be used elsewhere. After the first call, always returns None.
41    ///
42    /// The LED generic parameter allows the user to specify what type of LED should control the LED hardware.
43    #[must_use]
44    pub fn init() -> Option<Self> {
45        if let (Some(dp), Some(cp)) = (
46            stm32f4xx_hal::pac::Peripherals::take(),
47            cortex_m::peripheral::Peripherals::take(),
48        ) {
49            let rcc = dp.RCC.constrain();
50            // Let's run as fast as we can, why not?
51            let clocks = rcc
52                .cfgr
53                .use_hse(8.MHz()) // Per UM1724 the ST-Link MCO is used as HSE on OSC_IN, fixed at 8 MHz
54                .bypass_hse_oscillator() // Bypass since it's not coming from a crystal
55                .sysclk(180.MHz()) // 180 MHz is max SYSCLK
56                .hclk(180.MHz()) // 180 MHz is max HCLK
57                .freeze();
58
59            let gpio_a = dp.GPIOA.split();
60            let gpio_c = dp.GPIOC.split();
61
62            let user_led = LED::build(gpio_a.pa5, dp.TIM2, &clocks);
63            let user_button = Button::new(gpio_c.pc13);
64            let vcom =
65                SerialPort::new(gpio_a.pa2, gpio_a.pa3, dp.USART2, &clocks, 9600.bps()).ok()?;
66            let delay = cp.SYST.delay(&clocks);
67
68            Some(Self {
69                user_led,
70                user_button,
71                vcom,
72                delay,
73            })
74        } else {
75            None
76        }
77    }
78}