#![allow(static_mut_refs)] use log::*; use crate::logging::RenderbugLogger; #[derive(Debug)] struct TracedTask { id: u32, name: &'static str, priority: u32, running: bool, ready: bool } impl TracedTask { fn new(id: u32) -> Self { Self { id, name: "", priority: 0, running: false, ready: false } } } pub struct Tracer {} struct TracerState { tasks: [core::mem::MaybeUninit; 16], num_tasks: usize, } static mut TRACER_STATE: TracerState = TracerState::new(); impl TracerState { const fn new() -> Self { Self { tasks: [const { core::mem::MaybeUninit::uninit() }; 16], num_tasks: 0, } } fn get_task(&mut self, id: u32) -> &mut TracedTask { for i in 0..self.num_tasks { let info = unsafe { &mut *self.tasks[i].as_mut_ptr() }; if info.id == id { return info; } } // Otherwise, we register a new task if self.num_tasks < self.tasks.len() { self.tasks[self.num_tasks].write(TracedTask::new(id)); self.num_tasks += 1; } else { panic!("too many tasks registered"); } unsafe { &mut *self.tasks[self.num_tasks - 1].as_mut_ptr() } } } impl rtos_trace::RtosTrace for Tracer { fn start() { warn!("rtos start"); } fn stop() { warn!("rtos stop"); } fn task_new(id: u32) { let task = unsafe { TRACER_STATE.get_task(id) }; warn!("rtos new task {task:?}"); } fn task_send_info(id: u32, info: rtos_trace::TaskInfo) { let task = unsafe { TRACER_STATE.get_task(id) }; task.name = info.name; task.priority = info.priority; warn!("rtos task info for task {task:?}"); } fn task_new_stackless(id: u32, name: &'static str, priority: u32) { let task = unsafe { TRACER_STATE.get_task(id) }; task.name = name; task.priority = priority; warn!("rtos new task {task:?} {name}"); } fn task_terminate(id: u32) { let task = unsafe { TRACER_STATE.get_task(id) }; warn!("rtos terminate {task:?}") } fn task_exec_begin(id: u32) { let task = unsafe { TRACER_STATE.get_task(id) }; task.running = true; warn!("rtos exec {task:?}") } fn task_exec_end() { warn!("rtos exec end"); } fn task_ready_begin(id: u32) { let task = unsafe { TRACER_STATE.get_task(id) }; task.ready = true; warn!("rtos ready {task:?}") } fn task_ready_end(id: u32) { let task = unsafe { TRACER_STATE.get_task(id) }; task.ready = false; warn!("rtos suspend {task:?}") } fn system_idle() { warn!("rtos system idle"); } fn isr_enter() { warn!("rtos isr enter"); } fn isr_exit() { warn!("rtos isr exit"); } fn isr_exit_to_scheduler() { warn!("rtos isr exit to scheduler"); } fn name_marker(id: u32, name: &'static str) { warn!("rtos name marker {id}: {name}"); } fn marker(id: u32) { warn!("rtos marker {}", Self::name_for_marker(id)); } fn marker_begin(id: u32) { match id { //1..2 => trace!("rtos marker begin {}", Self::name_for_marker(id)), _ => { warn!("rtos marker begin {}", Self::name_for_marker(id)); RenderbugLogger::set_level(LevelFilter::Trace); } } } fn marker_end(id: u32) { match id { //1..2 => trace!("rtos marker end {}", Self::name_for_marker(id)), _ => { warn!("rtos marker end {}", Self::name_for_marker(id)); RenderbugLogger::reset_level(); }, } } } impl Tracer { const fn name_for_marker(id: u32) -> &'static str { match id { 0 => "run scheduler", 1 => "yield task", 2 => "timer tick", 3 => "process timer queue", 4 => "process embassy timer queue", _ => "unknown", } } }