blinky_timer_irq.rs 3.8 KB

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