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