-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathgpio_interrupts.rs
88 lines (73 loc) · 2.85 KB
/
gpio_interrupts.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#![no_main]
#![no_std]
use core::cell::RefCell;
use panic_semihosting as _;
use cortex_m::{asm, peripheral::NVIC};
use cortex_m_rt::entry;
use critical_section::Mutex;
use stm32f3xx_hal::{
gpio::{self, Edge, Input, Output, PushPull},
interrupt, pac,
prelude::*,
};
type LedPin = gpio::PE9<Output<PushPull>>;
static LED: Mutex<RefCell<Option<LedPin>>> = Mutex::new(RefCell::new(None));
type ButtonPin = gpio::PA0<Input>;
static BUTTON: Mutex<RefCell<Option<ButtonPin>>> = Mutex::new(RefCell::new(None));
// When the user button is pressed. The north LED will toggle.
#[entry]
fn main() -> ! {
// Getting access to registers we will need for configuration.
let device_peripherals = pac::Peripherals::take().unwrap();
let mut rcc = device_peripherals.RCC.constrain();
let mut syscfg = device_peripherals.SYSCFG.constrain(&mut rcc.apb2);
let mut exti = device_peripherals.EXTI;
let mut gpioe = device_peripherals.GPIOE.split(&mut rcc.ahb);
let mut gpioa = device_peripherals.GPIOA.split(&mut rcc.ahb);
let mut led = gpioe
.pe9
.into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
// Turn the led on so we know the configuration step occurred.
led.toggle().expect("unable to toggle led in configuration");
// Move the ownership of the led to the global LED
critical_section::with(|cs| *LED.borrow(cs).borrow_mut() = Some(led));
// Configuring the user button to trigger an interrupt when the button is pressed.
let mut user_button = gpioa
.pa0
.into_pull_down_input(&mut gpioa.moder, &mut gpioa.pupdr);
syscfg.select_exti_interrupt_source(&user_button);
user_button.trigger_on_edge(&mut exti, Edge::Rising);
user_button.enable_interrupt(&mut exti);
let interrupt_num = user_button.interrupt(); // hal::pac::Interrupt::EXTI0
// Moving ownership to the global BUTTON so we can clear the interrupt pending bit.
critical_section::with(|cs| *BUTTON.borrow(cs).borrow_mut() = Some(user_button));
unsafe { NVIC::unmask(interrupt_num) };
loop {
asm::wfi();
}
}
// Button Pressed interrupt.
// The exti# maps to the pin number that is being used as an external interrupt.
// See page 295 of the stm32f303 reference manual for proof:
// http://www.st.com/resource/en/reference_manual/dm00043574.pdf
//
// This may be called more than once per button press from the user since the button may not be debounced.
#[interrupt]
fn EXTI0() {
critical_section::with(|cs| {
// Toggle the LED
LED.borrow(cs)
.borrow_mut()
.as_mut()
.unwrap()
.toggle()
.unwrap();
// Clear the interrupt pending bit so we don't infinitely call this routine
BUTTON
.borrow(cs)
.borrow_mut()
.as_mut()
.unwrap()
.clear_interrupt();
})
}