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:
parent
8e0a2012dc
commit
a5be31fadc
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Removed the TIMG and SYSTIMER time-drivers, replaced by a generic time-driver taking `OneShotTimer<ErasedTimer>` (#1753)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@ -9,16 +9,17 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
default-target = "riscv32imac-unknown-none-elf"
|
default-target = "riscv32imac-unknown-none-elf"
|
||||||
features = ["esp32c6", "time-timg0"]
|
features = ["esp32c6"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
critical-section = "1.1.2"
|
critical-section = "1.1.2"
|
||||||
defmt = { version = "0.3.8", optional = true }
|
defmt = { version = "0.3.8", optional = true }
|
||||||
document-features = "0.2.8"
|
document-features = "0.2.8"
|
||||||
embassy-executor = { version = "0.5.0", optional = true }
|
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" }
|
esp-hal = { version = "0.18.0", path = "../esp-hal" }
|
||||||
portable-atomic = "1.6.0"
|
portable-atomic = "1.6.0"
|
||||||
|
log = { version = "0.4.22", optional = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
@ -38,15 +39,9 @@ esp32s3 = ["esp-hal/esp32s3"]
|
|||||||
|
|
||||||
## Implement `defmt::Format` on certain types.
|
## Implement `defmt::Format` on certain types.
|
||||||
defmt = ["dep:defmt", "embassy-executor?/defmt", "esp-hal/defmt"]
|
defmt = ["dep:defmt", "embassy-executor?/defmt", "esp-hal/defmt"]
|
||||||
|
## Enable logging via the log crate
|
||||||
|
log = ["dep:log"]
|
||||||
## Provide `Executor` and `InterruptExecutor`
|
## Provide `Executor` and `InterruptExecutor`
|
||||||
executors = ["dep:embassy-executor"]
|
executors = ["dep:embassy-executor"]
|
||||||
## Use the executor-integrated `embassy-time` timer queue.
|
## Use the executor-integrated `embassy-time` timer queue.
|
||||||
integrated-timers = ["embassy-executor?/integrated-timers"]
|
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"]
|
|
||||||
|
|||||||
@ -10,18 +10,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
"esp32", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32s2", "esp32s3"
|
"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!
|
// NOTE: update when adding new device support!
|
||||||
// Determine the name of the configured device:
|
// Determine the name of the configured device:
|
||||||
let device_name = if cfg!(feature = "esp32") {
|
let device_name = if cfg!(feature = "esp32") {
|
||||||
|
|||||||
@ -36,69 +36,17 @@
|
|||||||
// MUST be the first module
|
// MUST be the first module
|
||||||
mod fmt;
|
mod fmt;
|
||||||
|
|
||||||
use core::cell::Cell;
|
|
||||||
|
|
||||||
use embassy_time_driver::{AlarmHandle, Driver};
|
|
||||||
use esp_hal::clock::Clocks;
|
use esp_hal::clock::Clocks;
|
||||||
|
|
||||||
#[cfg(feature = "executors")]
|
#[cfg(feature = "executors")]
|
||||||
pub use self::executor::{Executor, InterruptExecutor};
|
pub use self::executor::{Executor, InterruptExecutor};
|
||||||
use self::time_driver::{EmbassyTimer, TimerType};
|
use self::time_driver::{EmbassyTimer, Timer};
|
||||||
|
|
||||||
#[cfg(feature = "executors")]
|
#[cfg(feature = "executors")]
|
||||||
mod executor;
|
mod executor;
|
||||||
mod time_driver;
|
mod time_driver;
|
||||||
|
|
||||||
/// Initialize embassy
|
/// 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)
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,9 +1,180 @@
|
|||||||
#[cfg(any(feature = "time-systimer-16mhz", feature = "time-systimer-80mhz"))]
|
use core::cell::{Cell, RefCell};
|
||||||
pub use self::systimer::*;
|
|
||||||
#[cfg(feature = "time-timg0")]
|
|
||||||
pub use self::timg::*;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "time-systimer-16mhz", feature = "time-systimer-80mhz"))]
|
use critical_section::Mutex;
|
||||||
mod systimer;
|
use embassy_time_driver::{AlarmHandle, Driver};
|
||||||
#[cfg(feature = "time-timg0")]
|
use esp_hal::{
|
||||||
mod timg;
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -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),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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)
|
- dma: add Mem2Mem to support memory to memory transfer (#1738)
|
||||||
- Add `uart` wake source (#1727)
|
- Add `uart` wake source (#1727)
|
||||||
- uart: Make `rx_timeout` optional in Config struct (#1759)
|
- uart: Make `rx_timeout` optional in Config struct (#1759)
|
||||||
|
- Add interrupt related functions to `PeriodicTimer`/`OneShotTimer`, added `ErasedTimer` (#1753)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,8 @@
|
|||||||
|
|
||||||
use fugit::{ExtU64, Instant, MicrosDurationU64};
|
use fugit::{ExtU64, Instant, MicrosDurationU64};
|
||||||
|
|
||||||
|
use crate::{interrupt::InterruptHandler, private};
|
||||||
|
|
||||||
#[cfg(systimer)]
|
#[cfg(systimer)]
|
||||||
pub mod systimer;
|
pub mod systimer;
|
||||||
#[cfg(any(timg0, timg1))]
|
#[cfg(any(timg0, timg1))]
|
||||||
@ -90,6 +92,11 @@ pub trait Timer: crate::private::Sealed {
|
|||||||
/// Clear the timer's interrupt.
|
/// Clear the timer's interrupt.
|
||||||
fn clear_interrupt(&self);
|
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?
|
/// Has the timer triggered?
|
||||||
fn is_interrupt_set(&self) -> bool;
|
fn is_interrupt_set(&self) -> bool;
|
||||||
|
|
||||||
@ -146,6 +153,45 @@ where
|
|||||||
self.inner.stop();
|
self.inner.stop();
|
||||||
self.inner.clear_interrupt();
|
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")]
|
#[cfg(feature = "embedded-hal-02")]
|
||||||
@ -232,6 +278,160 @@ where
|
|||||||
|
|
||||||
Ok(())
|
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")]
|
#[cfg(feature = "embedded-hal-02")]
|
||||||
|
|||||||
@ -229,11 +229,8 @@ where
|
|||||||
tconf.modify(|_r, w| w.work_en().set_bit());
|
tconf.modify(|_r, w| w.work_en().set_bit());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, const CHANNEL: u8> Alarm<T, Blocking, CHANNEL> {
|
fn set_interrupt_handler_internal(&self, handler: InterruptHandler) {
|
||||||
/// Set the interrupt handler for this alarm.
|
|
||||||
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
|
||||||
match CHANNEL {
|
match CHANNEL {
|
||||||
0 => unsafe {
|
0 => unsafe {
|
||||||
interrupt::bind_interrupt(Interrupt::SYSTIMER_TARGET0, handler.handler());
|
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>
|
impl<DM, const CHANNEL: u8> Alarm<Target, DM, CHANNEL>
|
||||||
where
|
where
|
||||||
DM: Mode,
|
DM: Mode,
|
||||||
@ -572,6 +576,10 @@ where
|
|||||||
fn set_alarm_active(&self, _active: bool) {
|
fn set_alarm_active(&self, _active: bool) {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_interrupt_handler(&self, handler: InterruptHandler) {
|
||||||
|
Alarm::set_interrupt_handler_internal(self, handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async functionality of the system timer.
|
// Async functionality of the system timer.
|
||||||
|
|||||||
@ -518,9 +518,16 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn enable_interrupt(&self, state: bool) {
|
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()
|
self.register_block()
|
||||||
.int_ena_timers()
|
.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) {
|
fn clear_interrupt(&self) {
|
||||||
@ -529,6 +536,24 @@ where
|
|||||||
.write(|w| w.t(self.timer_number()).clear_bit_by_one());
|
.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 {
|
fn is_interrupt_set(&self) -> bool {
|
||||||
self.register_block()
|
self.register_block()
|
||||||
.int_raw_timers()
|
.int_raw_timers()
|
||||||
@ -549,6 +574,8 @@ where
|
|||||||
pub trait Instance: Sealed + Enable {
|
pub trait Instance: Sealed + Enable {
|
||||||
fn register_block(&self) -> &RegisterBlock;
|
fn register_block(&self) -> &RegisterBlock;
|
||||||
|
|
||||||
|
fn timer_group(&self) -> u8;
|
||||||
|
|
||||||
fn timer_number(&self) -> u8;
|
fn timer_number(&self) -> u8;
|
||||||
|
|
||||||
fn reset_counter(&self);
|
fn reset_counter(&self);
|
||||||
@ -633,6 +660,10 @@ where
|
|||||||
unsafe { &*TG::register_block() }
|
unsafe { &*TG::register_block() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn timer_group(&self) -> u8 {
|
||||||
|
TG::id()
|
||||||
|
}
|
||||||
|
|
||||||
fn timer_number(&self) -> u8 {
|
fn timer_number(&self) -> u8 {
|
||||||
T
|
T
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Changed
|
### Changed
|
||||||
- `esp_wifi::initialize` no longer requires running maximum CPU clock, instead check it runs above 80MHz. (#1688)
|
- `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)
|
- Rename `set_mode` to `set_protocol`, also available in esp-now API (#1742)
|
||||||
|
- `esp_wifi::initialize` now takes a `PeriodicTimer<ErasedTimer>` (#1753)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|||||||
@ -141,7 +141,6 @@ features = [
|
|||||||
"coex",
|
"coex",
|
||||||
"async",
|
"async",
|
||||||
"embassy-net",
|
"embassy-net",
|
||||||
"esp-hal-embassy/time-timg0",
|
|
||||||
"esp-hal/default",
|
"esp-hal/default",
|
||||||
]
|
]
|
||||||
default-target = "riscv32imc-unknown-none-elf"
|
default-target = "riscv32imc-unknown-none-elf"
|
||||||
|
|||||||
@ -18,8 +18,6 @@ use common_adapter::{chip_specific::phy_mem_init, init_radio_clock_control, RADI
|
|||||||
use critical_section::Mutex;
|
use critical_section::Mutex;
|
||||||
use esp_hal as hal;
|
use esp_hal as hal;
|
||||||
use fugit::MegahertzU32;
|
use fugit::MegahertzU32;
|
||||||
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2))]
|
|
||||||
use hal::timer::systimer::{Alarm, Target};
|
|
||||||
use hal::{clock::Clocks, system::RadioClockController};
|
use hal::{clock::Clocks, system::RadioClockController};
|
||||||
use linked_list_allocator::Heap;
|
use linked_list_allocator::Heap;
|
||||||
#[cfg(feature = "wifi")]
|
#[cfg(feature = "wifi")]
|
||||||
@ -144,12 +142,7 @@ fn init_heap() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(esp32c3, esp32c2, esp32c6, esp32h2))]
|
pub(crate) type EspWifiTimer = crate::timer::TimeBase;
|
||||||
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>;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd)]
|
#[derive(Debug, PartialEq, PartialOrd)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
|
||||||
use critical_section::Mutex;
|
use critical_section::Mutex;
|
||||||
|
use esp_hal::{
|
||||||
|
interrupt::InterruptHandler,
|
||||||
|
timer::{ErasedTimer, PeriodicTimer},
|
||||||
|
};
|
||||||
#[cfg(any(feature = "esp32c6", feature = "esp32h2"))]
|
#[cfg(any(feature = "esp32c6", feature = "esp32h2"))]
|
||||||
use peripherals::INTPRI as SystemPeripheral;
|
use peripherals::INTPRI as SystemPeripheral;
|
||||||
#[cfg(not(any(feature = "esp32c6", feature = "esp32h2")))]
|
#[cfg(not(any(feature = "esp32c6", feature = "esp32h2")))]
|
||||||
@ -10,46 +14,34 @@ use crate::{
|
|||||||
hal::{
|
hal::{
|
||||||
interrupt::{self, TrapFrame},
|
interrupt::{self, TrapFrame},
|
||||||
peripherals::{self, Interrupt},
|
peripherals::{self, Interrupt},
|
||||||
prelude::*,
|
|
||||||
riscv,
|
riscv,
|
||||||
timer::systimer::{Alarm, Periodic, Target},
|
|
||||||
},
|
},
|
||||||
preempt::preempt::task_switch,
|
preempt::preempt::task_switch,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The timer responsible for time slicing.
|
/// The timer responsible for time slicing.
|
||||||
pub type TimeBase = Alarm<Target, esp_hal::Blocking, 0>;
|
pub type TimeBase = PeriodicTimer<ErasedTimer>;
|
||||||
static ALARM0: Mutex<RefCell<Option<Alarm<Periodic, esp_hal::Blocking, 0>>>> =
|
static ALARM0: Mutex<RefCell<Option<TimeBase>>> = Mutex::new(RefCell::new(None));
|
||||||
Mutex::new(RefCell::new(None));
|
const TIMESLICE_FREQUENCY: fugit::HertzU64 =
|
||||||
const TIMESLICE_FREQUENCY: fugit::HertzU32 = fugit::HertzU32::from_raw(crate::CONFIG.tick_rate_hz);
|
fugit::HertzU64::from_raw(crate::CONFIG.tick_rate_hz as u64);
|
||||||
|
|
||||||
// Time keeping
|
// Time keeping
|
||||||
pub const TICKS_PER_SECOND: u64 = 1_000_000;
|
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
|
// make sure the scheduling won't start before everything is setup
|
||||||
riscv::interrupt::disable();
|
riscv::interrupt::disable();
|
||||||
|
|
||||||
let alarm0 = systimer.into_periodic();
|
alarm0.set_interrupt_handler(InterruptHandler::new(
|
||||||
alarm0.set_period(TIMESLICE_FREQUENCY.into_duration());
|
unsafe { core::mem::transmute(handler as *const ()) },
|
||||||
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,
|
|
||||||
interrupt::Priority::Priority1,
|
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(())
|
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
|
// clear the systimer intr
|
||||||
critical_section::with(|cs| {
|
critical_section::with(|cs| {
|
||||||
unwrap!(ALARM0.borrow_ref_mut(cs).as_mut()).clear_interrupt();
|
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| {
|
critical_section::with(|cs| {
|
||||||
let alarm0 = ALARM0.borrow_ref(cs);
|
let mut alarm0 = ALARM0.borrow_ref_mut(cs);
|
||||||
let alarm0 = unwrap!(alarm0.as_ref());
|
let alarm0 = unwrap!(alarm0.as_mut());
|
||||||
|
|
||||||
alarm0.set_period(TIMESLICE_FREQUENCY.into_duration());
|
|
||||||
alarm0.clear_interrupt();
|
alarm0.clear_interrupt();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +1,18 @@
|
|||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
|
||||||
use critical_section::Mutex;
|
use critical_section::Mutex;
|
||||||
|
use esp_hal::{
|
||||||
|
interrupt::InterruptHandler,
|
||||||
|
timer::{ErasedTimer, PeriodicTimer},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hal::{
|
hal::{interrupt, trapframe::TrapFrame, xtensa_lx, xtensa_lx_rt},
|
||||||
interrupt,
|
|
||||||
peripherals::{self, TIMG1},
|
|
||||||
prelude::*,
|
|
||||||
timer::timg::{Timer, Timer0},
|
|
||||||
trapframe::TrapFrame,
|
|
||||||
xtensa_lx,
|
|
||||||
xtensa_lx_rt,
|
|
||||||
},
|
|
||||||
preempt::preempt::task_switch,
|
preempt::preempt::task_switch,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The timer responsible for time slicing.
|
/// 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));
|
static TIMER1: Mutex<RefCell<Option<TimeBase>>> = Mutex::new(RefCell::new(None));
|
||||||
const TIMESLICE_FREQUENCY: fugit::HertzU64 =
|
const TIMESLICE_FREQUENCY: fugit::HertzU64 =
|
||||||
fugit::HertzU64::from_raw(crate::CONFIG.tick_rate_hz as u64);
|
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()
|
esp_hal::time::current_time().ticks()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_timer(timer1: TimeBase) -> Result<(), esp_hal::timer::Error> {
|
pub fn setup_timer(mut timer1: TimeBase) -> Result<(), esp_hal::timer::Error> {
|
||||||
unsafe {
|
timer1.set_interrupt_handler(InterruptHandler::new(
|
||||||
interrupt::bind_interrupt(
|
unsafe { core::mem::transmute(handler as *const ()) },
|
||||||
peripherals::Interrupt::TG1_T0_LEVEL,
|
|
||||||
core::mem::transmute(tg1_t0_level as *const ()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
unwrap!(interrupt::enable(
|
|
||||||
peripherals::Interrupt::TG1_T0_LEVEL,
|
|
||||||
interrupt::Priority::Priority2,
|
interrupt::Priority::Priority2,
|
||||||
));
|
));
|
||||||
|
timer1.start(TIMESLICE_FREQUENCY.into_duration())?;
|
||||||
timer1.listen();
|
|
||||||
timer1.load_value(TIMESLICE_FREQUENCY.into_duration())?;
|
|
||||||
timer1.start();
|
|
||||||
critical_section::with(|cs| {
|
critical_section::with(|cs| {
|
||||||
|
timer1.enable_interrupt(true);
|
||||||
TIMER1.borrow_ref_mut(cs).replace(timer1);
|
TIMER1.borrow_ref_mut(cs).replace(timer1);
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -68,16 +55,12 @@ fn do_task_switch(context: &mut TrapFrame) {
|
|||||||
let mut timer = TIMER1.borrow_ref_mut(cs);
|
let mut timer = TIMER1.borrow_ref_mut(cs);
|
||||||
let timer = unwrap!(timer.as_mut());
|
let timer = unwrap!(timer.as_mut());
|
||||||
timer.clear_interrupt();
|
timer.clear_interrupt();
|
||||||
timer
|
|
||||||
.load_value(TIMESLICE_FREQUENCY.into_duration())
|
|
||||||
.unwrap();
|
|
||||||
timer.start();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
task_switch(context);
|
task_switch(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn tg1_t0_level(context: &mut TrapFrame) {
|
extern "C" fn handler(context: &mut TrapFrame) {
|
||||||
do_task_switch(context);
|
do_task_switch(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -74,8 +74,6 @@ embedded-hal = ["esp-hal/embedded-hal"]
|
|||||||
|
|
||||||
embassy = ["dep:esp-hal-embassy"]
|
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"]
|
embassy-generic-timers = ["embassy-time/generic-queue-8"]
|
||||||
|
|
||||||
opsram-2m = ["esp-hal/opsram-2m"]
|
opsram-2m = ["esp-hal/opsram-2m"]
|
||||||
|
|||||||
@ -40,7 +40,7 @@ To demonstrated, in `src/bin/embassy_hello_world.rs` you will see the following:
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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.
|
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.
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
//! concurrently.
|
//! concurrently.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -17,9 +17,19 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
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]
|
#[embassy_executor::task]
|
||||||
async fn run() {
|
async fn run() {
|
||||||
loop {
|
loop {
|
||||||
@ -30,13 +40,18 @@ async fn run() {
|
|||||||
|
|
||||||
#[main]
|
#[main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
|
esp_println::logger::init_logger_from_env();
|
||||||
|
|
||||||
esp_println::println!("Init!");
|
esp_println::println!("Init!");
|
||||||
let peripherals = Peripherals::take();
|
let peripherals = Peripherals::take();
|
||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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();
|
spawner.spawn(run()).ok();
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
//! LIS3DH to get accelerometer data.
|
//! LIS3DH to get accelerometer data.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -26,18 +26,31 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use lis3dh_async::{Lis3dh, Range, SlaveAddr};
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let peripherals = Peripherals::take();
|
let peripherals = Peripherals::take();
|
||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -27,17 +27,30 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let peripherals = Peripherals::take();
|
let peripherals = Peripherals::take();
|
||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
//! You can also inspect the MCLK, BCLK and WS with a logic analyzer.
|
//! You can also inspect the MCLK, BCLK and WS with a logic analyzer.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -28,10 +28,20 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
println!("Init!");
|
println!("Init!");
|
||||||
@ -39,8 +49,11 @@ async fn main(_spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
//! | XSMT | +3V3 |
|
//! | XSMT | +3V3 |
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -43,7 +43,7 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
@ -55,6 +55,16 @@ const SINE: [i16; 64] = [
|
|||||||
-28897, -27244, -25329, -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
|
-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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
println!("Init!");
|
println!("Init!");
|
||||||
@ -62,8 +72,11 @@ async fn main(_spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
//! signal set by the task running on the other core.
|
//! signal set by the task running on the other core.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32s3
|
//% CHIPS: esp32 esp32s3
|
||||||
//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers
|
//% FEATURES: embassy embassy-generic-timers
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -23,7 +23,7 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_hal_embassy::Executor;
|
use esp_hal_embassy::Executor;
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
@ -31,6 +31,16 @@ use static_cell::StaticCell;
|
|||||||
|
|
||||||
static mut APP_CORE_STACK: Stack<8192> = Stack::new();
|
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
|
/// Waits for a message that contains a duration, then flashes a led for that
|
||||||
/// duration of time.
|
/// duration of time.
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
@ -58,8 +68,12 @@ async fn main(_spawner: Spawner) {
|
|||||||
|
|
||||||
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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);
|
let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
//! signal set by the task running on the other core.
|
//! signal set by the task running on the other core.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32s3
|
//% CHIPS: esp32 esp32s3
|
||||||
//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers
|
//% FEATURES: embassy embassy-generic-timers
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -23,7 +23,7 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_hal_embassy::InterruptExecutor;
|
use esp_hal_embassy::InterruptExecutor;
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
@ -31,6 +31,16 @@ use static_cell::StaticCell;
|
|||||||
|
|
||||||
static mut APP_CORE_STACK: Stack<8192> = Stack::new();
|
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
|
/// Waits for a message that contains a duration, then flashes a led for that
|
||||||
/// duration of time.
|
/// duration of time.
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
@ -77,8 +87,12 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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);
|
let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
// The interrupt-executor is created in `main` and is used to spawn `high_prio`.
|
// The interrupt-executor is created in `main` and is used to spawn `high_prio`.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -29,12 +29,22 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{/*systimer::SystemTimer,*/ timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_hal_embassy::InterruptExecutor;
|
use esp_hal_embassy::InterruptExecutor;
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use static_cell::StaticCell;
|
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.
|
/// Periodically print something.
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn high_prio() {
|
async fn high_prio() {
|
||||||
@ -78,8 +88,21 @@ async fn main(low_prio_spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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();
|
static EXECUTOR: StaticCell<InterruptExecutor<2>> = StaticCell::new();
|
||||||
let executor = InterruptExecutor::new(system.software_interrupt_control.software_interrupt2);
|
let executor = InterruptExecutor::new(system.software_interrupt_control.software_interrupt2);
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
//! Uses GPIO 1, 2, 3 and 4 as the data pins.
|
//! Uses GPIO 1, 2, 3 and 4 as the data pins.
|
||||||
|
|
||||||
//% CHIPS: esp32c6 esp32h2
|
//% CHIPS: esp32c6 esp32h2
|
||||||
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
|
//% FEATURES: async embassy embassy-generic-timers
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -21,10 +21,20 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{systimer::SystemTimer, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
esp_println::println!("Init!");
|
esp_println::println!("Init!");
|
||||||
@ -32,8 +42,10 @@ async fn main(_spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let systimer = SystemTimer::new(peripherals.SYSTIMER);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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 io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
//! You can use a logic analyzer to see how the pins are used.
|
//! You can use a logic analyzer to see how the pins are used.
|
||||||
|
|
||||||
//% CHIPS: esp32c6 esp32h2
|
//% CHIPS: esp32c6 esp32h2
|
||||||
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
|
//% FEATURES: async embassy embassy-generic-timers
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -32,10 +32,20 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{systimer::SystemTimer, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
esp_println::println!("Init!");
|
esp_println::println!("Init!");
|
||||||
@ -43,12 +53,14 @@ async fn main(_spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let systimer = SystemTimer::new(peripherals.SYSTIMER);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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 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 = Dma::new(peripherals.DMA);
|
||||||
let dma_channel = dma.channel0;
|
let dma_channel = dma.channel0;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
//! Connect GPIO5 to GPIO4
|
//! Connect GPIO5 to GPIO4
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -17,6 +17,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rmt::{asynch::RxChannelAsync, PulseCode, Rmt, RxChannelConfig, RxChannelCreatorAsync},
|
rmt::{asynch::RxChannelAsync, PulseCode, Rmt, RxChannelConfig, RxChannelCreatorAsync},
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_println::{print, println};
|
use esp_println::{print, println};
|
||||||
|
|
||||||
@ -25,6 +26,16 @@ const WIDTH: usize = 80;
|
|||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
compile_error!("Run this example in release mode");
|
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]
|
#[embassy_executor::task]
|
||||||
async fn signal_task(mut pin: Output<'static, Gpio5>) {
|
async fn signal_task(mut pin: Output<'static, Gpio5>) {
|
||||||
loop {
|
loop {
|
||||||
@ -43,8 +54,11 @@ async fn main(spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timer_group0 = esp_hal::timer::timg::TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timer_group0);
|
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);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
//! Connect a logic analyzer to GPIO4 to see the generated pulses.
|
//! Connect a logic analyzer to GPIO4 to see the generated pulses.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -18,10 +18,20 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rmt::{asynch::TxChannelAsync, PulseCode, Rmt, TxChannelConfig, TxChannelCreatorAsync},
|
rmt::{asynch::TxChannelAsync, PulseCode, Rmt, TxChannelConfig, TxChannelCreatorAsync},
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
println!("Init!");
|
println!("Init!");
|
||||||
@ -29,8 +39,11 @@ async fn main(_spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_executor::Spawner;
|
||||||
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
|
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
|
||||||
@ -18,7 +18,7 @@ use esp_hal::{
|
|||||||
peripherals::{Peripherals, UART0},
|
peripherals::{Peripherals, UART0},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
uart::{
|
uart::{
|
||||||
config::{AtCmdConfig, Config},
|
config::{AtCmdConfig, Config},
|
||||||
Uart,
|
Uart,
|
||||||
@ -34,6 +34,16 @@ const READ_BUF_SIZE: usize = 64;
|
|||||||
// EOT (CTRL-D)
|
// EOT (CTRL-D)
|
||||||
const AT_CMD: u8 = 0x04;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn writer(
|
async fn writer(
|
||||||
mut tx: UartTx<'static, UART0, Async>,
|
mut tx: UartTx<'static, UART0, Async>,
|
||||||
@ -85,8 +95,11 @@ async fn main(spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
//! This is an example of running the embassy executor with SPI.
|
//! This is an example of running the embassy executor with SPI.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -35,9 +35,19 @@ use esp_hal::{
|
|||||||
SpiMode,
|
SpiMode,
|
||||||
},
|
},
|
||||||
system::SystemControl,
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
esp_println::println!("Init!");
|
esp_println::println!("Init!");
|
||||||
@ -45,8 +55,12 @@ async fn main(_spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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 io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
let sclk = io.pins.gpio0;
|
let sclk = io.pins.gpio0;
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
//! with `IS_SENDER` set to `true`.
|
//! with `IS_SENDER` set to `true`.
|
||||||
|
|
||||||
//% CHIPS: esp32c3 esp32c6 esp32s2 esp32s3
|
//% CHIPS: esp32c3 esp32c6 esp32s2 esp32s3
|
||||||
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
|
//% FEATURES: async embassy embassy-generic-timers
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -27,7 +27,7 @@ use esp_hal::{
|
|||||||
peripherals::{self, Peripherals, TWAI0},
|
peripherals::{self, Peripherals, TWAI0},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
twai::{self, EspTwaiFrame, TwaiRx, TwaiTx},
|
twai::{self, EspTwaiFrame, TwaiRx, TwaiTx},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
@ -35,6 +35,16 @@ use static_cell::StaticCell;
|
|||||||
|
|
||||||
type TwaiOutbox = Channel<NoopRawMutex, EspTwaiFrame, 16>;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn receiver(
|
async fn receiver(
|
||||||
mut rx: TwaiRx<'static, TWAI0, esp_hal::Async>,
|
mut rx: TwaiRx<'static, TWAI0, esp_hal::Async>,
|
||||||
@ -85,8 +95,12 @@ async fn main(spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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 io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
//! This example should be built in release mode.
|
//! This example should be built in release mode.
|
||||||
|
|
||||||
//% CHIPS: esp32s2 esp32s3
|
//% CHIPS: esp32s2 esp32s3
|
||||||
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
|
//% FEATURES: async embassy embassy-generic-timers
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -26,9 +26,19 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) -> () {
|
async fn main(_spawner: Spawner) -> () {
|
||||||
esp_println::println!("Init!");
|
esp_println::println!("Init!");
|
||||||
@ -36,7 +46,15 @@ async fn main(_spawner: Spawner) -> () {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
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 io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
|
|
||||||
let usb = Usb::new(peripherals.USB0, io.pins.gpio20, io.pins.gpio19);
|
let usb = Usb::new(peripherals.USB0, io.pins.gpio20, io.pins.gpio19);
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
//! Most dev-kits use a USB-UART-bridge - in that case you won't see any output.
|
//! Most dev-kits use a USB-UART-bridge - in that case you won't see any output.
|
||||||
|
|
||||||
//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s3
|
//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s3
|
||||||
//% FEATURES: async embassy embassy-time-timg0 embassy-generic-timers
|
//% FEATURES: async embassy embassy-generic-timers
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -16,7 +16,7 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
|
||||||
usb_serial_jtag::{UsbSerialJtag, UsbSerialJtagRx, UsbSerialJtagTx},
|
usb_serial_jtag::{UsbSerialJtag, UsbSerialJtagRx, UsbSerialJtagTx},
|
||||||
Async,
|
Async,
|
||||||
};
|
};
|
||||||
@ -24,6 +24,16 @@ use static_cell::StaticCell;
|
|||||||
|
|
||||||
const MAX_BUFFER_SIZE: usize = 512;
|
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]
|
#[embassy_executor::task]
|
||||||
async fn writer(
|
async fn writer(
|
||||||
mut tx: UsbSerialJtagTx<'static, Async>,
|
mut tx: UsbSerialJtagTx<'static, Async>,
|
||||||
@ -70,7 +80,14 @@ async fn main(spawner: Spawner) -> () {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
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();
|
let (tx, rx) = UsbSerialJtag::new_async(peripherals.USB_DEVICE).split();
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
//! This is an example of asynchronously `Wait`ing for a pin state to change.
|
//! This is an example of asynchronously `Wait`ing for a pin state to change.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
|
//% 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_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
@ -17,9 +17,19 @@ use esp_hal::{
|
|||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
system::SystemControl,
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
esp_println::println!("Init!");
|
esp_println::println!("Init!");
|
||||||
@ -27,8 +37,14 @@ async fn main(_spawner: Spawner) {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
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 io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
#[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))]
|
#[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))]
|
||||||
|
|||||||
@ -21,6 +21,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::PeriodicTimer,
|
||||||
};
|
};
|
||||||
use esp_println::{print, println};
|
use esp_println::{print, println};
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -46,10 +47,12 @@ fn main() -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
|
|||||||
@ -22,6 +22,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::PeriodicTimer,
|
||||||
};
|
};
|
||||||
use esp_println::{print, println};
|
use esp_println::{print, println};
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -54,10 +55,12 @@ fn main() -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
|
|||||||
@ -22,6 +22,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::PeriodicTimer,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -66,10 +67,12 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let server_address: Ipv4Address = HOST_IP.parse().expect("Invalid HOST_IP address");
|
let server_address: Ipv4Address = HOST_IP.parse().expect("Invalid HOST_IP address");
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
|
|||||||
@ -30,6 +30,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::PeriodicTimer,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_wifi::{ble::controller::BleConnector, initialize, EspWifiInitFor};
|
use esp_wifi::{ble::controller::BleConnector, initialize, EspWifiInitFor};
|
||||||
@ -43,10 +44,12 @@ fn main() -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Ble,
|
EspWifiInitFor::Ble,
|
||||||
timer,
|
timer,
|
||||||
|
|||||||
@ -32,6 +32,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::PeriodicTimer,
|
||||||
};
|
};
|
||||||
use esp_println::{print, println};
|
use esp_println::{print, println};
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -59,10 +60,12 @@ fn main() -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::WifiBle,
|
EspWifiInitFor::WifiBle,
|
||||||
timer,
|
timer,
|
||||||
|
|||||||
@ -19,6 +19,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::PeriodicTimer,
|
||||||
};
|
};
|
||||||
use esp_println::{print, println};
|
use esp_println::{print, println};
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -52,10 +53,12 @@ fn main() -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Because of the huge task-arena size configured this won't work on ESP32-S2
|
//! 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
|
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
@ -33,7 +33,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
|
||||||
};
|
};
|
||||||
use esp_println::{print, println};
|
use esp_println::{print, println};
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -50,6 +50,7 @@ use esp_wifi::{
|
|||||||
EspWifiInitFor,
|
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 {
|
macro_rules! mk_static {
|
||||||
($t:ty,$val:expr) => {{
|
($t:ty,$val:expr) => {{
|
||||||
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
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 system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
@ -85,8 +88,29 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let (wifi_interface, controller) =
|
let (wifi_interface, controller) =
|
||||||
esp_wifi::wifi::new_with_mode(&init, wifi, WifiApDevice).unwrap();
|
esp_wifi::wifi::new_with_mode(&init, wifi, WifiApDevice).unwrap();
|
||||||
|
|
||||||
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
#[cfg(feature = "esp32")]
|
||||||
esp_hal_embassy::init(&clocks, timer_group0);
|
{
|
||||||
|
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 {
|
let config = Config::ipv4_static(StaticConfigV4 {
|
||||||
address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 2, 1), 24),
|
address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 2, 1), 24),
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Because of the huge task-arena size configured this won't work on ESP32-S2
|
//! 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
|
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
@ -36,7 +36,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
|
||||||
};
|
};
|
||||||
use esp_println::{print, println};
|
use esp_println::{print, println};
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -58,6 +58,7 @@ use esp_wifi::{
|
|||||||
const SSID: &str = env!("SSID");
|
const SSID: &str = env!("SSID");
|
||||||
const PASSWORD: &str = env!("PASSWORD");
|
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 {
|
macro_rules! mk_static {
|
||||||
($t:ty,$val:expr) => {{
|
($t:ty,$val:expr) => {{
|
||||||
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
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 system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
@ -93,8 +96,29 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let (wifi_ap_interface, wifi_sta_interface, mut controller) =
|
let (wifi_ap_interface, wifi_sta_interface, mut controller) =
|
||||||
esp_wifi::wifi::new_ap_sta(&init, wifi).unwrap();
|
esp_wifi::wifi::new_ap_sta(&init, wifi).unwrap();
|
||||||
|
|
||||||
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
#[cfg(feature = "esp32")]
|
||||||
esp_hal_embassy::init(&clocks, timer_group0);
|
{
|
||||||
|
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 {
|
let ap_config = Config::ipv4_static(StaticConfigV4 {
|
||||||
address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 2, 1), 24),
|
address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 2, 1), 24),
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
//! Because of the huge task-arena size configured this won't work on ESP32-S2 and ESP32-C2
|
//! 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
|
//% CHIPS: esp32 esp32s3 esp32c3 esp32c6
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
@ -27,7 +27,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -44,6 +44,7 @@ use esp_wifi::{
|
|||||||
EspWifiInitFor,
|
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 {
|
macro_rules! mk_static {
|
||||||
($t:ty,$val:expr) => {{
|
($t:ty,$val:expr) => {{
|
||||||
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
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");
|
let server_address: Ipv4Address = HOST_IP.parse().expect("Invalid HOST_IP address");
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
@ -97,8 +100,29 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let (wifi_interface, controller) =
|
let (wifi_interface, controller) =
|
||||||
esp_wifi::wifi::new_with_mode(&init, wifi, WifiStaDevice).unwrap();
|
esp_wifi::wifi::new_with_mode(&init, wifi, WifiStaDevice).unwrap();
|
||||||
|
|
||||||
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
#[cfg(feature = "esp32")]
|
||||||
esp_hal_embassy::init(&clocks, timer_group0);
|
{
|
||||||
|
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());
|
let config = Config::dhcpv4(Default::default());
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
//! - offers one service with three characteristics (one is read/write, one is write only, one is read/write/notify)
|
//! - 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
|
//! - 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
|
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6 esp32h2
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
@ -33,11 +33,21 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_wifi::{ble::controller::asynch::BleConnector, initialize, EspWifiInitFor};
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
esp_println::logger::init_logger_from_env();
|
esp_println::logger::init_logger_from_env();
|
||||||
@ -47,10 +57,12 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Ble,
|
EspWifiInitFor::Ble,
|
||||||
timer,
|
timer,
|
||||||
@ -71,8 +83,29 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
))]
|
))]
|
||||||
let button = Input::new(io.pins.gpio9, Pull::Down);
|
let button = Input::new(io.pins.gpio9, Pull::Down);
|
||||||
|
|
||||||
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
#[cfg(feature = "esp32")]
|
||||||
esp_hal_embassy::init(&clocks, timer_group0);
|
{
|
||||||
|
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;
|
let mut bluetooth = peripherals.BT;
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Because of the huge task-arena size configured this won't work on ESP32-S2
|
//! 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
|
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
@ -23,7 +23,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -40,6 +40,7 @@ use esp_wifi::{
|
|||||||
EspWifiInitFor,
|
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 {
|
macro_rules! mk_static {
|
||||||
($t:ty,$val:expr) => {{
|
($t:ty,$val:expr) => {{
|
||||||
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
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 system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
@ -78,8 +81,29 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let (wifi_interface, controller) =
|
let (wifi_interface, controller) =
|
||||||
esp_wifi::wifi::new_with_mode(&init, wifi, WifiStaDevice).unwrap();
|
esp_wifi::wifi::new_with_mode(&init, wifi, WifiStaDevice).unwrap();
|
||||||
|
|
||||||
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
#[cfg(feature = "esp32")]
|
||||||
esp_hal_embassy::init(&clocks, timer_group0);
|
{
|
||||||
|
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());
|
let config = Config::dhcpv4(Default::default());
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Because of the huge task-arena size configured this won't work on ESP32-S2
|
//! 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
|
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
@ -20,7 +20,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -29,6 +29,16 @@ use esp_wifi::{
|
|||||||
EspWifiInitFor,
|
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]
|
#[main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
esp_println::logger::init_logger_from_env();
|
esp_println::logger::init_logger_from_env();
|
||||||
@ -38,10 +48,12 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
@ -55,8 +67,29 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
let mut esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap();
|
let mut esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap();
|
||||||
println!("esp-now version {}", esp_now.get_version().unwrap());
|
println!("esp-now version {}", esp_now.get_version().unwrap());
|
||||||
|
|
||||||
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
#[cfg(feature = "esp32")]
|
||||||
esp_hal_embassy::init(&clocks, timer_group0);
|
{
|
||||||
|
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));
|
let mut ticker = Ticker::every(Duration::from_secs(5));
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Because of the huge task-arena size configured this won't work on ESP32-S2
|
//! 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
|
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
@ -20,7 +20,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
timer::timg::TimerGroup,
|
timer::{ErasedTimer, OneShotTimer, PeriodicTimer},
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -29,6 +29,7 @@ use esp_wifi::{
|
|||||||
EspWifiInitFor,
|
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 {
|
macro_rules! mk_static {
|
||||||
($t:ty,$val:expr) => {{
|
($t:ty,$val:expr) => {{
|
||||||
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
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 system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
@ -64,8 +67,29 @@ async fn main(spawner: Spawner) -> ! {
|
|||||||
let esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap();
|
let esp_now = esp_wifi::esp_now::EspNow::new(&init, wifi).unwrap();
|
||||||
println!("esp-now version {}", esp_now.get_version().unwrap());
|
println!("esp-now version {}", esp_now.get_version().unwrap());
|
||||||
|
|
||||||
let timer_group0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
#[cfg(feature = "esp32")]
|
||||||
esp_hal_embassy::init(&clocks, timer_group0);
|
{
|
||||||
|
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, sender, receiver) = esp_now.split();
|
||||||
let manager = mk_static!(EspNowManager<'static>, manager);
|
let manager = mk_static!(EspNowManager<'static>, manager);
|
||||||
|
|||||||
@ -15,6 +15,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::PeriodicTimer,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -33,10 +34,12 @@ fn main() -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
|
|||||||
@ -20,6 +20,7 @@ use esp_hal::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
rng::Rng,
|
rng::Rng,
|
||||||
system::SystemControl,
|
system::SystemControl,
|
||||||
|
timer::PeriodicTimer,
|
||||||
};
|
};
|
||||||
use esp_println::{print, println};
|
use esp_println::{print, println};
|
||||||
use esp_wifi::{
|
use esp_wifi::{
|
||||||
@ -52,10 +53,12 @@ fn main() -> ! {
|
|||||||
let system = SystemControl::new(peripherals.SYSTEM);
|
let system = SystemControl::new(peripherals.SYSTEM);
|
||||||
let clocks = ClockControl::max(system.clock_control).freeze();
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
||||||
|
|
||||||
#[cfg(target_arch = "xtensa")]
|
let timer = PeriodicTimer::new(
|
||||||
let timer = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1, &clocks, None).timer0;
|
esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks, None)
|
||||||
#[cfg(target_arch = "riscv32")]
|
.timer0
|
||||||
let timer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).alarm0;
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let init = initialize(
|
let init = initialize(
|
||||||
EspWifiInitFor::Wifi,
|
EspWifiInitFor::Wifi,
|
||||||
timer,
|
timer,
|
||||||
|
|||||||
@ -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 = { path = "../esp-hal", features = ["defmt", "embedded-hal", "embedded-hal-02"], optional = true }
|
||||||
esp-hal-embassy = { path = "../esp-hal-embassy", optional = true }
|
esp-hal-embassy = { path = "../esp-hal-embassy", optional = true }
|
||||||
portable-atomic = "1.6.0"
|
portable-atomic = "1.6.0"
|
||||||
|
static_cell = { version = "2.0.0", features = ["nightly"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
crypto-bigint = { version = "0.5.5", default-features = false }
|
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" }
|
semihosting = { git = "https://github.com/taiki-e/semihosting", tag = "v0.1.10" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["async", "embassy", "embassy-time-timg0"]
|
default = ["async", "embassy"]
|
||||||
|
|
||||||
# Device support (required!):
|
# Device support (required!):
|
||||||
esp32 = [
|
esp32 = [
|
||||||
@ -154,9 +155,6 @@ embassy = [
|
|||||||
"embedded-test/external-executor",
|
"embedded-test/external-executor",
|
||||||
"dep:esp-hal-embassy",
|
"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
|
# https://doc.rust-lang.org/cargo/reference/profiles.html#test
|
||||||
# Test and bench profiles inherit from dev and release respectively.
|
# Test and bench profiles inherit from dev and release respectively.
|
||||||
|
|||||||
@ -21,9 +21,18 @@ use esp_hal::{
|
|||||||
macros::handler,
|
macros::handler,
|
||||||
peripherals::Peripherals,
|
peripherals::Peripherals,
|
||||||
system::SystemControl,
|
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 COUNTER: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
|
||||||
static INPUT_PIN: Mutex<RefCell<Option<Input<'static, Gpio2>>>> = Mutex::new(RefCell::new(None));
|
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 delay = Delay::new(&clocks);
|
||||||
|
|
||||||
let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks);
|
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks, None);
|
||||||
esp_hal_embassy::init(&clocks, timg0);
|
esp_hal_embassy::init(
|
||||||
|
&clocks,
|
||||||
|
mk_static!(
|
||||||
|
[OneShotTimer<ErasedTimer>; 1],
|
||||||
|
[OneShotTimer::new(timg0.timer0.into())]
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
Context {
|
Context {
|
||||||
io2: Input::new(io.pins.gpio2, Pull::Down),
|
io2: Input::new(io.pins.gpio2, Pull::Down),
|
||||||
|
|||||||
@ -487,18 +487,14 @@ fn lint_packages(workspace: &Path, _args: LintPackagesArgs) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Package::EspHalEmbassy => {
|
Package::EspHalEmbassy => {
|
||||||
// We need to specify a time driver, so we will check all
|
lint_package(
|
||||||
// options here (as the modules themselves are feature-gated):
|
&path,
|
||||||
for feature in ["time-systimer-16mhz", "time-timg0"] {
|
&[
|
||||||
lint_package(
|
"-Zbuild-std=core",
|
||||||
&path,
|
"--target=riscv32imac-unknown-none-elf",
|
||||||
&[
|
"--features=esp32c6",
|
||||||
"-Zbuild-std=core",
|
],
|
||||||
"--target=riscv32imac-unknown-none-elf",
|
)?;
|
||||||
&format!("--features=esp32c6,{feature}"),
|
|
||||||
],
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Package::EspHalProcmacros | Package::EspRiscvRt => lint_package(
|
Package::EspHalProcmacros | Package::EspRiscvRt => lint_package(
|
||||||
@ -538,7 +534,7 @@ fn lint_packages(workspace: &Path, _args: LintPackagesArgs) -> Result<()> {
|
|||||||
&[
|
&[
|
||||||
"-Zbuild-std=core",
|
"-Zbuild-std=core",
|
||||||
"--target=riscv32imc-unknown-none-elf",
|
"--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",
|
||||||
],
|
],
|
||||||
)?,
|
)?,
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user