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}