Skip to main content

osal_rs/freertos/
thread.rs

1/***************************************************************************
2 *
3 * osal-rs
4 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 ***************************************************************************/
19
20//! Thread management and synchronization for FreeRTOS.
21//!
22//! This module provides a safe Rust interface for creating and managing FreeRTOS tasks.
23//! It supports thread creation with callbacks, priority management, and thread notifications.
24
25use core::ffi::c_void;
26use core::fmt::{Debug, Display, Formatter};
27use core::ops::Deref;
28use core::ptr::null_mut;
29
30use alloc::boxed::Box;
31use alloc::sync::Arc;
32
33use super::ffi::{INVALID, TaskStatus, ThreadHandle, pdPASS, pdTRUE, vTaskDelete, vTaskGetInfo, vTaskResume, vTaskSuspend, xTaskCreate, xTaskGetCurrentTaskHandle};
34use super::types::{StackType, UBaseType, BaseType, TickType};
35use super::thread::ThreadState::*;
36use crate::os::ThreadSimpleFnPtr;
37use crate::traits::{ThreadFn, ThreadParam, ThreadFnPtr, ThreadNotification, ToTick, ToPriority};
38use crate::utils::{Bytes, DoublePtr, Error, Result};
39
40const MAX_TASK_NAME_LEN: usize = 16;
41
42/// Represents the possible states of a FreeRTOS task/thread.
43///
44/// # Examples
45///
46/// ```ignore
47/// use osal_rs::os::{Thread, ThreadState};
48/// 
49/// let thread = Thread::current();
50/// let metadata = thread.metadata().unwrap();
51/// 
52/// match metadata.state {
53///     ThreadState::Running => println!("Thread is currently executing"),
54///     ThreadState::Ready => println!("Thread is ready to run"),
55///     ThreadState::Blocked => println!("Thread is waiting for an event"),
56///     ThreadState::Suspended => println!("Thread is suspended"),
57///     _ => println!("Unknown state"),
58/// }
59/// ```
60#[derive(Copy, Clone, Debug, PartialEq)]
61#[repr(u8)]
62pub enum ThreadState {
63    /// Thread is currently executing on a CPU
64    Running = 0,
65    /// Thread is ready to run but not currently executing
66    Ready = 1,
67    /// Thread is blocked waiting for an event (e.g., semaphore, queue)
68    Blocked = 2,
69    /// Thread has been explicitly suspended
70    Suspended = 3,
71    /// Thread has been deleted
72    Deleted = 4,
73    /// Invalid or unknown state
74    Invalid,
75}
76
77/// Metadata and runtime information about a thread.
78///
79/// Contains detailed information about a thread's state, priorities, stack usage,
80/// and runtime statistics.
81///
82/// # Examples
83///
84/// ```ignore
85/// use osal_rs::os::Thread;
86/// 
87/// let thread = Thread::current();
88/// let metadata = thread.metadata().unwrap();
89/// 
90/// println!("Thread: {}", metadata.name);
91/// println!("Priority: {}", metadata.priority);
92/// println!("Stack high water mark: {}", metadata.stack_high_water_mark);
93/// ```
94#[derive(Clone, Debug)]
95pub struct ThreadMetadata {
96    /// FreeRTOS task handle
97    pub thread: ThreadHandle,
98    /// Thread name
99    pub name: Bytes<MAX_TASK_NAME_LEN>,
100    /// Original stack depth allocated for this thread
101    pub stack_depth: StackType,
102    /// Thread priority
103    pub priority: UBaseType,
104    /// Unique thread number assigned by FreeRTOS
105    pub thread_number: UBaseType,
106    /// Current execution state
107    pub state: ThreadState,
108    /// Current priority (may differ from base priority due to priority inheritance)
109    pub current_priority: UBaseType,
110    /// Base priority without inheritance
111    pub base_priority: UBaseType,
112    /// Total runtime counter (requires configGENERATE_RUN_TIME_STATS)
113    pub run_time_counter: UBaseType,
114    /// Minimum remaining stack space ever recorded (lower values indicate higher stack usage)
115    pub stack_high_water_mark: StackType,
116}
117
118unsafe impl Send for ThreadMetadata {}
119unsafe impl Sync for ThreadMetadata {}
120
121/// Converts a FreeRTOS TaskStatus into ThreadMetadata.
122///
123/// This conversion extracts all relevant task information from the FreeRTOS
124/// TaskStatus structure and creates a safe Rust representation.
125impl From<(ThreadHandle,TaskStatus)> for ThreadMetadata {
126    fn from(status: (ThreadHandle, TaskStatus)) -> Self {
127        let state = match status.1.eCurrentState {
128            0 => Running,
129            1 => Ready,
130            2 => Blocked,
131            3 => Suspended,
132            4 => Deleted,
133            _ => Invalid,
134        };
135
136        ThreadMetadata {
137            thread: status.0,
138            name: Bytes::from_char_ptr(status.1.pcTaskName),
139            // Avoid dereferencing pxStackBase, which may be null or otherwise invalid.
140            // Use 0 as a safe default for unknown stack depth.
141            stack_depth: 0,
142            priority: status.1.uxBasePriority,
143            thread_number: status.1.xTaskNumber,
144            state,
145            current_priority: status.1.uxCurrentPriority,
146            base_priority: status.1.uxBasePriority,
147            run_time_counter: status.1.ulRunTimeCounter,
148            stack_high_water_mark: status.1.usStackHighWaterMark,
149        }
150    }
151}
152
153/// Provides default values for ThreadMetadata.
154///
155/// Creates a metadata instance with null/zero values, representing an
156/// invalid or uninitialized thread.
157impl Default for ThreadMetadata {
158    fn default() -> Self {
159        ThreadMetadata {
160            thread: null_mut(),
161            name: Bytes::new(),
162            stack_depth: 0,
163            priority: 0,
164            thread_number: 0,
165            state: Invalid,
166            current_priority: 0,
167            base_priority: 0,
168            run_time_counter: 0,
169            stack_high_water_mark: 0,
170        }
171    }
172}
173
174/// A FreeRTOS task/thread wrapper.
175///
176/// Provides a safe Rust interface for creating and managing FreeRTOS tasks.
177/// Threads can be created with closures or function pointers and support
178/// various synchronization primitives.
179///
180/// # Examples
181///
182/// ## Creating a simple thread
183///
184/// ```ignore
185/// use osal_rs::os::{Thread, ThreadPriority};
186/// use core::time::Duration;
187/// 
188/// let thread = Thread::new(
189///     "worker",
190///     2048,  // stack size in words
191///     ThreadPriority::Normal,
192///     || {
193///         loop {
194///             println!("Working...");
195///             Duration::from_secs(1).sleep();
196///         }
197///     }
198/// ).unwrap();
199/// 
200/// thread.start().unwrap();
201/// ```
202///
203/// ## Using thread notifications
204///
205/// ```ignore
206/// use osal_rs::os::{Thread, ThreadNotification};
207/// use core::time::Duration;
208/// 
209/// let thread = Thread::new("notified", 2048, 5, || {
210///     loop {
211///         if let Some(value) = Thread::current().wait_notification(Duration::from_secs(1)) {
212///             println!("Received notification: {}", value);
213///         }
214///     }
215/// }).unwrap();
216/// 
217/// thread.start().unwrap();
218/// thread.notify(42).unwrap();  // Send notification
219/// ```
220#[derive(Clone)]
221pub struct Thread {
222    handle: ThreadHandle,
223    name: Bytes<MAX_TASK_NAME_LEN>,
224    stack_depth: StackType,
225    priority: UBaseType,
226    callback: Option<Arc<ThreadFnPtr>>,
227    param: Option<ThreadParam>
228}
229
230unsafe impl Send for Thread {}
231unsafe impl Sync for Thread {}
232
233impl Thread {
234
235    /// Creates a new uninitialized thread.
236    ///
237    /// The thread must be started with `spawn()` or `spawn_simple()`.
238    ///
239    /// # Examples
240    ///
241    /// ```ignore
242    /// use osal_rs::os::{Thread, ThreadFn};
243    /// 
244    /// let thread = Thread::new("worker", 4096, 5);
245    /// ```
246    pub fn new(name: &str, stack_depth: StackType, priority: UBaseType) -> Self 
247    {
248        Self { 
249            handle: null_mut(), 
250            name: Bytes::from_str(name),
251            stack_depth, 
252            priority, 
253            callback: None,
254            param: None 
255        }
256    }
257
258    /// Creates a thread from an existing task handle.
259    ///
260    /// # Returns
261    ///
262    /// * `Err(Error::NullPtr)` if handle is null
263    pub fn new_with_handle(handle: ThreadHandle, name: &str, stack_depth: StackType, priority: UBaseType) -> Result<Self> {
264        if handle.is_null() {
265            return Err(Error::NullPtr);
266        }
267        Ok(Self { 
268            handle, 
269            name: Bytes::from_str(name), 
270            stack_depth, 
271            priority, 
272            callback: None,
273            param: None 
274        })
275    }
276
277    /// Creates a new thread with a priority that implements `ToPriority`.
278    ///
279    /// This is a convenience constructor that allows using various priority types.
280    ///
281    /// # Parameters
282    ///
283    /// * `name` - Thread name for debugging
284    /// * `stack_depth` - Stack size in words (not bytes)
285    /// * `priority` - Thread priority (any type implementing `ToPriority`)
286    ///
287    /// # Examples
288    ///
289    /// ```ignore
290    /// use osal_rs::os::Thread;
291    /// 
292    /// let thread = Thread::new_with_to_priority("worker", 2048, 5);
293    /// ```
294    pub fn new_with_to_priority(name: &str, stack_depth: StackType, priority: impl ToPriority) -> Self 
295    {
296        Self { 
297            handle: null_mut(), 
298            name: Bytes::from_str(name), 
299            stack_depth, 
300            priority: priority.to_priority(), 
301            callback: None,
302            param: None 
303        }
304    }
305
306    /// Creates a thread from an existing FreeRTOS task handle.
307    ///
308    /// # Parameters
309    ///
310    /// * `handle` - Valid FreeRTOS task handle
311    /// * `name` - Thread name
312    /// * `stack_depth` - Stack size
313    /// * `priority` - Thread priority
314    ///
315    /// # Returns
316    ///
317    /// * `Err(Error::NullPtr)` if handle is null
318    ///
319    /// # Examples
320    ///
321    /// ```ignore
322    /// use osal_rs::os::Thread;
323    /// 
324    /// // Get current task handle from FreeRTOS
325    /// let handle = get_task_handle();
326    /// let thread = Thread::new_with_handle_and_to_priority(handle, "existing", 2048, 5).unwrap();
327    /// ```
328    pub fn new_with_handle_and_to_priority(handle: ThreadHandle, name: &str, stack_depth: StackType, priority: impl ToPriority) -> Result<Self> {
329        if handle.is_null() {
330            return Err(Error::NullPtr);
331        }
332        Ok(Self { 
333            handle, 
334            name: Bytes::from_str(name),
335            stack_depth, 
336            priority: priority.to_priority(), 
337            callback: None,
338            param: None 
339        })
340    }
341
342    /// Retrieves metadata for a thread from its handle.
343    ///
344    /// # Parameters
345    ///
346    /// * `handle` - FreeRTOS task handle
347    ///
348    /// # Returns
349    ///
350    /// Thread metadata including state, priority, stack usage, etc.
351    ///
352    /// # Examples
353    ///
354    /// ```ignore
355    /// use osal_rs::os::Thread;
356    /// 
357    /// let handle = get_some_task_handle();
358    /// let metadata = Thread::get_metadata_from_handle(handle);
359    /// println!("Thread '{}' state: {:?}", metadata.name, metadata.state);
360    /// ```
361    pub fn get_metadata_from_handle(handle: ThreadHandle) -> ThreadMetadata {
362        let mut status = TaskStatus::default();
363        unsafe {
364            vTaskGetInfo(handle, &mut status, pdTRUE, INVALID);
365        }
366        ThreadMetadata::from((handle, status))
367    }
368
369    /// Retrieves metadata for a thread object.
370    ///
371    /// # Parameters
372    ///
373    /// * `thread` - Thread reference
374    ///
375    /// # Returns
376    ///
377    /// Thread metadata or default if handle is null
378    ///
379    /// # Examples
380    ///
381    /// ```ignore
382    /// use osal_rs::os::Thread;
383    /// 
384    /// let thread = Thread::new("worker", 2048, 5);
385    /// let metadata = Thread::get_metadata(&thread);
386    /// println!("Stack high water mark: {}", metadata.stack_high_water_mark);
387    /// ```
388    pub fn get_metadata(thread: &Thread) -> ThreadMetadata {
389        if thread.handle.is_null() {
390            return ThreadMetadata::default();
391        }
392        Self::get_metadata_from_handle(thread.handle)
393    }
394
395    /// Waits for a thread notification with a timeout that implements `ToTick`.
396    ///
397    /// Convenience method that accepts `Duration` or other tick-convertible types.
398    ///
399    /// # Parameters
400    ///
401    /// * `bits_to_clear_on_entry` - Bits to clear before waiting
402    /// * `bits_to_clear_on_exit` - Bits to clear after receiving notification
403    /// * `timeout_ticks` - Maximum time to wait (convertible to ticks)
404    ///
405    /// # Returns
406    ///
407    /// * `Ok(u32)` - Notification value received
408    /// * `Err(Error::NullPtr)` - Thread handle is null
409    /// * `Err(Error::Timeout)` - No notification received within timeout
410    ///
411    /// # Examples
412    ///
413    /// ```ignore
414    /// use osal_rs::os::{Thread, ThreadFn};
415    /// use core::time::Duration;
416    /// 
417    /// let thread = Thread::current();
418    /// match thread.wait_notification_with_to_tick(0, 0xFF, Duration::from_secs(1)) {
419    ///     Ok(value) => println!("Received: {}", value),
420    ///     Err(_) => println!("Timeout"),
421    /// }
422    /// ```
423    #[inline]
424    pub fn wait_notification_with_to_tick(&self, bits_to_clear_on_entry: u32, bits_to_clear_on_exit: u32 , timeout_ticks: impl ToTick) -> Result<u32> {
425        if self.handle.is_null() {
426            return Err(Error::NullPtr);
427        }
428        self.wait_notification(bits_to_clear_on_entry, bits_to_clear_on_exit, timeout_ticks.to_ticks())
429    }
430
431}
432
433/// Internal C-compatible wrapper for thread callbacks.
434///
435/// This function bridges between FreeRTOS C API and Rust closures.
436/// It unpacks the boxed thread instance, initializes the handle,
437/// and calls the user-provided callback.
438///
439/// # Safety
440///
441/// This function is marked unsafe because it:
442/// - Expects a valid pointer to a boxed Thread instance
443/// - Performs raw pointer conversions
444/// - Is called from C code (FreeRTOS)
445unsafe extern "C" fn callback_c_wrapper(param_ptr: *mut c_void) {
446    if param_ptr.is_null() {
447        return;
448    }
449
450    let mut thread_instance: Box<Thread> = unsafe { Box::from_raw(param_ptr as *mut _) };
451
452    thread_instance.as_mut().handle = unsafe { xTaskGetCurrentTaskHandle() };
453
454    let thread = *thread_instance.clone();
455
456    let param_arc: Option<ThreadParam> = thread_instance
457        .param
458        .clone();
459
460    if let Some(callback) = &thread_instance.callback.clone() {
461        let _ = callback(thread_instance, param_arc);
462    }
463
464    thread.delete();
465}
466
467/// Internal C-compatible wrapper for simple thread callbacks.
468///
469/// This function bridges between FreeRTOS C API and simple Rust closures
470/// (without parameters). It unpacks the boxed function pointer and executes it.
471///
472/// # Safety
473///
474/// This function is marked unsafe because it:
475/// - Expects a valid pointer to a boxed function pointer
476/// - Performs raw pointer conversions
477/// - Is called from C code (FreeRTOS)
478/// - Directly calls vTaskDelete after execution
479unsafe extern "C" fn simple_callback_wrapper(param_ptr: *mut c_void) {
480    if param_ptr.is_null() {
481        return;
482    }
483
484    let func: Box<Arc<ThreadSimpleFnPtr>> = unsafe { Box::from_raw(param_ptr as *mut _) };
485    func();
486
487    unsafe { vTaskDelete( xTaskGetCurrentTaskHandle()); } 
488}
489
490
491
492impl ThreadFn for Thread {
493
494    /// Spawns a new thread with a callback.
495    /// 
496    /// # Important
497    /// The callback must be `'static`, which means it cannot borrow local variables.
498    /// Use `move` in the closure to transfer ownership of any captured values:
499    /// 
500    /// ```ignore
501    /// let data = Arc::new(Mutex::new(0));
502    /// let thread = Thread::new("my_thread", 4096, 3, move |_thread, _param| {
503    ///     // Use 'move' to capture 'data' by value
504    ///     let mut guard = data.lock().unwrap();
505    ///     *guard += 1;
506    ///     Ok(Arc::new(()))
507    /// });
508    /// ``
509    fn spawn<F>(&mut self, param: Option<ThreadParam>, callback: F) -> Result<Self> 
510        where 
511        F: Fn(Box<dyn ThreadFn>, Option<ThreadParam>) -> Result<ThreadParam>,
512        F: Send + Sync + 'static {
513
514        let mut handle: ThreadHandle =  null_mut();
515
516        let func: Arc<ThreadFnPtr> = Arc::new(callback);
517        
518        self.callback = Some(func);
519        self.param = param.clone();
520
521        let boxed_thread = Box::new(self.clone());
522
523        let ret = unsafe {
524            xTaskCreate(
525                Some(super::thread::callback_c_wrapper),
526                self.name.as_cstr().as_ptr(),
527                self.stack_depth,
528                Box::into_raw(boxed_thread) as *mut _,
529                self.priority,
530                &mut handle,
531            )
532        };
533
534        if ret != pdPASS {
535            return Err(Error::OutOfMemory)
536        }
537
538        Ok(Self { 
539            handle,
540            callback: self.callback.clone(),
541            param,
542            ..self.clone()
543        })
544    }
545
546    /// Spawns a new thread with a simple closure, similar to `std::thread::spawn`.
547    /// This is the recommended way to create threads for most use cases.
548    /// 
549    /// # Example
550    /// ```ignore
551    /// let counter = Arc::new(Mutex::new(0));
552    /// let counter_clone = Arc::clone(&counter);
553    /// 
554    /// let handle = Thread::spawn_simple("worker", 4096, 3, move || {
555    ///     let mut num = counter_clone.lock().unwrap();
556    ///     *num += 1;
557    /// }).unwrap();
558    /// 
559    /// handle.join(core::ptr::null_mut());
560    /// ```
561    fn spawn_simple<F>(&mut self, callback: F) -> Result<Self>
562    where
563        F: Fn() + Send + Sync + 'static,
564    {
565        let func: Arc<ThreadSimpleFnPtr> = Arc::new(callback);
566        let boxed_func = Box::new(func);
567        
568        let mut handle: ThreadHandle = null_mut();
569
570        let ret = unsafe {
571            xTaskCreate(
572                Some(simple_callback_wrapper),
573                self.name.as_cstr().as_ptr(),
574                self.stack_depth,
575                Box::into_raw(boxed_func) as *mut _,
576                self.priority,
577                &mut handle,
578            )
579        };
580
581        if ret != pdPASS {
582            return Err(Error::OutOfMemory);
583        }
584
585        Ok(Self {
586            handle,
587            ..self.clone()
588        })
589    }
590
591    /// Deletes the thread and frees its resources.
592    ///
593    /// # Safety
594    ///
595    /// After calling this, the thread handle becomes invalid.
596    ///
597    /// # Examples
598    ///
599    /// ```ignore
600    /// use osal_rs::os::{Thread, ThreadFn};
601    /// 
602    /// let thread = Thread::new("temp", 2048, 5);
603    /// thread.delete();
604    /// ```
605    fn delete(&self) {
606        if !self.handle.is_null() {
607            unsafe { vTaskDelete( self.handle ); } 
608        }
609    }
610
611    /// Suspends the thread execution.
612    ///
613    /// The thread remains suspended until `resume()` is called.
614    ///
615    /// # Examples
616    ///
617    /// ```ignore
618    /// use osal_rs::os::{Thread, ThreadFn};
619    /// use core::time::Duration;
620    /// 
621    /// let thread = get_some_thread();
622    /// thread.suspend();
623    /// Duration::from_secs(1).sleep();
624    /// thread.resume();
625    /// ```
626    fn suspend(&self) {
627        if !self.handle.is_null() {
628            unsafe { vTaskSuspend( self.handle ); } 
629        }
630    }
631
632    /// Resumes a previously suspended thread.
633    ///
634    /// # Examples
635    ///
636    /// ```ignore
637    /// thread.resume();
638    /// ```
639    fn resume(&self) {
640        if !self.handle.is_null() {
641            unsafe { vTaskResume( self.handle ); } 
642        }
643    }
644
645    /// Waits for the thread to complete (currently deletes the thread).
646    ///
647    /// # Returns
648    ///
649    /// Always returns `Ok(0)`
650    fn join(&self, _retval: DoublePtr) -> Result<i32> {
651        if !self.handle.is_null() {
652            unsafe { vTaskDelete( self.handle ); } 
653        }
654        Ok(0)
655    }
656
657    /// Retrieves this thread's metadata.
658    ///
659    /// # Examples
660    ///
661    /// ```ignore
662    /// use osal_rs::os::{Thread, ThreadFn};
663    /// 
664    /// let thread = Thread::current();
665    /// let meta = thread.get_metadata();
666    /// println!("Running thread: {}", meta.name);
667    /// ```
668    fn get_metadata(&self) -> ThreadMetadata {
669        let mut status = TaskStatus::default();
670        unsafe {
671            vTaskGetInfo(self.handle, &mut status, pdTRUE, INVALID);
672        }
673        ThreadMetadata::from((self.handle, status))
674    }
675
676    /// Returns a Thread object representing the currently executing thread.
677    ///
678    /// # Examples
679    ///
680    /// ```ignore
681    /// use osal_rs::os::{Thread, ThreadFn};
682    /// 
683    /// let current = Thread::get_current();
684    /// println!("Current thread: {}", current.get_metadata().name);
685    /// ```
686    fn get_current() -> Self {
687        let handle = unsafe { xTaskGetCurrentTaskHandle() };
688        let metadata = Self::get_metadata_from_handle(handle);
689        Self {
690            handle,
691            name: metadata.name.clone(),
692            stack_depth: metadata.stack_depth,
693            priority: metadata.priority,
694            callback: None,
695            param: None,
696        }
697    }
698
699    /// Sends a notification to this thread.
700    ///
701    /// # Parameters
702    ///
703    /// * `notification` - Type of notification action to perform
704    ///
705    /// # Returns
706    ///
707    /// * `Ok(())` - Notification sent successfully
708    /// * `Err(Error::NullPtr)` - Thread handle is null
709    /// * `Err(Error::QueueFull)` - Notification failed
710    ///
711    /// # Examples
712    ///
713    /// ```ignore
714    /// use osal_rs::os::{Thread, ThreadFn, ThreadNotification};
715    /// 
716    /// let thread = get_worker_thread();
717    /// thread.notify(ThreadNotification::SetValueWithOverwrite(42)).unwrap();
718    /// ```
719    fn notify(&self, notification: ThreadNotification) -> Result<()> {
720        if self.handle.is_null() {
721            return Err(Error::NullPtr);
722        }
723
724        let (action, value) = notification.into();
725
726        let ret = xTaskNotify!(
727            self.handle,
728            value,
729            action
730        );
731        
732        if ret != pdPASS {
733            Err(Error::QueueFull)
734        } else {
735            Ok(())
736        }
737
738    }
739
740    /// Sends a notification to this thread from an ISR.
741    ///
742    /// # Parameters
743    ///
744    /// * `notification` - Type of notification action
745    /// * `higher_priority_task_woken` - Set to pdTRUE if a higher priority task was woken
746    ///
747    /// # Returns
748    ///
749    /// * `Ok(())` - Notification sent successfully
750    /// * `Err(Error::NullPtr)` - Thread handle is null
751    /// * `Err(Error::QueueFull)` - Notification failed
752    ///
753    /// # Examples
754    ///
755    /// ```ignore
756    /// // In ISR context:
757    /// let mut woken = pdFALSE;
758    /// thread.notify_from_isr(ThreadNotification::Increment, &mut woken).ok();
759    /// ```
760    fn notify_from_isr(&self, notification: ThreadNotification, higher_priority_task_woken: &mut BaseType) -> Result<()> {
761        if self.handle.is_null() {
762            return Err(Error::NullPtr);
763        }
764
765        let (action, value) = notification.into();
766
767        let ret = xTaskNotifyFromISR!(
768            self.handle,
769            value,
770            action,
771            higher_priority_task_woken
772        );
773
774        if ret != pdPASS {
775            Err(Error::QueueFull)
776        } else {
777            Ok(())
778        }
779    }
780
781    /// Waits for a thread notification.
782    ///
783    /// # Parameters
784    ///
785    /// * `bits_to_clear_on_entry` - Bits to clear in notification value before waiting
786    /// * `bits_to_clear_on_exit` - Bits to clear after receiving notification
787    /// * `timeout_ticks` - Maximum ticks to wait
788    ///
789    /// # Returns
790    ///
791    /// * `Ok(u32)` - Notification value received
792    /// * `Err(Error::NullPtr)` - Thread handle is null
793    /// * `Err(Error::Timeout)` - No notification within timeout
794    ///
795    /// # Examples
796    ///
797    /// ```ignore
798    /// use osal_rs::os::{Thread, ThreadFn};
799    /// 
800    /// let thread = Thread::current();
801    /// match thread.wait_notification(0, 0xFFFFFFFF, 1000) {
802    ///     Ok(value) => println!("Received notification: {}", value),
803    ///     Err(_) => println!("Timeout waiting for notification"),
804    /// }
805    /// ```
806    fn wait_notification(&self, bits_to_clear_on_entry: u32, bits_to_clear_on_exit: u32 , timeout_ticks: TickType) -> Result<u32> {
807        if self.handle.is_null() {
808            return Err(Error::NullPtr);
809        }
810
811        let mut notification_value: u32 = 0;
812
813        let ret = xTaskNotifyWait!(
814            bits_to_clear_on_entry,
815            bits_to_clear_on_exit,
816            &mut notification_value,
817            timeout_ticks
818        );
819        
820
821        if ret == pdTRUE {
822            Ok(notification_value)
823        } else {
824            Err(Error::Timeout)
825        }
826    }
827
828}
829
830
831// impl Drop for Thread {
832//     fn drop(&mut self) {
833//         if !self.handle.is_null() {
834//             unsafe { vTaskDelete( self.handle ); } 
835//         }
836//     }
837// }
838
839/// Allows dereferencing to the underlying FreeRTOS thread handle.
840///
841/// This enables direct access to the handle when needed for low-level operations.
842impl Deref for Thread {
843    type Target = ThreadHandle;
844
845    fn deref(&self) -> &Self::Target {
846        &self.handle
847    }
848}
849
850/// Formats the thread for debugging purposes.
851///
852/// Includes handle, name, stack depth, priority, and callback status.
853impl Debug for Thread {
854    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
855        f.debug_struct("Thread")
856            .field("handle", &self.handle)
857            .field("name", &self.name)
858            .field("stack_depth", &self.stack_depth)
859            .field("priority", &self.priority)
860            .field("callback", &self.callback.as_ref().map(|_| "Some(...)"))
861            .field("param", &self.param)
862            .finish()
863    }
864}
865
866/// Formats the thread for display purposes.
867///
868/// Shows a concise representation with handle, name, priority, and stack depth.
869impl Display for Thread {
870    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
871        write!(f, "Thread {{ handle: {:?}, name: {}, priority: {}, stack_depth: {} }}", self.handle, self.name, self.priority, self.stack_depth)
872    }
873}
874
875