mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-26 20:00:32 +00:00
Make timekeeping the driver's job (#4047)
This commit is contained in:
parent
a5f929a663
commit
a84d3cc89f
@ -270,10 +270,6 @@ impl esp_radio_preempt_driver::Scheduler for Scheduler {
|
||||
timer::initialized()
|
||||
}
|
||||
|
||||
fn usleep(&self, us: u32) {
|
||||
usleep(us)
|
||||
}
|
||||
|
||||
fn enable(&self) {
|
||||
// allocate the main task
|
||||
task::allocate_main_task();
|
||||
@ -336,4 +332,15 @@ impl esp_radio_preempt_driver::Scheduler for Scheduler {
|
||||
unwrap!(task.thread_semaphore)
|
||||
})
|
||||
}
|
||||
|
||||
fn usleep(&self, us: u32) {
|
||||
usleep(us)
|
||||
}
|
||||
|
||||
fn now(&self) -> u64 {
|
||||
// FIXME: this function needs to return the timestamp of the scheduler's timer
|
||||
esp_hal::time::Instant::now()
|
||||
.duration_since_epoch()
|
||||
.as_micros()
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ use crate::semaphore::SemaphorePtr;
|
||||
|
||||
unsafe extern "Rust" {
|
||||
fn esp_preempt_initialized() -> bool;
|
||||
fn esp_preempt_usleep(us: u32);
|
||||
fn esp_preempt_enable();
|
||||
fn esp_preempt_disable();
|
||||
fn esp_preempt_yield_task();
|
||||
@ -50,6 +49,9 @@ unsafe extern "Rust" {
|
||||
) -> *mut c_void;
|
||||
fn esp_preempt_schedule_task_deletion(task_handle: *mut c_void);
|
||||
fn esp_preempt_current_task_thread_semaphore() -> SemaphorePtr;
|
||||
|
||||
fn esp_preempt_usleep(us: u32);
|
||||
fn esp_preempt_now() -> u64;
|
||||
}
|
||||
|
||||
/// Set the Scheduler implementation.
|
||||
@ -66,12 +68,6 @@ macro_rules! scheduler_impl {
|
||||
<$t as $crate::Scheduler>::initialized(&$name)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
#[inline]
|
||||
fn esp_preempt_usleep(us: u32) {
|
||||
<$t as $crate::Scheduler>::usleep(&$name, us)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
#[inline]
|
||||
fn esp_preempt_enable() {
|
||||
@ -117,6 +113,18 @@ macro_rules! scheduler_impl {
|
||||
fn esp_preempt_current_task_thread_semaphore() -> SemaphorePtr {
|
||||
<$t as $crate::Scheduler>::current_task_thread_semaphore(&$name)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
#[inline]
|
||||
fn esp_preempt_usleep(us: u32) {
|
||||
<$t as $crate::Scheduler>::usleep(&$name, us)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
#[inline]
|
||||
fn esp_preempt_now() -> u64 {
|
||||
<$t as $crate::Scheduler>::now(&$name)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -129,10 +137,6 @@ pub trait Scheduler: Send + Sync + 'static {
|
||||
/// up.
|
||||
fn initialized(&self) -> bool;
|
||||
|
||||
/// This function is called by `esp_radio::init` to put the current task to sleep for the
|
||||
/// specified number of microseconds.
|
||||
fn usleep(&self, us: u32);
|
||||
|
||||
/// This function is called by `esp-radio` to start the task scheduler.
|
||||
fn enable(&self);
|
||||
|
||||
@ -166,6 +170,16 @@ pub trait Scheduler: Send + Sync + 'static {
|
||||
/// usize-sized memory location, which will be used to store a pointer
|
||||
/// to a semaphore for this thread.
|
||||
fn current_task_thread_semaphore(&self) -> SemaphorePtr;
|
||||
|
||||
/// This function is called by a task to sleep for the specified number of microseconds.
|
||||
fn usleep(&self, us: u32);
|
||||
|
||||
/// Returns the current timestamp in microseconds.
|
||||
///
|
||||
/// The underlying timer is expected not to overflow during the lifetime of the program.
|
||||
///
|
||||
/// The clock that generates this timestamp must be the same one used to trigger timer events.
|
||||
fn now(&self) -> u64;
|
||||
}
|
||||
|
||||
// API used (mostly) by esp-radio
|
||||
@ -176,12 +190,6 @@ pub fn initialized() -> bool {
|
||||
unsafe { esp_preempt_initialized() }
|
||||
}
|
||||
|
||||
/// Puts the current task to sleep for the specified number of microseconds.
|
||||
#[inline]
|
||||
pub fn usleep(us: u32) {
|
||||
unsafe { esp_preempt_usleep(us) }
|
||||
}
|
||||
|
||||
/// Starts the task scheduler.
|
||||
#[inline]
|
||||
pub fn enable() {
|
||||
@ -239,3 +247,15 @@ pub unsafe fn schedule_task_deletion(task_handle: *mut c_void) {
|
||||
pub fn current_task_thread_semaphore() -> SemaphorePtr {
|
||||
unsafe { esp_preempt_current_task_thread_semaphore() }
|
||||
}
|
||||
|
||||
/// Puts the current task to sleep for the specified number of microseconds.
|
||||
#[inline]
|
||||
pub fn usleep(us: u32) {
|
||||
unsafe { esp_preempt_usleep(us) }
|
||||
}
|
||||
|
||||
/// Returns the current timestamp, in microseconds.
|
||||
#[inline]
|
||||
pub fn now() -> u64 {
|
||||
unsafe { esp_preempt_now() }
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ pub unsafe extern "C" fn __esp_radio_gettimeofday(tv: *mut timeval, _tz: *mut ()
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn __esp_radio_esp_timer_get_time() -> i64 {
|
||||
trace!("esp_timer_get_time");
|
||||
crate::time::ticks_to_micros(crate::time::systimer_count()) as i64
|
||||
crate::time::ticks_to_micros(crate::preempt::now()) as i64
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
|
@ -200,6 +200,6 @@ pub(crate) unsafe extern "C" fn sleep(
|
||||
/// components/newlib/time.c
|
||||
#[unsafe(no_mangle)]
|
||||
unsafe extern "C" fn usleep(us: u32) -> c_int {
|
||||
esp_radio_preempt_driver::usleep(us);
|
||||
crate::preempt::usleep(us);
|
||||
0
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use esp_radio_preempt_driver::mutex::{MutexHandle, MutexPtr};
|
||||
use esp_wifi_sys::c_types::c_void;
|
||||
|
||||
use crate::compat::OSI_FUNCS_TIME_BLOCKING;
|
||||
use crate::{
|
||||
compat::OSI_FUNCS_TIME_BLOCKING,
|
||||
preempt::mutex::{MutexHandle, MutexPtr},
|
||||
};
|
||||
|
||||
pub(crate) fn mutex_create(recursive: bool) -> *mut c_void {
|
||||
MutexHandle::new(recursive).leak().as_ptr().cast()
|
||||
|
@ -1,7 +1,9 @@
|
||||
use esp_radio_preempt_driver::queue::{QueueHandle, QueuePtr};
|
||||
use esp_wifi_sys::c_types::*;
|
||||
|
||||
use crate::compat::OSI_FUNCS_TIME_BLOCKING;
|
||||
use crate::{
|
||||
compat::OSI_FUNCS_TIME_BLOCKING,
|
||||
preempt::queue::{QueueHandle, QueuePtr},
|
||||
};
|
||||
|
||||
pub(crate) fn queue_create(queue_len: c_int, item_size: c_int) -> *mut c_void {
|
||||
trace!("queue_create len={} size={}", queue_len, item_size);
|
||||
|
@ -1,7 +1,9 @@
|
||||
use esp_radio_preempt_driver::semaphore::{SemaphoreHandle, SemaphorePtr};
|
||||
use esp_wifi_sys::c_types::c_void;
|
||||
|
||||
use crate::compat::OSI_FUNCS_TIME_BLOCKING;
|
||||
use crate::{
|
||||
compat::OSI_FUNCS_TIME_BLOCKING,
|
||||
preempt::semaphore::{SemaphoreHandle, SemaphorePtr},
|
||||
};
|
||||
|
||||
pub(crate) fn sem_create(max: u32, init: u32) -> *mut c_void {
|
||||
SemaphoreHandle::new(max, init).leak().as_ptr().cast()
|
||||
|
@ -64,9 +64,7 @@ impl TimerQueue {
|
||||
) -> Option<&mut Box<Timer>> {
|
||||
let mut current = self.head.as_mut();
|
||||
while let Some(timer) = current {
|
||||
if timer.active
|
||||
&& crate::time::time_diff(timer.started, current_timestamp) >= timer.timeout
|
||||
{
|
||||
if timer.active && current_timestamp - timer.started >= timer.timeout {
|
||||
return Some(timer);
|
||||
}
|
||||
current = timer.next.as_mut();
|
||||
@ -156,7 +154,7 @@ pub(crate) fn compat_timer_arm(ets_timer: *mut ets_timer, tmout: u32, repeat: bo
|
||||
|
||||
#[cfg(any(feature = "wifi", all(feature = "ble", npl)))]
|
||||
pub(crate) fn compat_timer_arm_us(ets_timer: *mut ets_timer, us: u32, repeat: bool) {
|
||||
let systick = crate::time::systimer_count();
|
||||
let systick = crate::preempt::now();
|
||||
let ticks = crate::time::micros_to_ticks(us as u64);
|
||||
|
||||
trace!(
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
compat::timer_compat::TIMERS,
|
||||
preempt::{task_create, yield_task},
|
||||
time::systimer_count,
|
||||
};
|
||||
|
||||
/// Initializes the `timer` task for the Wi-Fi driver.
|
||||
@ -16,7 +15,7 @@ pub(crate) fn init_tasks() {
|
||||
/// events.
|
||||
pub(crate) extern "C" fn timer_task(_param: *mut esp_wifi_sys::c_types::c_void) {
|
||||
loop {
|
||||
let current_timestamp = systimer_count();
|
||||
let current_timestamp = crate::preempt::now();
|
||||
let to_run = TIMERS.with(|timers| {
|
||||
let to_run = unsafe { timers.find_next_due(current_timestamp) }?;
|
||||
|
||||
|
@ -1,52 +1,19 @@
|
||||
// Time keeping
|
||||
//! Time conversions
|
||||
#![allow(unused)]
|
||||
pub const TICKS_PER_SECOND: u64 = 1_000_000;
|
||||
|
||||
/// Current systimer count value
|
||||
/// A tick is 1 / 1_000_000 seconds
|
||||
/// This function must not be called in a critical section. Doing so may return
|
||||
/// an incorrect value.
|
||||
pub(crate) fn systimer_count() -> u64 {
|
||||
esp_hal::time::Instant::now()
|
||||
.duration_since_epoch()
|
||||
.as_micros()
|
||||
}
|
||||
|
||||
// TODO: use an Instance type instead...
|
||||
#[cfg(target_arch = "riscv32")]
|
||||
pub(crate) fn time_diff(start: u64, end: u64) -> u64 {
|
||||
// 52-bit wrapping sub
|
||||
end.wrapping_sub(start) & 0x000f_ffff_ffff_ffff
|
||||
}
|
||||
|
||||
// TODO: use an Instance type instead...
|
||||
#[cfg(target_arch = "xtensa")]
|
||||
pub(crate) fn time_diff(start: u64, end: u64) -> u64 {
|
||||
end.wrapping_sub(start)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn micros_to_ticks(us: u64) -> u64 {
|
||||
us * (TICKS_PER_SECOND / 1_000_000)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn millis_to_ticks(ms: u64) -> u64 {
|
||||
ms * (TICKS_PER_SECOND / 1_000)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn ticks_to_micros(ticks: u64) -> u64 {
|
||||
ticks / (TICKS_PER_SECOND / 1_000_000)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn ticks_to_millis(ticks: u64) -> u64 {
|
||||
ticks / (TICKS_PER_SECOND / 1_000)
|
||||
}
|
||||
|
||||
/// Do not call this in a critical section!
|
||||
#[cfg(feature = "wifi")]
|
||||
pub(crate) fn elapsed_time_since(start: u64) -> u64 {
|
||||
let now = systimer_count();
|
||||
time_diff(start, now)
|
||||
}
|
||||
|
@ -530,10 +530,7 @@ pub unsafe extern "C" fn task_delete(task_handle: *mut c_void) {
|
||||
/// *************************************************************************
|
||||
pub unsafe extern "C" fn task_delay(tick: u32) {
|
||||
trace!("task_delay tick {}", tick);
|
||||
let start_time = crate::time::systimer_count();
|
||||
while crate::time::elapsed_time_since(start_time) < tick as u64 {
|
||||
yield_task();
|
||||
}
|
||||
crate::preempt::usleep(tick)
|
||||
}
|
||||
|
||||
/// **************************************************************************
|
||||
|
@ -12,6 +12,7 @@ esp-backtrace = { path = "../../../esp-backtrace", features = [
|
||||
] }
|
||||
esp-bootloader-esp-idf = { path = "../../../esp-bootloader-esp-idf" }
|
||||
esp-hal = { path = "../../../esp-hal", features = ["log-04", "unstable"] }
|
||||
esp-preempt = { path = "../../../esp-preempt", features = ["log-04"] }
|
||||
esp-println = { path = "../../../esp-println", features = ["log-04"] }
|
||||
esp-radio = { path = "../../../esp-radio", features = [
|
||||
"ieee802154",
|
||||
@ -23,12 +24,14 @@ esp32c6 = [
|
||||
"esp-backtrace/esp32c6",
|
||||
"esp-bootloader-esp-idf/esp32c6",
|
||||
"esp-hal/esp32c6",
|
||||
"esp-preempt/esp32c6",
|
||||
"esp-radio/esp32c6",
|
||||
]
|
||||
esp32h2 = [
|
||||
"esp-backtrace/esp32h2",
|
||||
"esp-bootloader-esp-idf/esp32h2",
|
||||
"esp-hal/esp32h2",
|
||||
"esp-preempt/esp32h2",
|
||||
"esp-radio/esp32h2",
|
||||
]
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
use esp_alloc as _;
|
||||
use esp_backtrace as _;
|
||||
use esp_hal::main;
|
||||
use esp_preempt as _;
|
||||
use esp_println::println;
|
||||
use esp_radio::ieee802154::{Config, Ieee802154};
|
||||
|
||||
|
@ -12,6 +12,7 @@ esp-backtrace = { path = "../../../esp-backtrace", features = [
|
||||
] }
|
||||
esp-bootloader-esp-idf = { path = "../../../esp-bootloader-esp-idf" }
|
||||
esp-hal = { path = "../../../esp-hal", features = ["log-04", "unstable"] }
|
||||
esp-preempt = { path = "../../../esp-preempt", features = ["log-04"] }
|
||||
esp-println = { path = "../../../esp-println", features = ["log-04"] }
|
||||
esp-radio = { path = "../../../esp-radio", features = [
|
||||
"ieee802154",
|
||||
@ -23,12 +24,14 @@ esp32c6 = [
|
||||
"esp-backtrace/esp32c6",
|
||||
"esp-bootloader-esp-idf/esp32c6",
|
||||
"esp-hal/esp32c6",
|
||||
"esp-preempt/esp32c6",
|
||||
"esp-radio/esp32c6",
|
||||
]
|
||||
esp32h2 = [
|
||||
"esp-backtrace/esp32h2",
|
||||
"esp-bootloader-esp-idf/esp32h2",
|
||||
"esp-hal/esp32h2",
|
||||
"esp-preempt/esp32h2",
|
||||
"esp-radio/esp32h2",
|
||||
]
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
use esp_alloc as _;
|
||||
use esp_backtrace as _;
|
||||
use esp_hal::main;
|
||||
use esp_preempt as _;
|
||||
use esp_println::println;
|
||||
use esp_radio::ieee802154::{Config, Ieee802154};
|
||||
|
||||
|
@ -12,6 +12,7 @@ esp-backtrace = { path = "../../../esp-backtrace", features = [
|
||||
] }
|
||||
esp-bootloader-esp-idf = { path = "../../../esp-bootloader-esp-idf" }
|
||||
esp-hal = { path = "../../../esp-hal", features = ["log-04", "unstable"] }
|
||||
esp-preempt = { path = "../../../esp-preempt", features = ["log-04"] }
|
||||
esp-println = { path = "../../../esp-println", features = ["log-04"] }
|
||||
esp-radio = { path = "../../../esp-radio", features = [
|
||||
"ieee802154",
|
||||
@ -24,12 +25,14 @@ esp32c6 = [
|
||||
"esp-backtrace/esp32c6",
|
||||
"esp-bootloader-esp-idf/esp32c6",
|
||||
"esp-hal/esp32c6",
|
||||
"esp-preempt/esp32c6",
|
||||
"esp-radio/esp32c6",
|
||||
]
|
||||
esp32h2 = [
|
||||
"esp-backtrace/esp32h2",
|
||||
"esp-bootloader-esp-idf/esp32h2",
|
||||
"esp-hal/esp32h2",
|
||||
"esp-preempt/esp32h2",
|
||||
"esp-radio/esp32h2",
|
||||
]
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
use esp_alloc as _;
|
||||
use esp_backtrace as _;
|
||||
use esp_hal::{delay::Delay, main};
|
||||
use esp_preempt as _;
|
||||
use esp_println::println;
|
||||
use esp_radio::ieee802154::{Config, Frame, Ieee802154};
|
||||
use ieee802154::mac::{
|
||||
|
@ -12,6 +12,7 @@ esp-backtrace = { path = "../../../esp-backtrace", features = [
|
||||
] }
|
||||
esp-bootloader-esp-idf = { path = "../../../esp-bootloader-esp-idf" }
|
||||
esp-hal = { path = "../../../esp-hal", features = ["log-04", "unstable"] }
|
||||
esp-preempt = { path = "../../../esp-preempt", features = ["log-04"] }
|
||||
esp-println = { path = "../../../esp-println", features = ["log-04"] }
|
||||
esp-radio = { path = "../../../esp-radio", features = [
|
||||
"ieee802154",
|
||||
@ -24,12 +25,14 @@ esp32c6 = [
|
||||
"esp-backtrace/esp32c6",
|
||||
"esp-bootloader-esp-idf/esp32c6",
|
||||
"esp-hal/esp32c6",
|
||||
"esp-preempt/esp32c6",
|
||||
"esp-radio/esp32c6",
|
||||
]
|
||||
esp32h2 = [
|
||||
"esp-backtrace/esp32h2",
|
||||
"esp-bootloader-esp-idf/esp32h2",
|
||||
"esp-hal/esp32h2",
|
||||
"esp-preempt/esp32h2",
|
||||
"esp-radio/esp32h2",
|
||||
]
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
use esp_alloc as _;
|
||||
use esp_backtrace as _;
|
||||
use esp_hal::{delay::Delay, main};
|
||||
use esp_preempt as _;
|
||||
use esp_println::println;
|
||||
use esp_radio::ieee802154::{Config, Frame, Ieee802154};
|
||||
use ieee802154::mac::{
|
||||
|
@ -13,6 +13,7 @@ esp-backtrace = { path = "../../../esp-backtrace", features = [
|
||||
] }
|
||||
esp-bootloader-esp-idf = { path = "../../../esp-bootloader-esp-idf" }
|
||||
esp-hal = { path = "../../../esp-hal", features = ["log-04", "unstable"] }
|
||||
esp-preempt = { path = "../../../esp-preempt", features = ["log-04"] }
|
||||
esp-println = { path = "../../../esp-println", features = ["log-04"] }
|
||||
esp-radio = { path = "../../../esp-radio", features = [
|
||||
"ieee802154",
|
||||
@ -25,12 +26,14 @@ esp32c6 = [
|
||||
"esp-backtrace/esp32c6",
|
||||
"esp-bootloader-esp-idf/esp32c6",
|
||||
"esp-hal/esp32c6",
|
||||
"esp-preempt/esp32c6",
|
||||
"esp-radio/esp32c6",
|
||||
]
|
||||
esp32h2 = [
|
||||
"esp-backtrace/esp32h2",
|
||||
"esp-bootloader-esp-idf/esp32h2",
|
||||
"esp-hal/esp32h2",
|
||||
"esp-preempt/esp32h2",
|
||||
"esp-radio/esp32h2",
|
||||
]
|
||||
|
||||
|
@ -14,6 +14,7 @@ use esp_hal::{
|
||||
system::software_reset,
|
||||
uart::{self, Uart},
|
||||
};
|
||||
use esp_preempt as _;
|
||||
use esp_println::println;
|
||||
use esp_radio::ieee802154::{Config, Ieee802154};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user