You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
HI! I am new to the rust embedded world, or general rust I would say so I am looking for some guidance from more experienced folks out there! :D Sadly I can not find any examples nor issues for my problem and all the examples either don't work or are outdated as it seems.
I have an Esp32-c3 devboard which supports most of the embassy functionalities as I found out via #745 .
Furthermore I had a look at the embassy examples from their repo here .
My Task: I have a button and a led connected to the chip. I want that the led is blinking when I either press the button OR a timer runs for 10 seconds. IF either the button is pressed or the timer ends I want the timer to restart from the beginning. I want the chip as power efficient as possible so I thought I use some interrupts.
I managed to get it working in standard esp-hal which looks like this:
ESP HAL VERSION
#![no_std]
#![no_main]
use core::cell::RefCell;
use core::time::Duration;
use critical_section::Mutex;
use esp_backtrace as _;
use esp_println::println;
use hal::{
clock::ClockControl,
gpio::{Event, Gpio4, Input, PullDown, PullUp, RTCPinWithResistors, IO},
interrupt,
peripherals::{self, Peripherals},
prelude::*,
riscv,
rtc_cntl::{
get_reset_reason, get_wakeup_cause,
sleep::{RtcioWakeupSource, TimerWakeupSource, WakeSource, WakeupLevel},
SocResetReason,
},
Delay, Rtc, Timer,
};
#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let mut rtc = Rtc::new(peripherals.RTC_CNTL);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
// Set GPIO3 as an output
let mut led = io.pins.gpio3.into_push_pull_output();
// Set GPIO4 as an input
let mut pin4 = io.pins.gpio4;
pin4.rtcio_pullup(true);
println!("up and runnning!");
let reason = get_reset_reason(hal::Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn);
println!("reset reason: {:?}", reason);
let wake_reason = get_wakeup_cause();
println!("wake reason: {:?}", wake_reason);
let mut delay = Delay::new(&clocks);
match wake_reason {
hal::reset::SleepSource::Timer => {
println!("timer wakeup");
for _ in 0..3 {
led.set_high().unwrap();
delay.delay_ms(200u32);
led.set_low().unwrap();
delay.delay_ms(200u32);
}
}
hal::reset::SleepSource::Gpio => {
println!("gpio wakeup");
for _ in 0..5 {
led.set_high().unwrap();
delay.delay_ms(500u32);
led.set_low().unwrap();
delay.delay_ms(200u32);
}
}
_ => {
println!("other wakeup")
}
}
let wakeup_pins: &mut [(&mut dyn RTCPinWithResistors, WakeupLevel)] =
&mut [(&mut pin4, WakeupLevel::Low)];
let rtcio = RtcioWakeupSource::new(wakeup_pins);
let timer = TimerWakeupSource::new(Duration::from_secs(10));
println!("Enter Deep Sleep!");
delay.delay_ms(100u32);
rtc.sleep_deep(&[&timer, &rtcio], &mut delay);
}
Now I wanted to achieve the same in embassy which ended up in something like this.
Embassy Version
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use embassy_executor::{Executor, Spawner};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel;
use embassy_sync::mutex::Mutex;
use embassy_sync::signal::Signal;
use embassy_time::{Duration, Timer};
use esp_backtrace as _;
use esp_println::println;
use hal::gpio::{GpioPin, Input, PullUp, PushPull};
use hal::interrupt::Priority;
use hal::peripherals::Interrupt;
use hal::prelude::main;
use hal::riscv;
use hal::IO;
use hal::{clock::ClockControl, embassy, peripherals::Peripherals, prelude::*};
use static_cell::make_static;
enum InterruptType {
Time,
Button,
}
static CHANNEL: Channel<CriticalSectionRawMutex, InterruptType, 1> = Channel::new();
#[embassy_executor::task]
async fn waiting_task() {
println!("WT begins");
Timer::after(Duration::from_millis(10_000)).await;
CHANNEL.send(InterruptType::Time).await;
println!("WT ends");
}
#[embassy_executor::task]
async fn button_task(mut button: GpioPin<Input<PullUp>, 4>) {
button.wait_for_falling_edge().await.unwrap();
CHANNEL.send(InterruptType::Button).await;
println!("Button Task ends");
}
#[main]
async fn main(spawner: Spawner) -> ! {
esp_println::println!("Init!");
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
embassy::init(
&clocks,
hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
);
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
// GPIO 3 as output
let mut led = io.pins.gpio3.into_push_pull_output();
// GPIO 4 as input but this seems wrong to do here as well
let button = io.pins.gpio4.into_pull_up_input();
// Async requires the GPIO interrupt to wake futures
// hal::interrupt::enable(Interrupt::GPIO, hal::interrupt::Priority::Priority1).unwrap();
// enable all interrupts
unsafe {
riscv::interrupt::enable();
}
// This should be inside the main task but can not make it a static lifetime for some reason
spawner.spawn(button_task(button)).ok();
loop {
// Spawn interrupt tasks? this seems kinda weird and wrong
spawner.spawn(waiting_task()).ok();
println!("Waiting... for input - sleeping");
match CHANNEL.receive().await {
InterruptType::Time => {
println!("Time Interrupt");
for _ in 0..3 {
led.set_high().unwrap();
Timer::after(Duration::from_millis(200)).await;
led.set_low().unwrap();
Timer::after(Duration::from_millis(200)).await;
}
}
InterruptType::Button => {
println!("Button Interrupt");
for _ in 0..5 {
led.set_high().unwrap();
Timer::after(Duration::from_millis(500)).await;
led.set_low().unwrap();
Timer::after(Duration::from_millis(200)).await;
}
}
}
}
}
Even I can tell their are mayor problems with this code.
First of all how do I end a started waiting_task if the button interrupt comes before that and remove it from the task queue without finishing its timer?
I thought a channel might be a good idea as I have read its basically a signal so i thought if i use channel.await in the main loop i can combine multiple interrupts that way
Another hurdle seems to provide the mut button to an async function. Should I use a mutex here as it seems i cannot make a lifetime annotation
Any help would be really greatly appreciated.
I have attached all of the files to hopefully recreate my issue.
I have right know the same problem to implement a button to recognize short and long press. I find it ugly needing 3 tasks per button to be able to evaluate a button press
HI! I am new to the rust embedded world, or general rust I would say so I am looking for some guidance from more experienced folks out there! :D Sadly I can not find any examples nor issues for my problem and all the examples either don't work or are outdated as it seems.
I have an Esp32-c3 devboard which supports most of the embassy functionalities as I found out via #745 .
Furthermore I had a look at the embassy examples from their repo here .
My Task: I have a button and a led connected to the chip. I want that the led is blinking when I either press the button OR a timer runs for 10 seconds. IF either the button is pressed or the timer ends I want the timer to restart from the beginning. I want the chip as power efficient as possible so I thought I use some interrupts.
I managed to get it working in standard esp-hal which looks like this:
ESP HAL VERSION
Now I wanted to achieve the same in embassy which ended up in something like this.
Embassy Version
Even I can tell their are mayor problems with this code.
Any help would be really greatly appreciated.
I have attached all of the files to hopefully recreate my issue.
embassy_button_blinks.zip
button-blinks-task.zip
The text was updated successfully, but these errors were encountered: