#![no_main]
#![no_std]
use cortex_m_rt::entry;
use critical_section::with;
use stm32_hal::{
adc::{Adc, AdcChannel},
clocks::Clocks,
gpio::{Edge, Pin, PinMode, Port},
low_power, make_simple_globals,
pac::{self, ADC1, EXTI, interrupt},
rtc::{Rtc, RtcClockSource, RtcConfig},
setup_nvic,
timer::{Timer, TimerInterrupt},
};
make_simple_globals!((SENSOR_READING, f32, 335.), (BOUNCING, bool, false));
make_globals!((ADC, ADC<ADC1>),);
#[entry]
fn main() -> ! {
let mut cp = cortex_m::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();
let clock_cfg = Clocks::default();
clock_cfg.setup().unwrap();
let mut button = Pin::new(Port::A, 0, PinMode::Input);
button.enable_interrupt(Edge::Falling);
let mut timer = Timer::new_tim3(dp.TIM3, 0.2, Default::default(), &clock_cfg);
timer.enable_interrupt(TimerInterrupt::Update); timer.enable();
let mut debounce_timer = Timer::new_tim15(dp.TIM15, 5., Default::default(), &clock_cfg);
debounce_timer.enable_interrupt(TimerInterrupt::Update);
let mut rtc = Rtc::new(
dp.RTC,
&mut dp.PWR,
RtcConfig {
clock_source: RtcClockSource::Lse,
..Default::default()
},
);
rtc.set_wakeup(&mut dp.EXTI, 30.);
let mut adc = Adc::new_adc1(
dp.ADC1,
Default::default(),
clock_cfg.systick(),
);
adc.enable_interrupt(AdcInterrupt::EndOfConversion);
with(|cs| {
ADC.borrow(cs).replace(Some(adc));
});
setup_nvic!([(EXTI0, 0), (TIM3, 1), (TIM15, 2), (RTC_WKUP, 2),], cp);
loop {
low_power::stop(low_power::StopMode::Two);
clocks.reselect_input();
}
}
#[interrupt]
fn EXTI0() {
gpio::clear_exti_interrupt(0);
with(|cs| {
let bouncing = BOUNCING.borrow(cs);
if bouncing.get() {
return;
}
unsafe { (*pac::TIM15::ptr()).cr1().modify(|_, w| w.cen().bit(true)) }
bouncing.set(true);
let mut s = ADC.borrow(cs).borrow_mut();
let sensor = s.as_mut().unwrap();
let reading = sensor.read(AdcChannel::C1).unwrap();
SENSOR_READING.borrow(cs).replace(reading);
});
}
#[interrupt]
fn RTC_WKUP() {
with(|cs| {
unsafe {
gpio::clear_exti_interrupt(20);
(*pac::RTC::ptr()).wpr.write(|w| w.bits(0xCA));
(*pac::RTC::ptr()).wpr.write(|w| w.bits(0x53));
(*pac::RTC::ptr()).cr().modify(|_, w| w.wute().clear_bit());
(*pac::RTC::ptr()).isr().modify(|_, w| w.wutf().clear_bit());
(*pac::RTC::ptr()).cr().modify(|_, w| w.wute().bit(true));
(*pac::RTC::ptr()).wpr.write(|w| w.bits(0xFF));
}
});
}
#[interrupt]
fn TIM3() {
timer::clear_update_interrupt(3);
}
#[interrupt]
fn TIM15() {
timer::clear_update_interrupt(15);
with(|cs| {
BOUNCING.borrow(cs).set(false);
unsafe {
(*pac::TIM15::ptr())
.cr1()
.modify(|_, w| w.cen().clear_bit())
}
});
}
#[defmt::panic_handler]
fn panic() -> ! {
cortex_m::asm::udf()
}