/*
Simplified Embedded Rust: ESP Core Library Edition
Programming GPIO - Button Press Counter Application Example
*/
#![no_std]
#![no_main]
use core::cell::{Cell, RefCell};
use critical_section::Mutex;
use esp_backtrace as _;
use esp_hal::{
gpio::{Event, Input, Io, Pull},
prelude::*,
};
use esp_println::println;
// Create a Global Variable for a GPIO Peripheral to pass around between threads.
static G_PIN: Mutex<RefCell<Option<Input>>> =
Mutex::new(RefCell::new(None));
// Create a Global Variable for a FLAG to pass around between threads.
static G_FLAG: Mutex<Cell<bool>> =
Mutex::new(Cell::new(false));
// ISR Definition
#[handler]
fn gpio() {
// Start a Critical Section
critical_section::with(|cs| {
// Obtain access to Global Button Peripheral and Clear Interrupt Pending Flag
G_PIN
.borrow_ref_mut(cs)
.as_mut()
.unwrap()
.clear_interrupt();
// Assert G_FLAG indicating a press button happened
G_FLAG.borrow(cs).set(true);
});
}
#[entry]
fn main() -> ! {
// Take Peripherals
let peripherals =
esp_hal::init(esp_hal::Config::default());
// Create IO Driver
let mut io =
Io::new(peripherals.GPIO, peripherals.IO_MUX);
// Interrupt Configuration
// Step 1: Register interrupt handler
io.set_interrupt_handler(gpio);
// Step 2: Configure button pin direction
let mut some_pin = Input::new(io.pins.gpio0, Pull::Up);
// Step 3: Configure button input to trigger an interrupt on the falling edge and start listening to events
some_pin.listen(Event::FallingEdge);
// Step 4: Now that button is configured, move the input pin to the global context
critical_section::with(|cs| {
G_PIN.borrow_ref_mut(cs).replace(some_pin)
});
// Instantiate variable to keep button count
let mut count = 0_u32;
loop {
critical_section::with(|cs| {
if G_FLAG.borrow(cs).get() {
// Clear global flag
G_FLAG.borrow(cs).set(false);
// Increment count and print to console
count += 1;
println!("Button press count = {}", count);
}
});
}
}