handle button press to enable/disable blinking
This commit is contained in:
parent
db4adc53fa
commit
530ea9a0e5
4 changed files with 142 additions and 16 deletions
55
src/main.rs
55
src/main.rs
|
@ -1,31 +1,66 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(async_fn_track_caller, type_alias_impl_trait)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
||||
|
||||
mod static_mutex;
|
||||
|
||||
use defmt::*;
|
||||
use defmt_rtt as _;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::{
|
||||
gpio::{Level, Output, Speed},
|
||||
peripherals::PA5
|
||||
exti::ExtiInput,
|
||||
gpio::{Input, Level, Output, Pull, Speed},
|
||||
peripherals::{PA5, PC13}
|
||||
};
|
||||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use panic_probe as _; // global logger
|
||||
use panic_probe as _;
|
||||
use static_mutex::StaticMutex;
|
||||
|
||||
type Mutex<T> = embassy_sync::mutex::Mutex<ThreadModeRawMutex, T>;
|
||||
type MutexGuard<'a, T> = embassy_sync::mutex::MutexGuard<'a, ThreadModeRawMutex, T>;
|
||||
|
||||
type NucleoLed = Output<'static, PA5>;
|
||||
type NucleoButton = ExtiInput<'static, PC13>;
|
||||
|
||||
static LED: StaticMutex<NucleoLed> = StaticMutex::new();
|
||||
static BLINKING: Mutex<bool> = Mutex::new(true);
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn blinker(mut led: Output<'static, PA5>, interval: Duration) {
|
||||
async fn blinker(interval: Duration) {
|
||||
loop {
|
||||
led.set_high();
|
||||
Timer::after(interval).await;
|
||||
led.set_low();
|
||||
if *BLINKING.lock().await {
|
||||
LED.lock().await.toggle();
|
||||
}
|
||||
Timer::after(interval).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn button_handler(mut button: NucleoButton) {
|
||||
loop {
|
||||
button.wait_for_falling_edge().await;
|
||||
let mut blinking = BLINKING.lock().await;
|
||||
if *blinking {
|
||||
info!("Disable blinking");
|
||||
LED.lock().await.set_low();
|
||||
*blinking = false;
|
||||
} else {
|
||||
info!("Enable blinking");
|
||||
*blinking = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(spawner: Spawner) {
|
||||
let p = embassy_stm32::init(Default::default());
|
||||
|
||||
let led = Output::new(p.PA5, Level::Low, Speed::Low);
|
||||
unwrap!(spawner.spawn(blinker(led, Duration::from_millis(500))));
|
||||
LED.init(Output::new(p.PA5, Level::Low, Speed::Low)).await;
|
||||
let button = ExtiInput::new(Input::new(p.PC13, Pull::Up), p.EXTI13);
|
||||
|
||||
unwrap!(spawner.spawn(blinker(Duration::from_millis(500))));
|
||||
unwrap!(spawner.spawn(button_handler(button)));
|
||||
}
|
||||
|
|
61
src/static_mutex.rs
Normal file
61
src/static_mutex.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use crate::{Mutex, MutexGuard};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
enum Value<T> {
|
||||
Full(T),
|
||||
Empty
|
||||
}
|
||||
|
||||
pub struct StaticMutex<T> {
|
||||
value: Mutex<Value<T>>
|
||||
}
|
||||
|
||||
impl<T> StaticMutex<T> {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
value: Mutex::new(Value::Empty)
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub async fn init(&self, new: T) {
|
||||
let mut value = self.value.lock().await;
|
||||
if !matches!(*value, Value::Empty) {
|
||||
panic!("Cannot initialise StaticMutex more than once");
|
||||
}
|
||||
*value = Value::Full(new);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub async fn lock(&self) -> StaticMutexLockGuard<'_, T> {
|
||||
let inner = self.value.lock().await;
|
||||
if matches!(*inner, Value::Empty) {
|
||||
panic!("This StaticMutex has not been initialised yet");
|
||||
}
|
||||
StaticMutexLockGuard { inner }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StaticMutexLockGuard<'a, T> {
|
||||
inner: MutexGuard<'a, Value<T>>
|
||||
}
|
||||
|
||||
impl<T> Deref for StaticMutexLockGuard<'_, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self.inner.deref() {
|
||||
Value::Full(ref value) => value,
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for StaticMutexLockGuard<'_, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match self.inner.deref_mut() {
|
||||
Value::Full(ref mut value) => value,
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue