From 49dc85c29507b22756f5b333c02b493081f0fe8b Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Sun, 2 Feb 2020 13:28:32 +0100 Subject: [PATCH] Add a new timer and interrupt based blinky example Signed-off-by: Daniel Egger --- CHANGELOG.md | 4 ++ Cargo.toml | 8 ++- examples/blinky_timer_irq.rs | 98 ++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 examples/blinky_timer_irq.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5369949..d99d0eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- Another blinky example using a timer interrupt + ### Changed - Added "bypass" parameter to Rcc HSE configuration (breaking change) diff --git a/Cargo.toml b/Cargo.toml index 9f30f26..f58cbd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,13 +77,17 @@ debug = true opt-level = "s" [[example]] -name = "led_hal_button_irq" -required-features = ["stm32f042", "rt"] +name = "blinky_timer_irq" +required-features = ["stm32f072", "rt"] [[example]] name = "dac" required-features = ["stm32f072"] +[[example]] +name = "led_hal_button_irq" +required-features = ["stm32f042", "rt"] + [[example]] name = "usb_serial" required-features = ["rt", "stm32f042", "stm32-usbd"] diff --git a/examples/blinky_timer_irq.rs b/examples/blinky_timer_irq.rs new file mode 100644 index 0000000..8a3b474 --- /dev/null +++ b/examples/blinky_timer_irq.rs @@ -0,0 +1,98 @@ +#![no_main] +#![no_std] + +use panic_halt as _; + +use stm32f0xx_hal as hal; + +use crate::hal::{ + gpio::*, + prelude::*, + stm32::{interrupt, Interrupt, Peripherals, TIM7}, + time::Hertz, + timers::*, +}; + +use cortex_m_rt::entry; + +use core::cell::RefCell; +use cortex_m::{interrupt::Mutex, peripheral::Peripherals as c_m_Peripherals}; + +// A type definition for the GPIO pin to be used for our LED +type LEDPIN = gpioa::PA5>; + +// Make LED pin globally available +static GLED: Mutex>> = Mutex::new(RefCell::new(None)); + +// Make timer interrupt registers globally available +static GINT: Mutex>>> = Mutex::new(RefCell::new(None)); + +// Define an interupt handler, i.e. function to call when interrupt occurs. Here if our external +// interrupt trips when the timer timed out +#[interrupt] +fn TIM7() { + static mut LED: Option = None; + static mut INT: Option> = None; + + let led = LED.get_or_insert_with(|| { + cortex_m::interrupt::free(|cs| { + // Move LED pin here, leaving a None in its place + GLED.borrow(cs).replace(None).unwrap() + }) + }); + + let int = INT.get_or_insert_with(|| { + cortex_m::interrupt::free(|cs| { + // Move LED pin here, leaving a None in its place + GINT.borrow(cs).replace(None).unwrap() + }) + }); + + led.toggle().ok(); + int.wait().ok(); +} + +#[entry] +fn main() -> ! { + if let (Some(mut p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) { + cortex_m::interrupt::free(move |cs| { + let mut rcc = p + .RCC + .configure() + .hsi48() + .enable_crs(p.CRS) + .sysclk(48.mhz()) + .pclk(24.mhz()) + .freeze(&mut p.FLASH); + + let gpioa = p.GPIOA.split(&mut rcc); + + // (Re-)configure PA5 as output + let led = gpioa.pa5.into_push_pull_output(cs); + + // Move the pin into our global storage + *GLED.borrow(cs).borrow_mut() = Some(led); + + // Set up a timer expiring after 1s + let mut timer = Timer::tim7(p.TIM7, Hertz(1), &mut rcc); + + // Generate an interrupt when the timer expires + timer.listen(Event::TimeOut); + + // Move the timer into our global storage + *GINT.borrow(cs).borrow_mut() = Some(timer); + + // Enable TIM7 IRQ, set prio 1 and clear any pending IRQs + let mut nvic = cp.NVIC; + unsafe { + nvic.set_priority(Interrupt::TIM7, 1); + cortex_m::peripheral::NVIC::unmask(Interrupt::TIM7); + } + cortex_m::peripheral::NVIC::unpend(Interrupt::TIM7); + }); + } + + loop { + continue; + } +}