Skip to content

Commit 25e734f

Browse files
khrsTheZoq2
andauthored
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>
1 parent 1b32169 commit 25e734f

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ required-features = ["rt", "stm32-usbd"]
116116
name = "blinky_timer_irq"
117117
required-features = ["rt"]
118118

119+
[[example]]
120+
name = "blinky_rtcalarm_irq"
121+
required-features = ["rt"]
122+
119123
[[example]]
120124
name = "qei"
121125
required-features = ["medium"]

examples/blinky_rtcalarm_irq.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//! Blinks an LED
2+
//!
3+
//! This assumes that a LED is connected to pc13 as is the case on the blue pill board.
4+
//!
5+
//! Please note according to RM0008:
6+
//! "Due to the fact that the switch only sinks a limited amount of current (3 mA), the use of
7+
//! GPIOs PC13 to PC15 in output mode is restricted: the speed has to be limited to 2MHz with
8+
//! a maximum load of 30pF and these IOs must not be used as a current source (e.g. to drive a LED)"
9+
10+
#![no_std]
11+
#![no_main]
12+
13+
use panic_halt as _;
14+
15+
use stm32f1xx_hal as hal;
16+
17+
use crate::hal::{
18+
gpio::{gpioc, Output, PushPull},
19+
pac::{interrupt, Interrupt, Peripherals, EXTI},
20+
prelude::*,
21+
rtc::Rtc,
22+
};
23+
24+
use core::cell::RefCell;
25+
use cortex_m::{asm::wfi, interrupt::Mutex};
26+
use cortex_m_rt::entry;
27+
use embedded_hal::digital::v2::OutputPin;
28+
29+
// A type definition for the GPIO pin to be used for our LED
30+
type LEDPIN = gpioc::PC13<Output<PushPull>>;
31+
32+
// Make LED pin globally available
33+
static G_LED: Mutex<RefCell<Option<LEDPIN>>> = Mutex::new(RefCell::new(None));
34+
// Make RTC globally available
35+
static G_RTC: Mutex<RefCell<Option<Rtc>>> = Mutex::new(RefCell::new(None));
36+
// Make EXTI registers globally available
37+
static G_EXTI: Mutex<RefCell<Option<EXTI>>> = Mutex::new(RefCell::new(None));
38+
39+
// Toggle LED every 3 seconds
40+
const TOGGLE_INTERVAL_SECONDS: u32 = 3;
41+
42+
// The f100 does not have an RTC, so this example is disabled
43+
#[cfg(feature = "stm32f101")]
44+
#[entry]
45+
fn main() -> ! {
46+
loop {
47+
continue;
48+
}
49+
}
50+
51+
#[cfg(not(feature = "stm32f101"))]
52+
#[interrupt]
53+
fn RTCALARM() {
54+
static mut LED: Option<LEDPIN> = None;
55+
static mut RTC: Option<Rtc> = None;
56+
static mut EXTI: Option<EXTI> = None;
57+
58+
let led = LED.get_or_insert_with(|| {
59+
cortex_m::interrupt::free(|cs| G_LED.borrow(cs).replace(None).unwrap())
60+
});
61+
let rtc = RTC.get_or_insert_with(|| {
62+
cortex_m::interrupt::free(|cs| G_RTC.borrow(cs).replace(None).unwrap())
63+
});
64+
let exti = EXTI.get_or_insert_with(|| {
65+
cortex_m::interrupt::free(|cs| G_EXTI.borrow(cs).replace(None).unwrap())
66+
});
67+
68+
exti.pr.write(|w| w.pr17().set_bit());
69+
rtc.set_alarm(rtc.current_time() + TOGGLE_INTERVAL_SECONDS);
70+
71+
let _ = led.toggle();
72+
}
73+
74+
#[cfg(not(feature = "stm32f101"))]
75+
#[entry]
76+
fn main() -> ! {
77+
let dp = Peripherals::take().unwrap();
78+
79+
let mut pwr = dp.PWR;
80+
let mut rcc = dp.RCC.constrain();
81+
82+
// Set up the GPIO pin
83+
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
84+
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
85+
let _ = led.set_high(); // Turn off
86+
87+
cortex_m::interrupt::free(|cs| *G_LED.borrow(cs).borrow_mut() = Some(led));
88+
89+
// Set up the EXTI (see notes in section 18.4.2 of reference manual)
90+
let exti = dp.EXTI;
91+
exti.ftsr.write(|w| w.tr17().set_bit());
92+
exti.imr.write(|w| w.mr17().set_bit());
93+
94+
cortex_m::interrupt::free(|cs| *G_EXTI.borrow(cs).borrow_mut() = Some(exti));
95+
96+
// Set up the RTC
97+
// Enable writes to the backup domain
98+
let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut rcc.apb1, &mut pwr);
99+
// Start the RTC
100+
let mut rtc = Rtc::rtc(dp.RTC, &mut backup_domain);
101+
rtc.set_time(0);
102+
rtc.set_alarm(TOGGLE_INTERVAL_SECONDS);
103+
rtc.listen_alarm();
104+
105+
cortex_m::interrupt::free(|cs| *G_RTC.borrow(cs).borrow_mut() = Some(rtc));
106+
107+
// Enable RTCALARM IRQ
108+
unsafe { cortex_m::peripheral::NVIC::unmask(Interrupt::RTCALARM) };
109+
110+
loop {
111+
wfi();
112+
}
113+
}

0 commit comments

Comments
 (0)