瀏覽代碼

Add blinky_rtcalarm_irq example (#217)

* Add blinky_rtcalarm_irq example

* Cleanup blinky_rtcalarm_irq example.

* Fix broken example on stm32f100

Co-authored-by: TheZoq2 <frans.skarman@protonmail.com>
Karol Harasim 3 年之前
父節點
當前提交
25e734fd77
共有 2 個文件被更改,包括 117 次插入0 次删除
  1. 4 0
      Cargo.toml
  2. 113 0
      examples/blinky_rtcalarm_irq.rs

+ 4 - 0
Cargo.toml

@@ -116,6 +116,10 @@ required-features = ["rt", "stm32-usbd"]
 name = "blinky_timer_irq"
 required-features = ["rt"]
 
+[[example]]
+name = "blinky_rtcalarm_irq"
+required-features = ["rt"]
+
 [[example]]
 name = "qei"
 required-features = ["medium"]

+ 113 - 0
examples/blinky_rtcalarm_irq.rs

@@ -0,0 +1,113 @@
+//! Blinks an LED
+//!
+//! This assumes that a LED is connected to pc13 as is the case on the blue pill board.
+//!
+//! Please note according to RM0008:
+//! "Due to the fact that the switch only sinks a limited amount of current (3 mA), the use of
+//! GPIOs PC13 to PC15 in output mode is restricted: the speed has to be limited to 2MHz with
+//! a maximum load of 30pF and these IOs must not be used as a current source (e.g. to drive a LED)"
+
+#![no_std]
+#![no_main]
+
+use panic_halt as _;
+
+use stm32f1xx_hal as hal;
+
+use crate::hal::{
+    gpio::{gpioc, Output, PushPull},
+    pac::{interrupt, Interrupt, Peripherals, EXTI},
+    prelude::*,
+    rtc::Rtc,
+};
+
+use core::cell::RefCell;
+use cortex_m::{asm::wfi, interrupt::Mutex};
+use cortex_m_rt::entry;
+use embedded_hal::digital::v2::OutputPin;
+
+// A type definition for the GPIO pin to be used for our LED
+type LEDPIN = gpioc::PC13<Output<PushPull>>;
+
+// Make LED pin globally available
+static G_LED: Mutex<RefCell<Option<LEDPIN>>> = Mutex::new(RefCell::new(None));
+// Make RTC globally available
+static G_RTC: Mutex<RefCell<Option<Rtc>>> = Mutex::new(RefCell::new(None));
+// Make EXTI registers globally available
+static G_EXTI: Mutex<RefCell<Option<EXTI>>> = Mutex::new(RefCell::new(None));
+
+// Toggle LED every 3 seconds
+const TOGGLE_INTERVAL_SECONDS: u32 = 3;
+
+// The f100 does not have an RTC, so this example is disabled
+#[cfg(feature = "stm32f101")]
+#[entry]
+fn main() -> ! {
+    loop {
+        continue;
+    }
+}
+
+#[cfg(not(feature = "stm32f101"))]
+#[interrupt]
+fn RTCALARM() {
+    static mut LED: Option<LEDPIN> = None;
+    static mut RTC: Option<Rtc> = None;
+    static mut EXTI: Option<EXTI> = None;
+
+    let led = LED.get_or_insert_with(|| {
+        cortex_m::interrupt::free(|cs| G_LED.borrow(cs).replace(None).unwrap())
+    });
+    let rtc = RTC.get_or_insert_with(|| {
+        cortex_m::interrupt::free(|cs| G_RTC.borrow(cs).replace(None).unwrap())
+    });
+    let exti = EXTI.get_or_insert_with(|| {
+        cortex_m::interrupt::free(|cs| G_EXTI.borrow(cs).replace(None).unwrap())
+    });
+
+    exti.pr.write(|w| w.pr17().set_bit());
+    rtc.set_alarm(rtc.current_time() + TOGGLE_INTERVAL_SECONDS);
+
+    let _ = led.toggle();
+}
+
+#[cfg(not(feature = "stm32f101"))]
+#[entry]
+fn main() -> ! {
+    let dp = Peripherals::take().unwrap();
+
+    let mut pwr = dp.PWR;
+    let mut rcc = dp.RCC.constrain();
+
+    // Set up the GPIO pin
+    let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
+    let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
+    let _ = led.set_high(); // Turn off
+
+    cortex_m::interrupt::free(|cs| *G_LED.borrow(cs).borrow_mut() = Some(led));
+
+    // Set up the EXTI (see notes in section 18.4.2 of reference manual)
+    let exti = dp.EXTI;
+    exti.ftsr.write(|w| w.tr17().set_bit());
+    exti.imr.write(|w| w.mr17().set_bit());
+
+    cortex_m::interrupt::free(|cs| *G_EXTI.borrow(cs).borrow_mut() = Some(exti));
+
+    // Set up the RTC
+    // Enable writes to the backup domain
+    let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut rcc.apb1, &mut pwr);
+    // Start the RTC
+    let mut rtc = Rtc::rtc(dp.RTC, &mut backup_domain);
+    rtc.set_time(0);
+    rtc.set_alarm(TOGGLE_INTERVAL_SECONDS);
+    rtc.listen_alarm();
+
+    cortex_m::interrupt::free(|cs| *G_RTC.borrow(cs).borrow_mut() = Some(rtc));
+
+    // Enable RTCALARM IRQ
+    unsafe { cortex_m::peripheral::NVIC::unmask(Interrupt::RTCALARM) };
+
+    loop {
+        wfi();
+    }
+}