Skip to content

Commit

Permalink
Use EXTI helpers to access different registers depending on CPU
Browse files Browse the repository at this point in the history
  • Loading branch information
mattico committed Oct 8, 2020
1 parent 0303d7a commit a6346da
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 27 deletions.
7 changes: 4 additions & 3 deletions examples/rtc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static RTC: Mutex<RefCell<Option<rtc::Rtc>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
logger::init();
let dp = pac::Peripherals::take().unwrap();
let mut dp = pac::Peripherals::take().unwrap();

// Constrain and Freeze power
info!("Setup PWR... ");
Expand Down Expand Up @@ -54,7 +54,7 @@ fn main() -> ! {

rtc.set_date_time(now);
rtc.enable_wakeup(10);
rtc.listen(rtc::Event::Wakeup);
rtc.listen(&mut dp.EXTI, rtc::Event::Wakeup);

unsafe {
pac::NVIC::unmask(interrupt::RTC_WKUP);
Expand All @@ -79,7 +79,8 @@ fn RTC_WKUP() {
let mut rc = RTC.borrow(cs).borrow_mut();
let rtc = rc.as_mut().unwrap();
let date_time = rtc.date_time().unwrap();
rtc.unpend(rtc::Event::Wakeup);
let exti = unsafe { &mut pac::Peripherals::steal().EXTI };
rtc.unpend(exti, rtc::Event::Wakeup);
date_time
});
info!("Time: {}", date_time);
Expand Down
45 changes: 21 additions & 24 deletions src/rtc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use cast::{f32, i32, u16, u32, u8};
use chrono::prelude::*;

use crate::exti::{Event as ExtiEvent, ExtiExt};
use crate::rcc::backup;
use crate::rcc::rec::ResetEnable;
use crate::rcc::CoreClocks;
Expand Down Expand Up @@ -707,7 +708,7 @@ impl Rtc {
// TODO: Alarms

/// Start listening for `event`
pub fn listen(&mut self, event: Event) {
pub fn listen(&mut self, exti: &mut EXTI, event: Event) {
// RTC interrupts aren't connected directly to the NVIC but are routed through the EXTI,
// I suppose so that they can use the EXTI's ability to wakeup the CPU or other things.
// We need to also enable the interrupt in the EXTI.
Expand All @@ -718,69 +719,67 @@ impl Rtc {
// EXTI 19 = RTC Wakeup Timer

// unsafe: Only we can use these bits for anything
let exti = unsafe { &*EXTI::ptr() };
let rcc = unsafe { &*RCC::ptr() };

match event {
Event::LseCss => {
exti.cpuimr1.modify(|_, w| w.mr18().unmasked());
exti.listen(ExtiEvent::RTC_OTHER);
exti.rtsr1.modify(|_, w| w.tr18().enabled());
rcc.cier.modify(|_, w| w.lsecssie().enabled());
}
Event::AlarmA => {
exti.cpuimr1.modify(|_, w| w.mr17().unmasked());
exti.listen(ExtiEvent::RTC_ALARM);
exti.rtsr1.modify(|_, w| w.tr17().enabled());
self.reg.cr.modify(|_, w| w.alraie().set_bit());
}
Event::AlarmB => {
exti.cpuimr1.modify(|_, w| w.mr17().unmasked());
exti.listen(ExtiEvent::RTC_ALARM);
exti.rtsr1.modify(|_, w| w.tr17().enabled());
self.reg.cr.modify(|_, w| w.alrbie().set_bit());
}
Event::Wakeup => {
exti.cpuimr1.modify(|_, w| w.mr19().unmasked());
exti.listen(ExtiEvent::RTC_WAKEUP);
exti.rtsr1.modify(|_, w| w.tr19().enabled());
self.reg.cr.modify(|_, w| w.wutie().set_bit());
}
Event::Timestamp => {
exti.cpuimr1.modify(|_, w| w.mr18().unmasked());
exti.listen(ExtiEvent::RTC_OTHER);
exti.rtsr1.modify(|_, w| w.tr18().enabled());
self.reg.cr.modify(|_, w| w.tsie().set_bit());
}
}
}

/// Stop listening for `event`
pub fn unlisten(&mut self, event: Event) {
pub fn unlisten(&mut self, exti: &mut EXTI, event: Event) {
// See the note in listen() about EXTI
// unsafe: Only we can use these bits for anything
let exti = unsafe { &*EXTI::ptr() };
let rcc = unsafe { &*RCC::ptr() };

match event {
Event::LseCss => {
rcc.cier.modify(|_, w| w.lsecssie().disabled());
exti.cpuimr1.modify(|_, w| w.mr18().masked());
exti.listen(ExtiEvent::RTC_OTHER);
exti.rtsr1.modify(|_, w| w.tr18().disabled());
}
Event::AlarmA => {
self.reg.cr.modify(|_, w| w.alraie().clear_bit());
exti.cpuimr1.modify(|_, w| w.mr17().masked());
exti.listen(ExtiEvent::RTC_ALARM);
exti.rtsr1.modify(|_, w| w.tr17().disabled());
}
Event::AlarmB => {
self.reg.cr.modify(|_, w| w.alrbie().clear_bit());
exti.cpuimr1.modify(|_, w| w.mr17().masked());
exti.listen(ExtiEvent::RTC_ALARM);
exti.rtsr1.modify(|_, w| w.tr17().disabled());
}
Event::Wakeup => {
self.reg.cr.modify(|_, w| w.wutie().clear_bit());
exti.cpuimr1.modify(|_, w| w.mr19().masked());
exti.listen(ExtiEvent::RTC_WAKEUP);
exti.rtsr1.modify(|_, w| w.tr19().disabled());
}
Event::Timestamp => {
self.reg.cr.modify(|_, w| w.tsie().clear_bit());
exti.cpuimr1.modify(|_, w| w.mr18().masked());
exti.listen(ExtiEvent::RTC_OTHER);
exti.rtsr1.modify(|_, w| w.tr18().disabled());
}
}
Expand All @@ -801,52 +800,50 @@ impl Rtc {
}

/// Clears the interrupt flag for `event`
pub fn unpend(&mut self, event: Event) {
pub fn unpend(&mut self, exti: &mut EXTI, event: Event) {
// See the note in listen() about EXTI
// unsafe: Only we can do anything with these bits
let exti = unsafe { &*EXTI::ptr() };
let rcc = unsafe { &*RCC::ptr() };

match event {
Event::LseCss => {
rcc.cicr.write(|w| w.lsecssc().clear());
exti.cpupr1.write(|w| w.pr18().clear());
exti.unpend(ExtiEvent::RTC_OTHER);
}
Event::AlarmA => {
self.reg.isr.modify(|_, w| w.alraf().clear_bit());
exti.cpupr1.write(|w| w.pr17().clear());
exti.unpend(ExtiEvent::RTC_ALARM);
}
Event::AlarmB => {
self.reg.isr.modify(|_, w| w.alrbf().clear_bit());
exti.cpupr1.write(|w| w.pr17().clear());
exti.unpend(ExtiEvent::RTC_ALARM);
}
Event::Wakeup => {
self.reg.isr.modify(|_, w| w.wutf().clear_bit());
exti.cpupr1.write(|w| w.pr19().clear());
exti.unpend(ExtiEvent::RTC_WAKEUP);
}
Event::Timestamp => {
self.reg.isr.modify(|_, w| w.tsf().clear_bit());
exti.cpupr1.write(|w| w.pr18().clear());
exti.unpend(ExtiEvent::RTC_OTHER);
}
}
}

/// Handle a Clock Security Subsystem failure for the LSE clock
///
/// Disables the LSE, disables the LSE CSS, and changes the RTC to use the LSI clock.
/// You may want to call `clear_date_time()`.
/// You may want to call `clear_date_time()`. You still need to unpend the LSECSS interrupt.
pub fn handle_lse_css(&mut self) {
if !self.is_pending(Event::LseCss) {
return;
}

// unsafe: Only we can use these bits
let rcc = unsafe { &*RCC::ptr() };
rcc.bdcr
.modify(|_, w| w.lsecsson().security_off().lseon().off());

// We're allowed to change this once after the LSE fails
self.prec.kernel_clk_mux(backup::RtcClkSel::LSI);

self.unpend(Event::LseCss);
}
}

0 comments on commit a6346da

Please sign in to comment.