Make timekeeping the driver's job (#4047)

This commit is contained in:
Dániel Buga 2025-09-05 09:31:40 +02:00 committed by GitHub
parent a5f929a663
commit a84d3cc89f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 88 additions and 74 deletions

View File

@ -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()
}
}

View File

@ -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() }
}

View File

@ -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)]

View File

@ -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
}

View File

@ -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()

View File

@ -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);

View File

@ -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()

View File

@ -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!(

View File

@ -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) }?;

View File

@ -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)
}

View File

@ -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)
}
/// **************************************************************************

View File

@ -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",
]

View File

@ -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};

View File

@ -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",
]

View File

@ -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};

View File

@ -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",
]

View File

@ -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::{

View File

@ -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",
]

View File

@ -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::{

View File

@ -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",
]

View File

@ -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};