//! Uses an RTC in standby mode to blink an LED for maximum power savings. #![no_std] #![no_main] use bsp::hal; use feather_m4 as bsp; #[cfg(not(feature = "use_semihosting"))] use panic_halt as _; #[cfg(feature = "use_semihosting")] use panic_semihosting as _; use bsp::entry; use hal::clock::GenericClockController; use hal::pac::{interrupt, CorePeripherals, Peripherals, Rtc}; use hal::prelude::*; use hal::rtc; use hal::sleeping_delay::SleepingDelay; use core::sync::atomic; use cortex_m::peripheral::NVIC; /// Shared atomic between RTC interrupt and sleeping_delay module static INTERRUPT_FIRED: atomic::AtomicBool = atomic::AtomicBool::new(false); #[entry] fn main() -> ! { // Configure all of our peripherals/clocks let mut peripherals = Peripherals::take().unwrap(); let mut core = CorePeripherals::take().unwrap(); let _clocks = GenericClockController::with_external_32kosc( peripherals.gclk, &mut peripherals.mclk, &mut peripherals.osc32kctrl, &mut peripherals.oscctrl, &mut peripherals.nvmctrl, ); // Configure the RTC. a 1024 Hz clock is configured for us when enabling our // main clock let timer = rtc::Rtc::count32_mode(peripherals.rtc, 1024.Hz(), &mut peripherals.mclk); let mut sleeping_delay = SleepingDelay::new(timer, &INTERRUPT_FIRED); // We can use the RTC in standby for maximum power savings core.SCB.set_sleepdeep(); // enable interrupts unsafe { core.NVIC.set_priority(interrupt::RTC, 2); NVIC::unmask(interrupt::RTC); } // Turn off unnecessary peripherals peripherals.mclk.ahbmask().modify(|_, w| { w.usb_().clear_bit(); w.dmac_().clear_bit() }); peripherals.mclk.apbamask().modify(|_, w| { w.eic_().clear_bit(); w.wdt_().clear_bit() }); peripherals.mclk.apbbmask().modify(|_, w| { w.usb_().clear_bit(); w.nvmctrl_().clear_bit(); w.dsu_().clear_bit() }); // Configure our red LED and blink forever, sleeping between! let pins = bsp::Pins::new(peripherals.port); let mut red_led = pins.d13.into_push_pull_output(); loop { red_led.set_low().unwrap(); sleeping_delay.delay_ms(1_000u32); red_led.set_high().unwrap(); sleeping_delay.delay_ms(100u32); } } #[interrupt] fn RTC() { // Let the sleepingtimer know that the interrupt fired, and clear it INTERRUPT_FIRED.store(true, atomic::Ordering::Relaxed); unsafe { Rtc::ptr() .as_ref() .unwrap() .mode0() .intflag() .modify(|_, w| w.cmp0().set_bit()); } }