diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index d8ac4ac0..d10752b3 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -53,6 +53,7 @@ time-tick-16mhz = ["time"] [dependencies] defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } +rtos-trace = { version = "0.1.2", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8", optional = true} diff --git a/embassy-executor/src/executor/raw/mod.rs b/embassy-executor/src/executor/raw/mod.rs index fb4cc628..c943ecd8 100644 --- a/embassy-executor/src/executor/raw/mod.rs +++ b/embassy-executor/src/executor/raw/mod.rs @@ -22,6 +22,8 @@ use core::{mem, ptr}; use atomic_polyfill::{AtomicU32, Ordering}; use critical_section::CriticalSection; +#[cfg(feature = "rtos-trace")] +use rtos_trace::trace; use self::run_queue::{RunQueue, RunQueueItem}; use self::util::UninitCell; @@ -306,6 +308,9 @@ impl Executor { /// - `task` must NOT be already enqueued (in this executor or another one). #[inline(always)] unsafe fn enqueue(&self, cs: CriticalSection, task: NonNull) { + #[cfg(feature = "rtos-trace")] + trace::task_ready_begin(task.as_ptr() as u32); + if self.run_queue.enqueue(cs, task) { (self.signal_fn)(self.signal_ctx) } @@ -323,6 +328,9 @@ impl Executor { pub(super) unsafe fn spawn(&'static self, task: NonNull) { task.as_ref().executor.set(self); + #[cfg(feature = "rtos-trace")] + trace::task_new(task.as_ptr() as u32); + critical_section::with(|cs| { self.enqueue(cs, task); }) @@ -365,9 +373,15 @@ impl Executor { return; } + #[cfg(feature = "rtos-trace")] + trace::task_exec_begin(p.as_ptr() as u32); + // Run the task task.poll_fn.read()(p as _); + #[cfg(feature = "rtos-trace")] + trace::task_exec_end(); + // Enqueue or update into timer_queue #[cfg(feature = "time")] self.timer_queue.update(p); @@ -381,6 +395,9 @@ impl Executor { let next_expiration = self.timer_queue.next_expiration(); driver::set_alarm(self.alarm, next_expiration.as_ticks()); } + + #[cfg(feature = "rtos-trace")] + trace::system_idle(); } /// Get a spawner that spawns tasks in this executor. @@ -425,3 +442,21 @@ pub(crate) unsafe fn register_timer(at: Instant, waker: &core::task::Waker) { let expires_at = task.expires_at.get(); task.expires_at.set(expires_at.min(at)); } + +#[cfg(feature = "rtos-trace")] +impl rtos_trace::RtosTraceOSCallbacks for Executor { + fn task_list() { + // We don't know what tasks exist, so we can't send them. + } + #[cfg(feature = "time")] + fn time() -> u64 { + Instant::now().as_micros() + } + #[cfg(not(feature = "time"))] + fn time() -> u64 { + 0 + } +} + +#[cfg(feature = "rtos-trace")] +rtos_trace::global_os_callbacks!{Executor} diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index 69e4aeb4..dd99f9e5 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs @@ -19,4 +19,25 @@ pub use embassy_macros::{main, task}; /// Implementation details for embassy macros. DO NOT USE. pub mod export { pub use atomic_polyfill as atomic; + + #[cfg(feature = "rtos-trace")] + pub use rtos_trace::trace; + + /// Expands the given block of code when `embassy-executor` is compiled with + /// the `rtos-trace` feature. + #[doc(hidden)] + #[macro_export] + #[cfg(feature = "rtos-trace")] + macro_rules! rtos_trace { + ($($tt:tt)*) => { $($tt)* }; + } + + /// Does not expand the given block of code when `embassy-executor` is + /// compiled without the `rtos-trace` feature. + #[doc(hidden)] + #[macro_export] + #[cfg(not(feature = "rtos-trace"))] + macro_rules! rtos_trace { + ($($tt:tt)*) => {}; + } } diff --git a/embassy-macros/src/macros/cortex_m_interrupt_take.rs b/embassy-macros/src/macros/cortex_m_interrupt_take.rs index 133eb5c2..5431704d 100644 --- a/embassy-macros/src/macros/cortex_m_interrupt_take.rs +++ b/embassy-macros/src/macros/cortex_m_interrupt_take.rs @@ -19,7 +19,13 @@ pub fn run(name: syn::Ident) -> Result { let func = HANDLER.func.load(::embassy_executor::export::atomic::Ordering::Relaxed); let ctx = HANDLER.ctx.load(::embassy_executor::export::atomic::Ordering::Relaxed); let func: fn(*mut ()) = ::core::mem::transmute(func); - func(ctx) + ::embassy_executor::rtos_trace! { + ::embassy_executor::export::trace::isr_enter(); + } + func(ctx); + ::embassy_executor::rtos_trace! { + ::embassy_executor::export::trace::isr_exit(); + } } static TAKEN: ::embassy_executor::export::atomic::AtomicBool = ::embassy_executor::export::atomic::AtomicBool::new(false);