Skip to content

Commit

Permalink
examples/blinky_timer_irq.rs: added an '#[interrupt]' blinky demo
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Manning committed Feb 20, 2020
1 parent 85851d1 commit 8a25787
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,8 @@ required-features = ["rt", "stm32f103", "stm32-usbd"]
[[example]]
name = "usb_serial_rtfm"
required-features = ["rt", "stm32f103", "stm32-usbd"]

[[example]]
name = "blinky_timer_irq"
required-features = ["medium", "rt", "stm32f103"]

116 changes: 116 additions & 0 deletions examples/blinky_timer_irq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// blinky timer using interrupts on TIM2
//
// This demo based off of the following demo:
// - https://github.com/stm32-rs/stm32f0xx-hal/blob/master/examples/blinky_timer_irq.rs
// with some information about STM32F1 interrupts/peripherals from:
// - https://github.com/geomatsi/rust-blue-pill-tests/blob/master/src/bin/blink-timer-irq-safe.rs

#![no_main]
#![no_std]

use panic_halt as _;

use stm32f1xx_hal as hal;

use crate::hal::{
gpio::*,
prelude::*,
stm32::{interrupt, Interrupt, Peripherals, TIM2},
timer::*,
};

use core::cell::RefCell;
use cortex_m::{
asm::wfi,
interrupt::Mutex,
peripheral::Peripherals as c_m_Peripherals};
use cortex_m_rt::entry;

// NOTE You can uncomment 'hprintln' here and in the code below for a bit more
// verbosity at runtime, at the cost of throwing off the timing of the blink
// (using 'semihosting' for printing debug info anywhere slows program
// execution down)
//use cortex_m_semihosting::hprintln;

// 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 timer interrupt registers globally available
static G_TIM: Mutex<RefCell<Option<CountDownTimer<TIM2>>>> = Mutex::new(RefCell::new(None));

// Define an interupt handler, i.e. function to call when interrupt occurs.
// This specific interrupt will "trip" when the timer TIM2 times out
#[interrupt]
fn TIM2() {
static mut LED: Option<LEDPIN> = None;
static mut TIM: Option<CountDownTimer<TIM2>> = None;

let led = LED.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {
// Move LED pin here, leaving a None in its place
G_LED.borrow(cs).replace(None).unwrap()
})
});

let tim = TIM.get_or_insert_with(|| {
cortex_m::interrupt::free(|cs| {
// Move LED pin here, leaving a None in its place
G_TIM.borrow(cs).replace(None).unwrap()
})
});

//hprintln!("TIM2 IRQ fired").unwrap();
led.toggle().ok();
tim.wait().ok();
}

#[entry]
fn main() -> ! {
if let (Some(dp), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
cortex_m::interrupt::free(move |cs| {
let mut rcc = dp.RCC.constrain();
let mut flash = dp.FLASH.constrain();
let clocks = rcc
.cfgr
.sysclk(8.mhz())
.pclk1(8.mhz())
.freeze(&mut flash.acr);

// Configure PC13 pin to blink LED
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
let led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);

// Move the pin into our global storage
*G_LED.borrow(cs).borrow_mut() = Some(led);

// Set up a timer expiring after 1s
let mut timer = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1).start_count_down(1.hz());

// Generate an interrupt when the timer expires
timer.listen(Event::Update);

// Move the timer into our global storage
*G_TIM.borrow(cs).borrow_mut() = Some(timer);

// Enable TIM2 IRQ, set prio 1 and clear any pending IRQs
let mut nvic = cp.NVIC;
// Calling 'set_priority()' and 'unmask()' requires 'unsafe {}'
// - https://docs.rs/stm32f1xx-hal/0.5.3/stm32f1xx_hal/stm32/struct.NVIC.html#method.set_priority
unsafe {
nvic.set_priority(Interrupt::TIM2, 1);
cortex_m::peripheral::NVIC::unmask(Interrupt::TIM2);
}
// Clear the interrupt state
cortex_m::peripheral::NVIC::unpend(Interrupt::TIM2);
});
}

//hprintln!("Entering main loop...").unwrap();
loop {
// From 'cortex_m::asm::wfi'
wfi();
}
}

0 comments on commit 8a25787

Please sign in to comment.