stm32-hal2 1.8.2

Hardware abstraction layer for the STM32 MCUs
Documentation
//! For project structure and debugging boilerplate, see the `synax_overview` example.

#![no_main]
#![no_std]

use core::{
    cell::{Cell, RefCell},
    sync::atomic::{AtomicUsize, Ordering},
};

use cortex_m::{self, peripheral::NVIC};
use cortex_m_rt::entry;
use critical_section::{with, Mutex};
use stm32_hal::{
    clocks::Clocks,
    low_power::{self, StopMode},
    pac,
    rtc::{Rtc, RtcClockSource, RtcConfig},
};

make_globals!((RTC, Rtc));

#[entry]
fn main() -> ! {
    // Set up CPU peripherals
    let mut cp = cortex_m::Peripherals::take().unwrap();
    // Set up microcontroller peripherals
    let mut dp = pac::Peripherals::take().unwrap();

    let clock_cfg = Clocks::default();

    clock_cfg.setup().unwrap();

    // Set up the realtime clock.
    let mut rtc = Rtc::new(
        dp.RTC,
        RtcConfig {
            clock_source: RtcClockSource::Lse,
            bypass_lse_output: true, // eg if using a SMD oscillator.
            ..Default::default()
        },
    );

    rtc.set_12h_fmt(); // Optionally, use 12-hour format.

    // Set the RTC to trigger an interrupt every 30 seconds.
    rtc.set_wakeup(30.);

    // Store the RTC in a global variable that we can access in interrupts, using
    // critical sections.
    with(|cs| {
        RTC.borrow(cs).replace(Some(rtc));
    });

    // Unmask the interrupt line.
    unsafe {
        NVIC::unmask(pac::Interrupt::RTC_WKUP);
    }

    loop {
        // The RTC uses Chrono for dates, times, and datetimes. All of these are naive.
        let date = rtc.get_date();
        let time = rtc.get_time();
        let dt = rtc.get_datetime();

        // See also: `get_seconds()`, `get_day()` etc.
        let hours = rtc.get_hours();

        // Enter a low power mode.
        low_power::stop(StopMode::One);

        // Turn back on the PLL, which is disabled by setting `stop` mode.
        clock_cfg.reselect_input();
    }
}

// todo: Alarms.

#[interrupt]
/// RTC wakeup handler
fn RTC_WKUP() {
    with(|cs| {
        // Reset pending bit for interrupt line
        unsafe {
            (*pac::EXTI::ptr()).pr1.modify(|_, w| w.pr20().set_bit());
        }
        access_global!(RTC, rtc, cs);
        rtc.clear_wakeup_flag();

        // Do something.
    });
}

// same panicking *behavior* as `panic-probe` but doesn't print a panic message
// this prevents the panic message being printed *twice* when `defmt::panic` is invoked
#[defmt::panic_handler]
fn panic() -> ! {
    cortex_m::asm::udf()
}