Improve and use timer abstractions (#1753)

* Make esp-wifi timer agnostic

* Use timer-abstractions in embassy time driver

* Refactor

* Fix

* Fix

* Docs

* Adapt examples

* Adapt tests

* Refactoring

* Changelogs

* Fix example

* Adapt xtask

* Make CI pass

---------

Co-authored-by: Jesse Braham <jessebraham@users.noreply.github.com>
This commit is contained in:
Björn Quentin 2024-07-09 17:59:38 +02:00 committed by GitHub
parent 8e0a2012dc
commit a5be31fadc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
54 changed files with 1125 additions and 599 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
### Changed
- Removed the TIMG and SYSTIMER time-drivers, replaced by a generic time-driver taking `OneShotTimer<ErasedTimer>` (#1753)
### Fixed

View File

@ -9,16 +9,17 @@ license = "MIT OR Apache-2.0"
[package.metadata.docs.rs]
default-target = "riscv32imac-unknown-none-elf"
features = ["esp32c6", "time-timg0"]
features = ["esp32c6"]
[dependencies]
critical-section = "1.1.2"
defmt = { version = "0.3.8", optional = true }
document-features = "0.2.8"
embassy-executor = { version = "0.5.0", optional = true }
embassy-time-driver = "0.1.0"
embassy-time-driver = { version = "0.1.0", features = [ "tick-hz-1_000_000" ] }
esp-hal = { version = "0.18.0", path = "../esp-hal" }
portable-atomic = "1.6.0"
log = { version = "0.4.22", optional = true }
[build-dependencies]
cfg-if = "1.0.0"
@ -38,15 +39,9 @@ esp32s3 = ["esp-hal/esp32s3"]
## Implement `defmt::Format` on certain types.
defmt = ["dep:defmt", "embassy-executor?/defmt", "esp-hal/defmt"]
## Enable logging via the log crate
log = ["dep:log"]
## Provide `Executor` and `InterruptExecutor`
executors = ["dep:embassy-executor"]
## Use the executor-integrated `embassy-time` timer queue.
integrated-timers = ["embassy-executor?/integrated-timers"]
#! ### Time Driver Feature Flags
## SYSTIMER (16MHz)
time-systimer-16mhz = ["embassy-time-driver/tick-hz-16_000_000"]
## SYSTIMER (80MHz)
time-systimer-80mhz = ["embassy-time-driver/tick-hz-80_000_000"]
## TIMG0 (1MHz)
time-timg0 = ["embassy-time-driver/tick-hz-1_000_000"]

View File

@ -10,18 +10,6 @@ fn main() -> Result<(), Box<dyn Error>> {
"esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s2", "esp32s3"
);
// If the `embassy` feature is enabled, ensure that a time driver implementation
// is available:
cfg_if::cfg_if! {
if #[cfg(feature = "esp32")] {
assert_unique_used_features!("time-timg0");
} else if #[cfg(feature = "esp32s2")] {
assert_unique_used_features!("time-systimer-80mhz", "time-timg0");
} else {
assert_unique_used_features!("time-systimer-16mhz", "time-timg0");
}
}
// NOTE: update when adding new device support!
// Determine the name of the configured device:
let device_name = if cfg!(feature = "esp32") {

View File

@ -36,69 +36,17 @@
// MUST be the first module
mod fmt;
use core::cell::Cell;
use embassy_time_driver::{AlarmHandle, Driver};
use esp_hal::clock::Clocks;
#[cfg(feature = "executors")]
pub use self::executor::{Executor, InterruptExecutor};
use self::time_driver::{EmbassyTimer, TimerType};
use self::time_driver::{EmbassyTimer, Timer};
#[cfg(feature = "executors")]
mod executor;
mod time_driver;
/// Initialize embassy
pub fn init(clocks: &Clocks, time_driver: TimerType) {
pub fn init(clocks: &Clocks, time_driver: &'static mut [Timer]) {
EmbassyTimer::init(clocks, time_driver)
}
#[allow(clippy::type_complexity)]
pub(crate) struct AlarmState {
pub callback: Cell<Option<(fn(*mut ()), *mut ())>>,
pub allocated: Cell<bool>,
}
unsafe impl Send for AlarmState {}
impl AlarmState {
pub const fn new() -> Self {
Self {
callback: Cell::new(None),
allocated: Cell::new(false),
}
}
}
impl Driver for EmbassyTimer {
fn now(&self) -> u64 {
EmbassyTimer::now()
}
unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
critical_section::with(|cs| {
for (i, alarm) in self.alarms.borrow(cs).iter().enumerate() {
if !alarm.allocated.get() {
// set alarm so it is not overwritten
alarm.allocated.set(true);
self.on_alarm_allocated(i);
return Some(AlarmHandle::new(i as u8));
}
}
None
})
}
fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) {
let n = alarm.id() as usize;
critical_section::with(|cs| {
let alarm = &self.alarms.borrow(cs)[n];
alarm.callback.set(Some((callback, ctx)));
})
}
fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
self.set_alarm(alarm, timestamp)
}
}

View File

@ -1,9 +1,180 @@
#[cfg(any(feature = "time-systimer-16mhz", feature = "time-systimer-80mhz"))]
pub use self::systimer::*;
#[cfg(feature = "time-timg0")]
pub use self::timg::*;
use core::cell::{Cell, RefCell};
#[cfg(any(feature = "time-systimer-16mhz", feature = "time-systimer-80mhz"))]
mod systimer;
#[cfg(feature = "time-timg0")]
mod timg;
use critical_section::Mutex;
use embassy_time_driver::{AlarmHandle, Driver};
use esp_hal::{
clock::Clocks,
interrupt::{InterruptHandler, Priority},
prelude::*,
time::current_time,
timer::{ErasedTimer, OneShotTimer},
};
pub const MAX_SUPPORTED_ALARM_COUNT: usize = 7;
pub type Timer = OneShotTimer<ErasedTimer>;
static TIMERS: Mutex<RefCell<Option<&'static mut [Timer]>>> = Mutex::new(RefCell::new(None));
#[allow(clippy::type_complexity)]
struct AlarmState {
pub callback: Cell<Option<(fn(*mut ()), *mut ())>>,
pub allocated: Cell<bool>,
}
unsafe impl Send for AlarmState {}
impl AlarmState {
pub const fn new() -> Self {
Self {
callback: Cell::new(None),
allocated: Cell::new(false),
}
}
}
pub(super) struct EmbassyTimer {
alarms: Mutex<[AlarmState; MAX_SUPPORTED_ALARM_COUNT]>,
}
#[allow(clippy::declare_interior_mutable_const)]
const ALARM_STATE_NONE: AlarmState = AlarmState::new();
embassy_time_driver::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer {
alarms: Mutex::new([ALARM_STATE_NONE; MAX_SUPPORTED_ALARM_COUNT]),
});
impl EmbassyTimer {
pub(super) fn init(_clocks: &Clocks, timers: &'static mut [Timer]) {
if timers.len() > MAX_SUPPORTED_ALARM_COUNT {
panic!(
"Maximum of {} timers can be used.",
MAX_SUPPORTED_ALARM_COUNT
);
}
static HANDLERS: [InterruptHandler; MAX_SUPPORTED_ALARM_COUNT] = [
handler0, handler1, handler2, handler3, handler4, handler5, handler6,
];
timers
.iter_mut()
.enumerate()
.for_each(|(n, timer)| timer.set_interrupt_handler(HANDLERS[n]));
critical_section::with(|cs| {
TIMERS.replace(cs, Some(timers));
});
#[handler(priority = Priority::max())]
fn handler0() {
DRIVER.on_interrupt(0);
}
#[handler(priority = Priority::max())]
fn handler1() {
DRIVER.on_interrupt(1);
}
#[handler(priority = Priority::max())]
fn handler2() {
DRIVER.on_interrupt(2);
}
#[handler(priority = Priority::max())]
fn handler3() {
DRIVER.on_interrupt(3);
}
#[handler(priority = Priority::max())]
fn handler4() {
DRIVER.on_interrupt(4);
}
#[handler(priority = Priority::max())]
fn handler5() {
DRIVER.on_interrupt(5);
}
#[handler(priority = Priority::max())]
fn handler6() {
DRIVER.on_interrupt(6);
}
}
fn on_interrupt(&self, id: usize) {
let cb = critical_section::with(|cs| {
let mut timers = TIMERS.borrow_ref_mut(cs);
let timers = timers.as_mut().unwrap();
let timer = &mut timers[id];
timer.clear_interrupt();
let alarm = &self.alarms.borrow(cs)[id];
if let Some((f, ctx)) = alarm.callback.get() {
Some((f, ctx))
} else {
None
}
});
if let Some((f, ctx)) = cb {
f(ctx);
}
}
fn arm(timer: &mut Timer, timestamp: u64) {
let now = current_time().duration_since_epoch();
let ts = timestamp.micros();
let timeout = if ts > now { ts - now } else { now };
timer.schedule(timeout).unwrap();
timer.enable_interrupt(true);
}
}
impl Driver for EmbassyTimer {
fn now(&self) -> u64 {
current_time().ticks()
}
unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
critical_section::with(|cs| {
for (i, alarm) in self.alarms.borrow(cs).iter().enumerate() {
if !alarm.allocated.get() {
// set alarm so it is not overwritten
alarm.allocated.set(true);
return Some(AlarmHandle::new(i as u8));
}
}
None
})
}
fn set_alarm_callback(&self, alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) {
let n = alarm.id() as usize;
critical_section::with(|cs| {
let alarm = &self.alarms.borrow(cs)[n];
alarm.callback.set(Some((callback, ctx)));
})
}
fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
// we sometimes get called with `u64::MAX` for apparently not yet initialized
// timers which would fail later on
if timestamp == u64::MAX {
return false;
}
// The hardware fires the alarm even if timestamp is lower than the current
// time. In this case the interrupt handler will pend a wake-up when we exit the
// critical section.
//
// This is correct behavior. See https://docs.rs/embassy-time-driver/0.1.0/embassy_time_driver/trait.Driver.html#tymethod.set_alarm
// (... the driver should return true and arrange to call the alarm callback as
// soon as possible, but not synchronously.)
critical_section::with(|cs| {
let mut timers = TIMERS.borrow_ref_mut(cs);
let timers = timers.as_mut().unwrap();
let timer = &mut timers[alarm.id() as usize];
Self::arm(timer, timestamp);
});
true
}
}

View File

@ -1,135 +0,0 @@
use critical_section::{CriticalSection, Mutex};
use embassy_time_driver::AlarmHandle;
use esp_hal::{
clock::Clocks,
interrupt,
peripherals::Interrupt,
prelude::*,
timer::systimer::{Alarm, SystemTimer, Target},
Async,
};
use crate::AlarmState;
pub const ALARM_COUNT: usize = 3;
pub type TimerType = SystemTimer<'static, Async>;
pub struct EmbassyTimer {
pub(crate) alarms: Mutex<[AlarmState; ALARM_COUNT]>,
pub(crate) alarm0: Alarm<Target, Async, 0>,
pub(crate) alarm1: Alarm<Target, Async, 1>,
pub(crate) alarm2: Alarm<Target, Async, 2>,
}
#[allow(clippy::declare_interior_mutable_const)]
const ALARM_STATE_NONE: AlarmState = AlarmState::new();
embassy_time_driver::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer {
alarms: Mutex::new([ALARM_STATE_NONE; ALARM_COUNT]),
alarm0: unsafe { Alarm::<_, Async, 0>::conjure() },
alarm1: unsafe { Alarm::<_, Async, 1>::conjure() },
alarm2: unsafe { Alarm::<_, Async, 2>::conjure() },
});
impl EmbassyTimer {
pub(crate) fn now() -> u64 {
SystemTimer::now()
}
fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
let alarm = &self.alarms.borrow(cs)[n];
if let Some((f, ctx)) = alarm.callback.get() {
f(ctx);
}
}
pub(crate) fn on_alarm_allocated(&self, n: usize) {
match n {
0 => self.alarm0.enable_interrupt(true),
1 => self.alarm1.enable_interrupt(true),
2 => self.alarm2.enable_interrupt(true),
_ => {}
}
}
fn on_interrupt(&self, id: usize) {
critical_section::with(|cs| {
self.clear_interrupt(id);
self.trigger_alarm(id, cs);
})
}
pub fn init(_clocks: &Clocks, _systimer: TimerType) {
unsafe {
interrupt::bind_interrupt(Interrupt::SYSTIMER_TARGET0, target0_handler.handler());
unwrap!(interrupt::enable(
Interrupt::SYSTIMER_TARGET0,
target0_handler.priority()
));
interrupt::bind_interrupt(Interrupt::SYSTIMER_TARGET1, target1_handler.handler());
unwrap!(interrupt::enable(
Interrupt::SYSTIMER_TARGET1,
target1_handler.priority()
));
interrupt::bind_interrupt(Interrupt::SYSTIMER_TARGET2, target2_handler.handler());
unwrap!(interrupt::enable(
Interrupt::SYSTIMER_TARGET2,
target2_handler.priority()
));
}
#[handler]
fn target0_handler() {
DRIVER.on_interrupt(0);
}
#[handler]
fn target1_handler() {
DRIVER.on_interrupt(1);
}
#[handler]
fn target2_handler() {
DRIVER.on_interrupt(2);
}
}
pub(crate) fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
critical_section::with(|_cs| {
let n = alarm.id() as usize;
// The hardware fires the alarm even if timestamp is lower than the current
// time. In this case the interrupt handler will pend a wakeup when we exit the
// critical section.
self.arm(n, timestamp);
});
// In theory, the above comment is true. However, in practice, we seem to be
// missing interrupt for very short timeouts, so let's make sure and catch
// timestamps that already passed. Returning `false` means embassy will
// run one more poll loop.
Self::now() < timestamp
}
fn clear_interrupt(&self, id: usize) {
match id {
0 => self.alarm0.clear_interrupt(),
1 => self.alarm1.clear_interrupt(),
2 => self.alarm2.clear_interrupt(),
_ => {}
}
}
fn arm(&self, id: usize, timestamp: u64) {
match id {
0 => self.alarm0.set_target(timestamp),
1 => self.alarm1.set_target(timestamp),
2 => self.alarm2.set_target(timestamp),
_ => {}
}
}
}

View File

@ -1,126 +0,0 @@
use critical_section::{CriticalSection, Mutex};
use embassy_time_driver::AlarmHandle;
#[cfg(any(esp32, esp32s2, esp32s3))]
use esp_hal::timer::timg::Timer1;
use esp_hal::{
clock::Clocks,
interrupt::{self, Priority},
peripherals::{Interrupt, TIMG0},
prelude::*,
timer::timg::{Instance, Timer0, TimerGroup},
Async,
};
use crate::AlarmState;
#[cfg(not(any(esp32, esp32s2, esp32s3)))]
pub const ALARM_COUNT: usize = 1;
#[cfg(any(esp32, esp32s2, esp32s3))]
pub const ALARM_COUNT: usize = 2;
pub type TimerType = TimerGroup<'static, TIMG0, Async>;
pub struct EmbassyTimer {
pub(crate) alarms: Mutex<[AlarmState; ALARM_COUNT]>,
}
#[allow(clippy::declare_interior_mutable_const)]
const ALARM_STATE_NONE: AlarmState = AlarmState::new();
embassy_time_driver::time_driver_impl!(static DRIVER: EmbassyTimer = EmbassyTimer {
alarms: Mutex::new([ALARM_STATE_NONE; ALARM_COUNT]),
});
impl EmbassyTimer {
pub(crate) fn now() -> u64 {
unsafe { Timer0::<TIMG0>::steal() }.now()
}
fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
let alarm = &self.alarms.borrow(cs)[n];
if let Some((f, ctx)) = alarm.callback.get() {
f(ctx);
}
}
pub(crate) fn on_alarm_allocated(&self, _n: usize) {}
fn on_interrupt<Timer: Instance>(&self, id: u8, timer: Timer) {
critical_section::with(|cs| {
timer.clear_interrupt();
self.trigger_alarm(id as usize, cs);
});
}
pub fn init(clocks: &Clocks, timer: TimerType) {
// set divider to get a 1mhz clock. APB (80mhz) / 80 = 1mhz...
timer.timer0.set_divider(clocks.apb_clock.to_MHz() as u16);
timer.timer0.set_counter_active(true);
#[cfg(any(esp32, esp32s2, esp32s3))]
{
timer.timer1.set_divider(clocks.apb_clock.to_MHz() as u16);
timer.timer1.set_counter_active(true);
}
unsafe {
interrupt::bind_interrupt(Interrupt::TG0_T0_LEVEL, tg0_t0_level.handler());
unwrap!(interrupt::enable(
Interrupt::TG0_T0_LEVEL,
tg0_t0_level.priority()
));
}
#[cfg(any(esp32, esp32s2, esp32s3))]
unsafe {
interrupt::bind_interrupt(Interrupt::TG0_T1_LEVEL, tg0_t1_level.handler());
unwrap!(interrupt::enable(
Interrupt::TG0_T1_LEVEL,
tg0_t1_level.priority()
));
}
#[handler(priority = Priority::max())]
fn tg0_t0_level() {
let timer = unsafe { Timer0::<TIMG0>::steal() };
DRIVER.on_interrupt(0, timer);
}
#[cfg(any(esp32, esp32s2, esp32s3))]
#[handler(priority = Priority::max())]
fn tg0_t1_level() {
let timer = unsafe { Timer1::<TIMG0>::steal() };
DRIVER.on_interrupt(1, timer);
}
}
pub(crate) fn set_alarm(&self, _alarm: AlarmHandle, timestamp: u64) -> bool {
critical_section::with(|_cs| {
// The hardware fires the alarm even if timestamp is lower than the current
// time. In this case the interrupt handler will pend a wakeup when we exit the
// critical section.
#[cfg(any(esp32, esp32s2, esp32s3))]
if _alarm.id() == 1 {
let mut tg = unsafe { Timer1::<TIMG0>::steal() };
Self::arm(&mut tg, timestamp);
return;
}
let mut tg = unsafe { Timer0::<TIMG0>::steal() };
Self::arm(&mut tg, timestamp);
});
true
}
fn arm<T>(tg: &mut T, timestamp: u64)
where
T: Instance,
{
tg.load_alarm_value(timestamp);
tg.listen();
tg.set_counter_decrementing(false);
tg.set_auto_reload(false);
tg.set_alarm_active(true);
}
}

View File

@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- dma: add Mem2Mem to support memory to memory transfer (#1738)
- Add `uart` wake source (#1727)
- uart: Make `rx_timeout` optional in Config struct (#1759)
- Add interrupt related functions to `PeriodicTimer`/`OneShotTimer`, added `ErasedTimer` (#1753)
### Fixed

View File

@ -42,6 +42,8 @@
use fugit::{ExtU64, Instant, MicrosDurationU64};
use crate::{interrupt::InterruptHandler, private};
#[cfg(systimer)]
pub mod systimer;
#[cfg(any(timg0, timg1))]
@ -90,6 +92,11 @@ pub trait Timer: crate::private::Sealed {
/// Clear the timer's interrupt.
fn clear_interrupt(&self);
/// Set the interrupt handler
///
/// Note that this will replace any previously set interrupt handler
fn set_interrupt_handler(&self, handler: InterruptHandler);
/// Has the timer triggered?
fn is_interrupt_set(&self) -> bool;
@ -146,6 +153,45 @@ where
self.inner.stop();
self.inner.clear_interrupt();
}
/// Start counting until the given timeout and raise an interrupt
pub fn schedule(&mut self, timeout: MicrosDurationU64) -> Result<(), Error> {
if self.inner.is_running() {
self.inner.stop();
}
self.inner.clear_interrupt();
self.inner.reset();
self.inner.enable_auto_reload(false);
self.inner.load_value(timeout)?;
self.inner.start();
Ok(())
}
/// Stop the timer
pub fn stop(&mut self) {
self.inner.stop();
}
/// Set the interrupt handler
///
/// Note that this will replace any previously set interrupt handler
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
self.inner.set_interrupt_handler(handler);
}
/// Enable listening for interrupts
pub fn enable_interrupt(&mut self, enable: bool) {
self.inner.enable_interrupt(enable);
}
/// Clear the interrupt flag
pub fn clear_interrupt(&mut self) {
self.inner.clear_interrupt();
self.inner.set_alarm_active(false);
}
}
#[cfg(feature = "embedded-hal-02")]
@ -232,6 +278,160 @@ where
Ok(())
}
/// Set the interrupt handler
///
/// Note that this will replace any previously set interrupt handler
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
self.inner.set_interrupt_handler(handler);
}
/// Enable/disable listening for interrupts
pub fn enable_interrupt(&mut self, enable: bool) {
self.inner.enable_interrupt(enable);
}
/// Clear the interrupt flag
pub fn clear_interrupt(&mut self) {
self.inner.clear_interrupt();
self.inner.set_alarm_active(true);
}
}
/// A type-erased timer
///
/// You can create an instance of this by just calling `.into()` on a timer.
#[allow(missing_docs)]
pub enum ErasedTimer {
Timg0Timer0(timg::Timer<timg::Timer0<crate::peripherals::TIMG0>, crate::Blocking>),
#[cfg(timg_timer1)]
Timg0Timer1(timg::Timer<timg::Timer1<crate::peripherals::TIMG0>, crate::Blocking>),
#[cfg(timg1)]
Timg1Timer0(timg::Timer<timg::Timer0<crate::peripherals::TIMG1>, crate::Blocking>),
#[cfg(all(timg1, timg_timer1))]
Timg1Timer1(timg::Timer<timg::Timer1<crate::peripherals::TIMG1>, crate::Blocking>),
#[cfg(systimer)]
SystimerAlarm0Periodic(systimer::Alarm<systimer::Periodic, crate::Blocking, 0>),
#[cfg(systimer)]
SystimerAlarm1Periodic(systimer::Alarm<systimer::Periodic, crate::Blocking, 1>),
#[cfg(systimer)]
SystimerAlarm2Periodic(systimer::Alarm<systimer::Periodic, crate::Blocking, 2>),
#[cfg(systimer)]
SystimerAlarm0Target(systimer::Alarm<systimer::Target, crate::Blocking, 0>),
#[cfg(systimer)]
SystimerAlarm1Target(systimer::Alarm<systimer::Target, crate::Blocking, 1>),
#[cfg(systimer)]
SystimerAlarm2Target(systimer::Alarm<systimer::Target, crate::Blocking, 2>),
}
impl private::Sealed for ErasedTimer {}
impl From<timg::Timer<timg::Timer0<crate::peripherals::TIMG0>, crate::Blocking>> for ErasedTimer {
fn from(value: timg::Timer<timg::Timer0<crate::peripherals::TIMG0>, crate::Blocking>) -> Self {
Self::Timg0Timer0(value)
}
}
#[cfg(timg_timer1)]
impl From<timg::Timer<timg::Timer1<crate::peripherals::TIMG0>, crate::Blocking>> for ErasedTimer {
fn from(value: timg::Timer<timg::Timer1<crate::peripherals::TIMG0>, crate::Blocking>) -> Self {
Self::Timg0Timer1(value)
}
}
#[cfg(timg1)]
impl From<timg::Timer<timg::Timer0<crate::peripherals::TIMG1>, crate::Blocking>> for ErasedTimer {
fn from(value: timg::Timer<timg::Timer0<crate::peripherals::TIMG1>, crate::Blocking>) -> Self {
Self::Timg1Timer0(value)
}
}
#[cfg(all(timg1, timg_timer1))]
impl From<timg::Timer<timg::Timer1<crate::peripherals::TIMG1>, crate::Blocking>> for ErasedTimer {
fn from(value: timg::Timer<timg::Timer1<crate::peripherals::TIMG1>, crate::Blocking>) -> Self {
Self::Timg1Timer1(value)
}
}
#[cfg(systimer)]
impl From<systimer::Alarm<systimer::Periodic, crate::Blocking, 0>> for ErasedTimer {
fn from(value: systimer::Alarm<systimer::Periodic, crate::Blocking, 0>) -> Self {
Self::SystimerAlarm0Periodic(value)
}
}
#[cfg(systimer)]
impl From<systimer::Alarm<systimer::Periodic, crate::Blocking, 1>> for ErasedTimer {
fn from(value: systimer::Alarm<systimer::Periodic, crate::Blocking, 1>) -> Self {
Self::SystimerAlarm1Periodic(value)
}
}
#[cfg(systimer)]
impl From<systimer::Alarm<systimer::Periodic, crate::Blocking, 2>> for ErasedTimer {
fn from(value: systimer::Alarm<systimer::Periodic, crate::Blocking, 2>) -> Self {
Self::SystimerAlarm2Periodic(value)
}
}
#[cfg(systimer)]
impl From<systimer::Alarm<systimer::Target, crate::Blocking, 0>> for ErasedTimer {
fn from(value: systimer::Alarm<systimer::Target, crate::Blocking, 0>) -> Self {
Self::SystimerAlarm0Target(value)
}
}
#[cfg(systimer)]
impl From<systimer::Alarm<systimer::Target, crate::Blocking, 1>> for ErasedTimer {
fn from(value: systimer::Alarm<systimer::Target, crate::Blocking, 1>) -> Self {
Self::SystimerAlarm1Target(value)
}
}
#[cfg(systimer)]
impl From<systimer::Alarm<systimer::Target, crate::Blocking, 2>> for ErasedTimer {
fn from(value: systimer::Alarm<systimer::Target, crate::Blocking, 2>) -> Self {
Self::SystimerAlarm2Target(value)
}
}
impl Timer for ErasedTimer {
delegate::delegate! {
to match self {
ErasedTimer::Timg0Timer0(inner) => inner,
#[cfg(timg_timer1)]
ErasedTimer::Timg0Timer1(inner) => inner,
#[cfg(timg1)]
ErasedTimer::Timg1Timer0(inner) => inner,
#[cfg(all(timg1,timg_timer1))]
ErasedTimer::Timg1Timer1(inner) => inner,
#[cfg(systimer)]
ErasedTimer::SystimerAlarm0Periodic(inner) => inner,
#[cfg(systimer)]
ErasedTimer::SystimerAlarm1Periodic(inner) => inner,
#[cfg(systimer)]
ErasedTimer::SystimerAlarm2Periodic(inner) => inner,
#[cfg(systimer)]
ErasedTimer::SystimerAlarm0Target(inner) => inner,
#[cfg(systimer)]
ErasedTimer::SystimerAlarm1Target(inner) => inner,
#[cfg(systimer)]
ErasedTimer::SystimerAlarm2Target(inner) => inner,
} {
fn start(&self);
fn stop(&self);
fn reset(&self);
fn is_running(&self) -> bool;
fn now(&self) -> Instant<u64, 1, 1_000_000>;
fn load_value(&self, value: MicrosDurationU64) -> Result<(), Error>;
fn enable_auto_reload(&self, auto_reload: bool);
fn enable_interrupt(&self, state: bool);
fn clear_interrupt(&self);
fn set_interrupt_handler(&self, handler: InterruptHandler);
fn is_interrupt_set(&self) -> bool;
fn set_alarm_active(&self, state: bool);
}
}
}
#[cfg(feature = "embedded-hal-02")]

View File

@ -229,11 +229,8 @@ where
tconf.modify(|_r, w| w.work_en().set_bit());
}
}
}
impl<T, const CHANNEL: u8> Alarm<T, Blocking, CHANNEL> {
/// Set the interrupt handler for this alarm.
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
fn set_interrupt_handler_internal(&self, handler: InterruptHandler) {
match CHANNEL {
0 => unsafe {
interrupt::bind_interrupt(Interrupt::SYSTIMER_TARGET0, handler.handler());
@ -261,6 +258,13 @@ impl<T, const CHANNEL: u8> Alarm<T, Blocking, CHANNEL> {
}
}
impl<T, const CHANNEL: u8> Alarm<T, Blocking, CHANNEL> {
/// Set the interrupt handler for this alarm.
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
self.set_interrupt_handler_internal(handler)
}
}
impl<DM, const CHANNEL: u8> Alarm<Target, DM, CHANNEL>
where
DM: Mode,
@ -572,6 +576,10 @@ where
fn set_alarm_active(&self, _active: bool) {
// Nothing to do
}
fn set_interrupt_handler(&self, handler: InterruptHandler) {
Alarm::set_interrupt_handler_internal(self, handler);
}
}
// Async functionality of the system timer.

View File

@ -518,9 +518,16 @@ where
}
fn enable_interrupt(&self, state: bool) {
// always use level interrupt
#[cfg(any(esp32, esp32s2))]
self.register_block()
.t(self.timer_number().into())
.config()
.modify(|_, w| w.level_int_en().set_bit());
self.register_block()
.int_ena_timers()
.write(|w| w.t(self.timer_number()).bit(state));
.modify(|_, w| w.t(self.timer_number()).bit(state));
}
fn clear_interrupt(&self) {
@ -529,6 +536,24 @@ where
.write(|w| w.t(self.timer_number()).clear_bit_by_one());
}
fn set_interrupt_handler(&self, handler: InterruptHandler) {
let interrupt = match (self.timer_group(), self.timer_number()) {
(0, 0) => Interrupt::TG0_T0_LEVEL,
#[cfg(timg_timer1)]
(0, 1) => Interrupt::TG0_T1_LEVEL,
#[cfg(timg1)]
(1, 0) => Interrupt::TG1_T0_LEVEL,
#[cfg(all(timg_timer1, timg1))]
(1, 1) => Interrupt::TG1_T1_LEVEL,
_ => unreachable!(),
};
unsafe {
interrupt::bind_interrupt(interrupt, handler.handler());
}
interrupt::enable(interrupt, handler.priority()).unwrap();
}
fn is_interrupt_set(&self) -> bool {
self.register_block()
.int_raw_timers()
@ -549,6 +574,8 @@ where
pub trait Instance: Sealed + Enable {
fn register_block(&self) -> &RegisterBlock;
fn timer_group(&self) -> u8;
fn timer_number(&self) -> u8;
fn reset_counter(&self);
@ -633,6 +660,10 @@ where
unsafe { &*TG::register_block() }
}
fn timer_group(&self) -> u8 {
TG::id()
}
fn timer_number(&self) -> u8 {
T
}

View File

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- `esp_wifi::initialize` no longer requires running maximum CPU clock, instead check it runs above 80MHz. (#1688)
- Rename `set_mode` to `set_protocol`, also available in esp-now API (#1742)
- `esp_wifi::initialize` now takes a `PeriodicTimer<ErasedTimer>` (#1753)
### Removed

View File

@ -141,7 +141,6 @@ features = [
"coex",
"async",
"embassy-net",
"esp-hal-embassy/time-timg0",
"esp-hal/default",
]
default-target = "riscv32imc-unknown-none-elf"

View File

@ -18,8 +18,6 @@ use common_adapter::{chip_specific::phy_mem_init, init_radio_clock_control, RADI
use critical_section::Mutex;
use esp_hal as hal;
use fugit::MegahertzU32;
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2))]
use hal::timer::systimer::{Alarm, Target};
use hal::{clock::Clocks, system::RadioClockController};
use linked_list_allocator::Heap;
#[cfg(feature = "wifi")]
@ -144,12 +142,7 @@ fn init_heap() {
});
}
#[cfg(any(esp32c3, esp32c2, esp32c6, esp32h2))]
pub(crate) type EspWifiTimer = Alarm<Target, esp_hal::Blocking, 0>;
#[cfg(any(esp32, esp32s3, esp32s2))]
pub(crate) type EspWifiTimer =
hal::timer::timg::Timer<hal::timer::timg::Timer0<hal::peripherals::TIMG1>, esp_hal::Blocking>;
pub(crate) type EspWifiTimer = crate::timer::TimeBase;
#[derive(Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]

View File

@ -1,6 +1,10 @@
use core::cell::RefCell;
use critical_section::Mutex;
use esp_hal::{
interrupt::InterruptHandler,
timer::{ErasedTimer, PeriodicTimer},
};
#[cfg(any(feature = "esp32c6", feature = "esp32h2"))]
use peripherals::INTPRI as SystemPeripheral;
#[cfg(not(any(feature = "esp32c6", feature = "esp32h2")))]
@ -10,46 +14,34 @@ use crate::{
hal::{
interrupt::{self, TrapFrame},
peripherals::{self, Interrupt},
prelude::*,
riscv,
timer::systimer::{Alarm, Periodic, Target},
},
preempt::preempt::task_switch,
};
/// The timer responsible for time slicing.
pub type TimeBase = Alarm<Target, esp_hal::Blocking, 0>;
static ALARM0: Mutex<RefCell<Option<Alarm<Periodic, esp_hal::Blocking, 0>>>> =
Mutex::new(RefCell::new(None));
const TIMESLICE_FREQUENCY: fugit::HertzU32 = fugit::HertzU32::from_raw(crate::CONFIG.tick_rate_hz);
pub type TimeBase = PeriodicTimer<ErasedTimer>;
static ALARM0: Mutex<RefCell<Option<TimeBase>>> = Mutex::new(RefCell::new(None));
const TIMESLICE_FREQUENCY: fugit::HertzU64 =
fugit::HertzU64::from_raw(crate::CONFIG.tick_rate_hz as u64);
// Time keeping
pub const TICKS_PER_SECOND: u64 = 1_000_000;
pub fn setup_timer(systimer: TimeBase) -> Result<(), esp_hal::timer::Error> {
pub fn setup_timer(mut alarm0: TimeBase) -> Result<(), esp_hal::timer::Error> {
// make sure the scheduling won't start before everything is setup
riscv::interrupt::disable();
let alarm0 = systimer.into_periodic();
alarm0.set_period(TIMESLICE_FREQUENCY.into_duration());
alarm0.clear_interrupt();
alarm0.enable_interrupt(true);
critical_section::with(|cs| ALARM0.borrow_ref_mut(cs).replace(alarm0));
unsafe {
interrupt::bind_interrupt(
Interrupt::SYSTIMER_TARGET0,
core::mem::transmute::<*const (), unsafe extern "C" fn()>(
systimer_target0 as *const (),
),
);
}
unwrap!(interrupt::enable(
Interrupt::SYSTIMER_TARGET0,
alarm0.set_interrupt_handler(InterruptHandler::new(
unsafe { core::mem::transmute(handler as *const ()) },
interrupt::Priority::Priority1,
));
alarm0.start(TIMESLICE_FREQUENCY.into_duration())?;
critical_section::with(|cs| {
alarm0.enable_interrupt(true);
ALARM0.borrow_ref_mut(cs).replace(alarm0);
});
Ok(())
}
@ -64,7 +56,7 @@ pub fn setup_multitasking() {
}
}
extern "C" fn systimer_target0(trap_frame: &mut TrapFrame) {
extern "C" fn handler(trap_frame: &mut TrapFrame) {
// clear the systimer intr
critical_section::with(|cs| {
unwrap!(ALARM0.borrow_ref_mut(cs).as_mut()).clear_interrupt();
@ -83,10 +75,8 @@ extern "C" fn FROM_CPU_INTR3(trap_frame: &mut TrapFrame) {
}
critical_section::with(|cs| {
let alarm0 = ALARM0.borrow_ref(cs);
let alarm0 = unwrap!(alarm0.as_ref());
alarm0.set_period(TIMESLICE_FREQUENCY.into_duration());
let mut alarm0 = ALARM0.borrow_ref_mut(cs);
let alarm0 = unwrap!(alarm0.as_mut());
alarm0.clear_interrupt();
});

View File

@ -1,22 +1,18 @@
use core::cell::RefCell;
use critical_section::Mutex;
use esp_hal::{
interrupt::InterruptHandler,
timer::{ErasedTimer, PeriodicTimer},
};
use crate::{
hal::{
interrupt,
peripherals::{self, TIMG1},
prelude::*,
timer::timg::{Timer, Timer0},
trapframe::TrapFrame,
xtensa_lx,
xtensa_lx_rt,
},
hal::{interrupt, trapframe::TrapFrame, xtensa_lx, xtensa_lx_rt},
preempt::preempt::task_switch,
};
/// The timer responsible for time slicing.
pub type TimeBase = Timer<Timer0<TIMG1>, esp_hal::Blocking>;
pub type TimeBase = PeriodicTimer<ErasedTimer>;
static TIMER1: Mutex<RefCell<Option<TimeBase>>> = Mutex::new(RefCell::new(None));
const TIMESLICE_FREQUENCY: fugit::HertzU64 =
fugit::HertzU64::from_raw(crate::CONFIG.tick_rate_hz as u64);
@ -30,23 +26,14 @@ pub fn get_systimer_count() -> u64 {
esp_hal::time::current_time().ticks()
}
pub fn setup_timer(timer1: TimeBase) -> Result<(), esp_hal::timer::Error> {
unsafe {
interrupt::bind_interrupt(
peripherals::Interrupt::TG1_T0_LEVEL,
core::mem::transmute(tg1_t0_level as *const ()),
);
}
unwrap!(interrupt::enable(
peripherals::Interrupt::TG1_T0_LEVEL,
pub fn setup_timer(mut timer1: TimeBase) -> Result<(), esp_hal::timer::Error> {
timer1.set_interrupt_handler(InterruptHandler::new(
unsafe { core::mem::transmute(handler as *const ()) },
interrupt::Priority::Priority2,
));
timer1.listen();
timer1.load_value(TIMESLICE_FREQUENCY.into_duration())?;
timer1.start();
timer1.start(TIMESLICE_FREQUENCY.into_duration())?;
critical_section::with(|cs| {
timer1.enable_interrupt(true);
TIMER1.borrow_ref_mut(cs).replace(timer1);
});
Ok(())
@ -68,16 +55,12 @@ fn do_task_switch(context: &mut TrapFrame) {
let mut timer = TIMER1.borrow_ref_mut(cs);
let timer = unwrap!(timer.as_mut());
timer.clear_interrupt();
timer
.load_value(TIMESLICE_FREQUENCY.into_duration())
.unwrap();
timer.start();
});
task_switch(context);
}
extern "C" fn tg1_t0_level(context: &mut TrapFrame) {
extern "C" fn handler(context: &mut TrapFrame) {
do_task_switch(context);
}

View File

@ -74,8 +74,6 @@ embedded-hal = ["esp-hal/embedded-hal"]
embassy = ["dep:esp-hal-embassy"]
embassy-time-systimer-16mhz = ["esp-hal-embassy/time-systimer-16mhz"]
embassy-time-timg0 = ["esp-hal-embassy/time-timg0"]
embassy-generic-timers = ["embassy-time/generic-queue-8"]
opsram-2m = ["esp-hal/opsram-2m"]

View File

@ -40,7 +40,7 @@ To demonstrated, in `src/bin/embassy_hello_world.rs` you will see the following:
```rust
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy embassy-generic-timers embassy-time-timg0
//% FEATURES: embassy esp-hal-embassy/integrated-timers
```
Another thing to be aware of is the GPIO pins being used. We have tried to use pins available the DevKit-C boards from Espressif, however this is being done on a best-effort basis.

View File

@ -4,7 +4,7 @@
//! concurrently.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: embassy esp-hal-embassy/integrated-timers
#![no_std]
#![no_main]
@ -17,9 +17,19 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[embassy_executor::task]
async fn run() {
loop {
@ -30,13 +40,18 @@ async fn run() {
#[main]
async fn main(spawner: Spawner) {
esp_println::logger::init_logger_from_env();
esp_println::println!("Init!");
let peripherals = Peripherals::take();
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timers = [timer0];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
spawner.spawn(run()).ok();

View File

@ -11,7 +11,7 @@
//! LIS3DH to get accelerometer data.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -26,18 +26,31 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use lis3dh_async::{Lis3dh, Range, SlaveAddr};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
let peripherals = Peripherals::take();
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timers = [timer0];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -12,7 +12,7 @@
//!
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -27,17 +27,30 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
let peripherals = Peripherals::take();
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timers = [timer0];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -12,7 +12,7 @@
//! You can also inspect the MCLK, BCLK and WS with a logic analyzer.
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -28,10 +28,20 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use esp_println::println;
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
println!("Init!");
@ -39,8 +49,11 @@ async fn main(_spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timers = [timer0];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -27,7 +27,7 @@
//! | XSMT | +3V3 |
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -43,7 +43,7 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use esp_println::println;
@ -55,6 +55,16 @@ const SINE: [i16; 64] = [
-28897, -27244, -25329, -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
];
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
println!("Init!");
@ -62,8 +72,11 @@ async fn main(_spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timers = [timer0];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -4,7 +4,7 @@
//! signal set by the task running on the other core.
//% CHIPS: esp32 esp32s3
//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -23,7 +23,7 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use esp_hal_embassy::Executor;
use esp_println::println;
@ -31,6 +31,16 @@ use static_cell::StaticCell;
static mut APP_CORE_STACK: Stack<8192> = Stack::new();
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
/// Waits for a message that contains a duration, then flashes a led for that
/// duration of time.
#[embassy_executor::task]
@ -58,8 +68,12 @@ async fn main(_spawner: Spawner) {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timer1 = OneShotTimer::new(timg0.timer1.into());
let timers = [timer0, timer1];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 2], timers);
esp_hal_embassy::init(&clocks, timers);
let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);

View File

@ -4,7 +4,7 @@
//! signal set by the task running on the other core.
//% CHIPS: esp32 esp32s3
//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -23,7 +23,7 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use esp_hal_embassy::InterruptExecutor;
use esp_println::println;
@ -31,6 +31,16 @@ use static_cell::StaticCell;
static mut APP_CORE_STACK: Stack<8192> = Stack::new();
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
/// Waits for a message that contains a duration, then flashes a led for that
/// duration of time.
#[embassy_executor::task]
@ -77,8 +87,12 @@ fn main() -> ! {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timer1 = OneShotTimer::new(timg0.timer1.into());
let timers = [timer0, timer1];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 2], timers);
esp_hal_embassy::init(&clocks, timers);
let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);

View File

@ -15,7 +15,7 @@
// The interrupt-executor is created in `main` and is used to spawn `high_prio`.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: embassy esp-hal-embassy/log esp-hal-embassy/integrated-timers
#![no_std]
#![no_main]
@ -29,12 +29,22 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{/*systimer::SystemTimer,*/ timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use esp_hal_embassy::InterruptExecutor;
use esp_println::println;
use static_cell::StaticCell;
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
/// Periodically print something.
#[embassy_executor::task]
async fn high_prio() {
@ -78,8 +88,21 @@ async fn main(low_prio_spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
#[cfg(not(feature = "esp32c2"))]
let timer1 = {
let timg1 = TimerGroup::new(peripherals.TIMG1, &clocks, None);
OneShotTimer::new(timg1.timer0.into())
};
#[cfg(feature = "esp32c2")]
let timer1 = {
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
OneShotTimer::new(systimer.alarm0.into())
};
let timers = [timer0, timer1];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 2], timers);
esp_hal_embassy::init(&clocks, timers);
static EXECUTOR: StaticCell<InterruptExecutor<2>> = StaticCell::new();
let executor = InterruptExecutor::new(system.software_interrupt_control.software_interrupt2);

View File

@ -4,7 +4,7 @@
//! Uses GPIO 1, 2, 3 and 4 as the data pins.
//% CHIPS: esp32c6 esp32h2
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -21,10 +21,20 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{systimer::SystemTimer, ErasedTimer, OneShotTimer},
};
use esp_println::println;
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
esp_println::println!("Init!");
@ -32,8 +42,10 @@ async fn main(_spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let systimer = SystemTimer::new(peripherals.SYSTIMER);
let timers = [OneShotTimer::new(systimer.alarm0.into())];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -8,7 +8,7 @@
//! You can use a logic analyzer to see how the pins are used.
//% CHIPS: esp32c6 esp32h2
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -32,10 +32,20 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{systimer::SystemTimer, ErasedTimer, OneShotTimer},
};
use esp_println::println;
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
esp_println::println!("Init!");
@ -43,12 +53,14 @@ async fn main(_spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let systimer = SystemTimer::new(peripherals.SYSTIMER);
let timers = [OneShotTimer::new(systimer.alarm0.into())];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let (tx_buffer, mut tx_descriptors, _, _) = dma_buffers!(32000, 0);
let (tx_buffer, tx_descriptors, _, _) = dma_buffers!(32000, 0);
let dma = Dma::new(peripherals.DMA);
let dma_channel = dma.channel0;

View File

@ -2,7 +2,7 @@
//! Connect GPIO5 to GPIO4
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -17,6 +17,7 @@ use esp_hal::{
prelude::*,
rmt::{asynch::RxChannelAsync, PulseCode, Rmt, RxChannelConfig, RxChannelCreatorAsync},
system::SystemControl,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use esp_println::{print, println};
@ -25,6 +26,16 @@ const WIDTH: usize = 80;
#[cfg(debug_assertions)]
compile_error!("Run this example in release mode");
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[embassy_executor::task]
async fn signal_task(mut pin: Output<'static, Gpio5>) {
loop {
@ -43,8 +54,11 @@ async fn main(spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timer_group0 = esp_hal::timer::timg::TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timer_group0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timers = [timer0];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -3,7 +3,7 @@
//! Connect a logic analyzer to GPIO4 to see the generated pulses.
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -18,10 +18,20 @@ use esp_hal::{
prelude::*,
rmt::{asynch::TxChannelAsync, PulseCode, Rmt, TxChannelConfig, TxChannelCreatorAsync},
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use esp_println::println;
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
println!("Init!");
@ -29,8 +39,11 @@ async fn main(_spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timers = [timer0];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -7,7 +7,7 @@
#![no_main]
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
@ -18,7 +18,7 @@ use esp_hal::{
peripherals::{Peripherals, UART0},
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
uart::{
config::{AtCmdConfig, Config},
Uart,
@ -34,6 +34,16 @@ const READ_BUF_SIZE: usize = 64;
// EOT (CTRL-D)
const AT_CMD: u8 = 0x04;
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[embassy_executor::task]
async fn writer(
mut tx: UartTx<'static, UART0, Async>,
@ -85,8 +95,11 @@ async fn main(spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timer0 = OneShotTimer::new(timg0.timer0.into());
let timers = [timer0];
let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -15,7 +15,7 @@
//! This is an example of running the embassy executor with SPI.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -35,9 +35,19 @@ use esp_hal::{
SpiMode,
},
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
esp_println::println!("Init!");
@ -45,8 +55,12 @@ async fn main(_spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timers = mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg0.timer0.into())]
);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let sclk = io.pins.gpio0;

View File

@ -11,7 +11,7 @@
//! with `IS_SENDER` set to `true`.
//% CHIPS: esp32c3 esp32c6 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -27,7 +27,7 @@ use esp_hal::{
peripherals::{self, Peripherals, TWAI0},
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
twai::{self, EspTwaiFrame, TwaiRx, TwaiTx},
};
use esp_println::println;
@ -35,6 +35,16 @@ use static_cell::StaticCell;
type TwaiOutbox = Channel<NoopRawMutex, EspTwaiFrame, 16>;
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[embassy_executor::task]
async fn receiver(
mut rx: TwaiRx<'static, TWAI0, esp_hal::Async>,
@ -85,8 +95,12 @@ async fn main(spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
let timers = mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg0.timer0.into())]
);
esp_hal_embassy::init(&clocks, timers);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

View File

@ -3,7 +3,7 @@
//! This example should be built in release mode.
//% CHIPS: esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -26,9 +26,19 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) -> () {
esp_println::println!("Init!");
@ -36,7 +46,15 @@ async fn main(_spawner: Spawner) -> () {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
esp_hal_embassy::init(&clocks, TimerGroup::new_async(peripherals.TIMG0, &clocks));
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg0.timer0.into())]
),
);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let usb = Usb::new(peripherals.USB0, io.pins.gpio20, io.pins.gpio19);

View File

@ -3,7 +3,7 @@
//! Most dev-kits use a USB-UART-bridge - in that case you won't see any output.
//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -16,7 +16,7 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
usb_serial_jtag::{UsbSerialJtag, UsbSerialJtagRx, UsbSerialJtagTx},
Async,
};
@ -24,6 +24,16 @@ use static_cell::StaticCell;
const MAX_BUFFER_SIZE: usize = 512;
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[embassy_executor::task]
async fn writer(
mut tx: UsbSerialJtagTx<'static, Async>,
@ -70,7 +80,14 @@ async fn main(spawner: Spawner) -> () {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
esp_hal_embassy::init(&clocks, TimerGroup::new_async(peripherals.TIMG0, &clocks));
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg0.timer0.into())]
),
);
let (tx, rx) = UsbSerialJtag::new_async(peripherals.USB_DEVICE).split();

View File

@ -3,7 +3,7 @@
//! This is an example of asynchronously `Wait`ing for a pin state to change.
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
//% FEATURES: async embassy embassy-generic-timers
#![no_std]
#![no_main]
@ -17,9 +17,19 @@ use esp_hal::{
peripherals::Peripherals,
prelude::*,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) {
esp_println::println!("Init!");
@ -27,8 +37,14 @@ async fn main(_spawner: Spawner) {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg0.timer0.into())]
),
);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
#[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))]

View File

@ -21,6 +21,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::PeriodicTimer,
};
use esp_println::{print, println};
use esp_wifi::{
@ -46,10 +47,12 @@ fn main() -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,

View File

@ -22,6 +22,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::PeriodicTimer,
};
use esp_println::{print, println};
use esp_wifi::{
@ -54,10 +55,12 @@ fn main() -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,

View File

@ -22,6 +22,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::PeriodicTimer,
};
use esp_println::println;
use esp_wifi::{
@ -66,10 +67,12 @@ fn main() -> ! {
let server_address: Ipv4Address = HOST_IP.parse().expect("Invalid HOST_IP address");
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,

View File

@ -30,6 +30,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::PeriodicTimer,
};
use esp_println::println;
use esp_wifi::{ble::controller::BleConnector, initialize, EspWifiInitFor};
@ -43,10 +44,12 @@ fn main() -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Ble,
timer,

View File

@ -32,6 +32,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::PeriodicTimer,
};
use esp_println::{print, println};
use esp_wifi::{
@ -59,10 +60,12 @@ fn main() -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::WifiBle,
timer,

View File

@ -19,6 +19,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::PeriodicTimer,
};
use esp_println::{print, println};
use esp_wifi::{
@ -52,10 +53,12 @@ fn main() -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,

View File

@ -8,7 +8,7 @@
//!
//! Because of the huge task-arena size configured this won't work on ESP32-S2
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils
//% FEATURES: async embassy embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
#![no_std]
@ -33,7 +33,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::timg::TimerGroup,
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
};
use esp_println::{print, println};
use esp_wifi::{
@ -50,6 +50,7 @@ use esp_wifi::{
EspWifiInitFor,
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
@ -68,10 +69,12 @@ async fn main(spawner: Spawner) -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,
@ -85,8 +88,29 @@ async fn main(spawner: Spawner) -> ! {
let (wifi_interface, controller) =
esp_wifi::wifi::new_with_mode(&init, wifi, WifiApDevice).unwrap();
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timer_group0);
#[cfg(feature = "esp32")]
{
let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg1.timer0.into())]
),
);
}
#[cfg(not(feature = "esp32"))]
{
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(systimer.alarm0.into())]
),
);
}
let config = Config::ipv4_static(StaticConfigV4 {
address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 2, 1), 24),

View File

@ -11,7 +11,7 @@
//!
//! Because of the huge task-arena size configured this won't work on ESP32-S2
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils
//% FEATURES: async embassy embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
#![no_std]
@ -36,7 +36,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::timg::TimerGroup,
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
};
use esp_println::{print, println};
use esp_wifi::{
@ -58,6 +58,7 @@ use esp_wifi::{
const SSID: &str = env!("SSID");
const PASSWORD: &str = env!("PASSWORD");
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
@ -76,10 +77,12 @@ async fn main(spawner: Spawner) -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,
@ -93,8 +96,29 @@ async fn main(spawner: Spawner) -> ! {
let (wifi_ap_interface, wifi_sta_interface, mut controller) =
esp_wifi::wifi::new_ap_sta(&init, wifi).unwrap();
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timer_group0);
#[cfg(feature = "esp32")]
{
let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg1.timer0.into())]
),
);
}
#[cfg(not(feature = "esp32"))]
{
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(systimer.alarm0.into())]
),
);
}
let ap_config = Config::ipv4_static(StaticConfigV4 {
address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 2, 1), 24),

View File

@ -10,7 +10,7 @@
//! Because of the huge task-arena size configured this won't work on ESP32-S2 and ESP32-C2
//!
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils
//% FEATURES: async embassy embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils
//% CHIPS: esp32 esp32s3 esp32c3 esp32c6
#![no_std]
@ -27,7 +27,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::timg::TimerGroup,
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
};
use esp_println::println;
use esp_wifi::{
@ -44,6 +44,7 @@ use esp_wifi::{
EspWifiInitFor,
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
@ -80,10 +81,12 @@ async fn main(spawner: Spawner) -> ! {
let server_address: Ipv4Address = HOST_IP.parse().expect("Invalid HOST_IP address");
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,
@ -97,8 +100,29 @@ async fn main(spawner: Spawner) -> ! {
let (wifi_interface, controller) =
esp_wifi::wifi::new_with_mode(&init, wifi, WifiStaDevice).unwrap();
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timer_group0);
#[cfg(feature = "esp32")]
{
let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg1.timer0.into())]
),
);
}
#[cfg(not(feature = "esp32"))]
{
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(systimer.alarm0.into())]
),
);
}
let config = Config::dhcpv4(Default::default());

View File

@ -4,7 +4,7 @@
//! - offers one service with three characteristics (one is read/write, one is write only, one is read/write/notify)
//! - pressing the boot-button on a dev-board will send a notification if it is subscribed
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/ble
//% FEATURES: async embassy embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/ble
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6 esp32h2
#![no_std]
@ -33,11 +33,21 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::timg::TimerGroup,
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
};
use esp_println::println;
use esp_wifi::{ble::controller::asynch::BleConnector, initialize, EspWifiInitFor};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) -> ! {
esp_println::logger::init_logger_from_env();
@ -47,10 +57,12 @@ async fn main(_spawner: Spawner) -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Ble,
timer,
@ -71,8 +83,29 @@ async fn main(_spawner: Spawner) -> ! {
))]
let button = Input::new(io.pins.gpio9, Pull::Down);
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timer_group0);
#[cfg(feature = "esp32")]
{
let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg1.timer0.into())]
),
);
}
#[cfg(not(feature = "esp32"))]
{
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(systimer.alarm0.into())]
),
);
}
let mut bluetooth = peripherals.BT;

View File

@ -7,7 +7,7 @@
//!
//! Because of the huge task-arena size configured this won't work on ESP32-S2
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils
//% FEATURES: async embassy embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
#![no_std]
@ -23,7 +23,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::timg::TimerGroup,
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
};
use esp_println::println;
use esp_wifi::{
@ -40,6 +40,7 @@ use esp_wifi::{
EspWifiInitFor,
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
@ -61,10 +62,12 @@ async fn main(spawner: Spawner) -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,
@ -78,8 +81,29 @@ async fn main(spawner: Spawner) -> ! {
let (wifi_interface, controller) =
esp_wifi::wifi::new_with_mode(&init, wifi, WifiStaDevice).unwrap();
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timer_group0);
#[cfg(feature = "esp32")]
{
let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg1.timer0.into())]
),
);
}
#[cfg(not(feature = "esp32"))]
{
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(systimer.alarm0.into())]
),
);
}
let config = Config::dhcpv4(Default::default());

View File

@ -4,7 +4,7 @@
//!
//! Because of the huge task-arena size configured this won't work on ESP32-S2
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils esp-wifi/esp-now
//% FEATURES: async embassy embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils esp-wifi/esp-now
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
#![no_std]
@ -20,7 +20,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::timg::TimerGroup,
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
};
use esp_println::println;
use esp_wifi::{
@ -29,6 +29,16 @@ use esp_wifi::{
EspWifiInitFor,
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[main]
async fn main(_spawner: Spawner) -> ! {
esp_println::logger::init_logger_from_env();
@ -38,10 +48,12 @@ async fn main(_spawner: Spawner) -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,
@ -55,8 +67,29 @@ async fn main(_spawner: Spawner) -> ! {
let mut esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap();
println!("esp-now version {}", esp_now.get_version().unwrap());
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timer_group0);
#[cfg(feature = "esp32")]
{
let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg1.timer0.into())]
),
);
}
#[cfg(not(feature = "esp32"))]
{
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(systimer.alarm0.into())]
),
);
}
let mut ticker = Ticker::every(Duration::from_secs(5));
loop {

View File

@ -4,7 +4,7 @@
//!
//! Because of the huge task-arena size configured this won't work on ESP32-S2
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils esp-wifi/esp-now
//% FEATURES: async embassy embassy-generic-timers esp-wifi esp-wifi/async esp-wifi/embassy-net esp-wifi/wifi-default esp-wifi/wifi esp-wifi/utils esp-wifi/esp-now
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
#![no_std]
@ -20,7 +20,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::timg::TimerGroup,
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
};
use esp_println::println;
use esp_wifi::{
@ -29,6 +29,7 @@ use esp_wifi::{
EspWifiInitFor,
};
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
@ -47,10 +48,12 @@ async fn main(spawner: Spawner) -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,
@ -64,8 +67,29 @@ async fn main(spawner: Spawner) -> ! {
let esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap();
println!("esp-now version {}", esp_now.get_version().unwrap());
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timer_group0);
#[cfg(feature = "esp32")]
{
let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg1.timer0.into())]
),
);
}
#[cfg(not(feature = "esp32"))]
{
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(systimer.alarm0.into())]
),
);
}
let (manager, sender, receiver) = esp_now.split();
let manager = mk_static!(EspNowManager<'static>, manager);

View File

@ -15,6 +15,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::PeriodicTimer,
};
use esp_println::println;
use esp_wifi::{
@ -33,10 +34,12 @@ fn main() -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,

View File

@ -20,6 +20,7 @@ use esp_hal::{
prelude::*,
rng::Rng,
system::SystemControl,
timer::PeriodicTimer,
};
use esp_println::{print, println};
use esp_wifi::{
@ -52,10 +53,12 @@ fn main() -> ! {
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::max(system.clock_control).freeze();
#[cfg(target_arch = "xtensa")]
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
#[cfg(target_arch = "riscv32")]
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
let timer = PeriodicTimer::new(
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
.timer0
.into(),
);
let init = initialize(
EspWifiInitFor::Wifi,
timer,

View File

@ -106,6 +106,7 @@ esp-backtrace = { path = "../esp-backtrace", default-features = false, feat
esp-hal = { path = "../esp-hal", features = ["defmt", "embedded-hal", "embedded-hal-02"], optional = true }
esp-hal-embassy = { path = "../esp-hal-embassy", optional = true }
portable-atomic = "1.6.0"
static_cell = { version = "2.0.0", features = ["nightly"] }
[dev-dependencies]
crypto-bigint = { version = "0.5.5", default-features = false }
@ -122,7 +123,7 @@ p256 = { version = "0.13.2", default-features = false, features =
semihosting = { git = "https://github.com/taiki-e/semihosting", tag = "v0.1.10" }
[features]
default = ["async", "embassy", "embassy-time-timg0"]
default = ["async", "embassy"]
# Device support (required!):
esp32 = [
@ -154,9 +155,6 @@ embassy = [
"embedded-test/external-executor",
"dep:esp-hal-embassy",
]
embassy-time-systimer-16mhz = ["esp-hal-embassy/time-systimer-16mhz"]
embassy-time-systimer-80mhz = ["esp-hal-embassy/time-systimer-80mhz"]
embassy-time-timg0 = ["esp-hal-embassy/time-timg0"]
# https://doc.rust-lang.org/cargo/reference/profiles.html#test
# Test and bench profiles inherit from dev and release respectively.

View File

@ -21,9 +21,18 @@ use esp_hal::{
macros::handler,
peripherals::Peripherals,
system::SystemControl,
timer::timg::TimerGroup,
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
static COUNTER: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
static INPUT_PIN: Mutex<RefCell<Option<Input<'static, Gpio2>>>> = Mutex::new(RefCell::new(None));
@ -44,8 +53,14 @@ impl<'d> Context<'d> {
let delay = Delay::new(&clocks);
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
esp_hal_embassy::init(&clocks, timg0);
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
esp_hal_embassy::init(
&clocks,
mk_static!(
[OneShotTimer<ErasedTimer>; 1],
[OneShotTimer::new(timg0.timer0.into())]
),
);
Context {
io2: Input::new(io.pins.gpio2, Pull::Down),

View File

@ -487,19 +487,15 @@ fn lint_packages(workspace: &Path, _args: LintPackagesArgs) -> Result<()> {
}
Package::EspHalEmbassy => {
// We need to specify a time driver, so we will check all
// options here (as the modules themselves are feature-gated):
for feature in ["time-systimer-16mhz", "time-timg0"] {
lint_package(
&path,
&[
"-Zbuild-std=core",
"--target=riscv32imac-unknown-none-elf",
&format!("--features=esp32c6,{feature}"),
"--features=esp32c6",
],
)?;
}
}
Package::EspHalProcmacros | Package::EspRiscvRt => lint_package(
&path,
@ -538,7 +534,7 @@ fn lint_packages(workspace: &Path, _args: LintPackagesArgs) -> Result<()> {
&[
"-Zbuild-std=core",
"--target=riscv32imc-unknown-none-elf",
"--features=esp32c3,wifi-default,ble,esp-now,async,embassy-net,esp-hal-embassy/time-timg0",
"--features=esp32c3,wifi-default,ble,esp-now,async,embassy-net",
],
)?,