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
1+ //! blinky timer using interrupts on TIM2
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)"
79
810#![ no_main]
911#![ no_std]
@@ -13,15 +15,16 @@ use panic_halt as _;
1315use stm32f1xx_hal as hal;
1416
1517use crate :: hal:: {
16- gpio:: * ,
18+ gpio:: { gpioc , Output , PushPull } ,
1719 pac:: { interrupt, Interrupt , Peripherals , TIM2 } ,
1820 prelude:: * ,
19- timer:: * ,
21+ timer:: { CountDownTimer , Event , Timer } ,
2022} ;
2123
2224use core:: cell:: RefCell ;
23- use cortex_m:: { asm:: wfi, interrupt:: Mutex , peripheral :: Peripherals as c_m_Peripherals } ;
25+ use cortex_m:: { asm:: wfi, interrupt:: Mutex } ;
2426use cortex_m_rt:: entry;
27+ use embedded_hal:: digital:: v2:: OutputPin ;
2528
2629// NOTE You can uncomment 'hprintln' here and in the code below for a bit more
2730// verbosity at runtime, at the cost of throwing off the timing of the blink
@@ -59,55 +62,44 @@ fn TIM2() {
5962 } )
6063 } ) ;
6164
62- //hprintln!("TIM2 IRQ fired").unwrap();
63- led. toggle ( ) . ok ( ) ;
64- tim. wait ( ) . ok ( ) ;
65+ let _ = led. toggle ( ) ;
66+ let _ = tim. wait ( ) ;
6567}
6668
6769#[ entry]
6870fn main ( ) -> ! {
69- if let ( Some ( dp) , Some ( cp) ) = ( Peripherals :: take ( ) , c_m_Peripherals:: take ( ) ) {
70- cortex_m:: interrupt:: free ( move |cs| {
71- let mut rcc = dp. RCC . constrain ( ) ;
72- let mut flash = dp. FLASH . constrain ( ) ;
73- let clocks = rcc
74- . cfgr
75- . sysclk ( 8 . mhz ( ) )
76- . pclk1 ( 8 . mhz ( ) )
77- . freeze ( & mut flash. acr ) ;
78-
79- // Configure PC13 pin to blink LED
80- let mut gpioc = dp. GPIOC . split ( & mut rcc. apb2 ) ;
81- let led = gpioc. pc13 . into_push_pull_output ( & mut gpioc. crh ) ;
82-
83- // Move the pin into our global storage
84- * G_LED . borrow ( cs) . borrow_mut ( ) = Some ( led) ;
85-
86- // Set up a timer expiring after 1s
87- let mut timer = Timer :: tim2 ( dp. TIM2 , & clocks, & mut rcc. apb1 ) . start_count_down ( 1 . hz ( ) ) ;
88-
89- // Generate an interrupt when the timer expires
90- timer. listen ( Event :: Update ) ;
91-
92- // Move the timer into our global storage
93- * G_TIM . borrow ( cs) . borrow_mut ( ) = Some ( timer) ;
94-
95- // Enable TIM2 IRQ, set prio 1 and clear any pending IRQs
96- let mut nvic = cp. NVIC ;
97- // Calling 'set_priority()' and 'unmask()' requires 'unsafe {}'
98- // - https://docs.rs/stm32f1xx-hal/0.5.3/stm32f1xx_hal/stm32/struct.NVIC.html#method.set_priority
99- unsafe {
100- nvic. set_priority ( Interrupt :: TIM2 , 1 ) ;
101- cortex_m:: peripheral:: NVIC :: unmask ( Interrupt :: TIM2 ) ;
102- }
103- // Clear the interrupt state
104- cortex_m:: peripheral:: NVIC :: unpend ( Interrupt :: TIM2 ) ;
105- } ) ;
71+ let dp = Peripherals :: take ( ) . unwrap ( ) ;
72+
73+ let mut rcc = dp. RCC . constrain ( ) ;
74+ let mut flash = dp. FLASH . constrain ( ) ;
75+ let clocks = rcc
76+ . cfgr
77+ . sysclk ( 8 . mhz ( ) )
78+ . pclk1 ( 8 . mhz ( ) )
79+ . freeze ( & mut flash. acr ) ;
80+
81+ // Configure PC13 pin to blink LED
82+ let mut gpioc = dp. GPIOC . split ( & mut rcc. apb2 ) ;
83+ let mut led = gpioc. pc13 . into_push_pull_output ( & mut gpioc. crh ) ;
84+ let _ = led. set_high ( ) ; // Turn off
85+
86+ // Move the pin into our global storage
87+ cortex_m:: interrupt:: free ( |cs| * 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+ cortex_m:: interrupt:: free ( |cs| * G_TIM . borrow ( cs) . borrow_mut ( ) = Some ( timer) ) ;
97+
98+ unsafe {
99+ cortex_m:: peripheral:: NVIC :: unmask ( Interrupt :: TIM2 ) ;
106100 }
107101
108- //hprintln!("Entering main loop...").unwrap();
109102 loop {
110- // From 'cortex_m::asm::wfi'
111103 wfi ( ) ;
112104 }
113105}
0 commit comments