Skip to content

Commit 8a25787

Browse files
author
Brian Manning
committed
examples/blinky_timer_irq.rs: added an '#[interrupt]' blinky demo
1 parent 85851d1 commit 8a25787

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,8 @@ required-features = ["rt", "stm32f103", "stm32-usbd"]
114114
[[example]]
115115
name = "usb_serial_rtfm"
116116
required-features = ["rt", "stm32f103", "stm32-usbd"]
117+
118+
[[example]]
119+
name = "blinky_timer_irq"
120+
required-features = ["medium", "rt", "stm32f103"]
121+

examples/blinky_timer_irq.rs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// blinky timer using interrupts on TIM2
2+
//
3+
// This demo based off of the following demo:
4+
// - https://github.com/stm32-rs/stm32f0xx-hal/blob/master/examples/blinky_timer_irq.rs
5+
// with some information about STM32F1 interrupts/peripherals from:
6+
// - https://github.com/geomatsi/rust-blue-pill-tests/blob/master/src/bin/blink-timer-irq-safe.rs
7+
8+
#![no_main]
9+
#![no_std]
10+
11+
use panic_halt as _;
12+
13+
use stm32f1xx_hal as hal;
14+
15+
use crate::hal::{
16+
gpio::*,
17+
prelude::*,
18+
stm32::{interrupt, Interrupt, Peripherals, TIM2},
19+
timer::*,
20+
};
21+
22+
use core::cell::RefCell;
23+
use cortex_m::{
24+
asm::wfi,
25+
interrupt::Mutex,
26+
peripheral::Peripherals as c_m_Peripherals};
27+
use cortex_m_rt::entry;
28+
29+
// NOTE You can uncomment 'hprintln' here and in the code below for a bit more
30+
// verbosity at runtime, at the cost of throwing off the timing of the blink
31+
// (using 'semihosting' for printing debug info anywhere slows program
32+
// execution down)
33+
//use cortex_m_semihosting::hprintln;
34+
35+
// A type definition for the GPIO pin to be used for our LED
36+
type LEDPIN = gpioc::PC13<Output<PushPull>>;
37+
38+
// Make LED pin globally available
39+
static G_LED: Mutex<RefCell<Option<LEDPIN>>> = Mutex::new(RefCell::new(None));
40+
41+
// Make timer interrupt registers globally available
42+
static G_TIM: Mutex<RefCell<Option<CountDownTimer<TIM2>>>> = Mutex::new(RefCell::new(None));
43+
44+
// Define an interupt handler, i.e. function to call when interrupt occurs.
45+
// This specific interrupt will "trip" when the timer TIM2 times out
46+
#[interrupt]
47+
fn TIM2() {
48+
static mut LED: Option<LEDPIN> = None;
49+
static mut TIM: Option<CountDownTimer<TIM2>> = None;
50+
51+
let led = LED.get_or_insert_with(|| {
52+
cortex_m::interrupt::free(|cs| {
53+
// Move LED pin here, leaving a None in its place
54+
G_LED.borrow(cs).replace(None).unwrap()
55+
})
56+
});
57+
58+
let tim = TIM.get_or_insert_with(|| {
59+
cortex_m::interrupt::free(|cs| {
60+
// Move LED pin here, leaving a None in its place
61+
G_TIM.borrow(cs).replace(None).unwrap()
62+
})
63+
});
64+
65+
//hprintln!("TIM2 IRQ fired").unwrap();
66+
led.toggle().ok();
67+
tim.wait().ok();
68+
}
69+
70+
#[entry]
71+
fn main() -> ! {
72+
if let (Some(dp), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
73+
cortex_m::interrupt::free(move |cs| {
74+
let mut rcc = dp.RCC.constrain();
75+
let mut flash = dp.FLASH.constrain();
76+
let clocks = rcc
77+
.cfgr
78+
.sysclk(8.mhz())
79+
.pclk1(8.mhz())
80+
.freeze(&mut flash.acr);
81+
82+
// Configure PC13 pin to blink LED
83+
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
84+
let led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
85+
86+
// Move the pin into our global storage
87+
*G_LED.borrow(cs).borrow_mut() = Some(led);
88+
89+
// Set up a timer expiring after 1s
90+
let mut timer = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1).start_count_down(1.hz());
91+
92+
// Generate an interrupt when the timer expires
93+
timer.listen(Event::Update);
94+
95+
// Move the timer into our global storage
96+
*G_TIM.borrow(cs).borrow_mut() = Some(timer);
97+
98+
// Enable TIM2 IRQ, set prio 1 and clear any pending IRQs
99+
let mut nvic = cp.NVIC;
100+
// Calling 'set_priority()' and 'unmask()' requires 'unsafe {}'
101+
// - https://docs.rs/stm32f1xx-hal/0.5.3/stm32f1xx_hal/stm32/struct.NVIC.html#method.set_priority
102+
unsafe {
103+
nvic.set_priority(Interrupt::TIM2, 1);
104+
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM2);
105+
}
106+
// Clear the interrupt state
107+
cortex_m::peripheral::NVIC::unpend(Interrupt::TIM2);
108+
});
109+
}
110+
111+
//hprintln!("Entering main loop...").unwrap();
112+
loop {
113+
// From 'cortex_m::asm::wfi'
114+
wfi();
115+
}
116+
}

0 commit comments

Comments
 (0)