Skip to main content

osal_rs/
lib.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//! # OSAL-RS - Operating System Abstraction Layer for Rust
21//!
22//! A cross-platform abstraction layer for embedded and real-time operating systems.
23//!
24//! ## Overview
25//!
26//! OSAL-RS provides a unified, safe Rust API for working with different real-time
27//! operating systems. Currently supports FreeRTOS with planned support for POSIX
28//! and other RTOSes.
29//!
30//! ## Features
31//!
32//! - **Thread Management**: Create and control threads with priorities
33//! - **Synchronization**: Mutexes, semaphores, and event groups
34//! - **Communication**: Queues for inter-thread message passing
35//! - **Timers**: Software timers for periodic and one-shot operations
36//! - **Time Management**: Duration-based timing with tick conversion
37//! - **No-std Support**: Works in bare-metal embedded environments
38//! - **Type Safety**: Leverages Rust's type system for correctness
39//!
40//! ## Quick Start
41//!
42//! ### Basic Thread Example
43//!
44//! ```ignore
45//! use osal_rs::os::*;
46//! use core::time::Duration;
47//!
48//! fn main() {
49//!     // Create a thread
50//!     let thread = Thread::new(
51//!         "worker",
52//!         4096,  // stack size
53//!         5,     // priority
54//!         || {
55//!             loop {
56//!                 println!("Working...");
57//!                 Duration::from_secs(1).sleep();
58//!             }
59//!         }
60//!     ).unwrap();
61//!
62//!     thread.start().unwrap();
63//!     
64//!     // Start the scheduler
65//!     System::start();
66//! }
67//! ```
68//!
69//! ### Mutex Example
70//!
71//! ```ignore
72//! use osal_rs::os::*;
73//! use alloc::sync::Arc;
74//!
75//! let counter = Arc::new(Mutex::new(0));
76//! let counter_clone = counter.clone();
77//!
78//! let thread = Thread::new("incrementer", 2048, 5, move || {
79//!     let mut guard = counter_clone.lock().unwrap();
80//!     *guard += 1;
81//! }).unwrap();
82//! ```
83//!
84//! ### Queue Example
85//!
86//! ```ignore
87//! use osal_rs::os::*;
88//! use core::time::Duration;
89//!
90//! let queue = Queue::new(10, 4).unwrap();
91//!
92//! // Send data
93//! let data = [1u8, 2, 3, 4];
94//! queue.post(&data, 100).unwrap();
95//!
96//! // Receive data
97//! let mut buffer = [0u8; 4];
98//! queue.fetch(&mut buffer, 100).unwrap();
99//! ```
100//!
101//! ### Semaphore Example
102//!
103//! ```ignore
104//! use osal_rs::os::*;
105//! use core::time::Duration;
106//!
107//! let sem = Semaphore::new(1, 1).unwrap();
108//!
109//! if sem.wait(Duration::from_millis(100)).into() {
110//!     // Critical section
111//!     sem.signal();
112//! }
113//! ```
114//!
115//! ### Timer Example
116//!
117//! ```ignore
118//! use osal_rs::os::*;
119//! use core::time::Duration;
120//!
121//! let timer = Timer::new_with_to_tick(
122//!     "periodic",
123//!     Duration::from_millis(500),
124//!     true,  // auto-reload
125//!     None,
126//!     |_, _| {
127//!         println!("Timer tick");
128//!         Ok(None)
129//!     }
130//! ).unwrap();
131//!
132//! timer.start_with_to_tick(Duration::from_millis(10));
133//! ```
134//!
135//! ## Module Organization
136//!
137//! - [`os`] - Main module containing all OS abstractions
138//!   - Threads, mutexes, semaphores, queues, event groups, timers
139//!   - System-level functions
140//!   - Type definitions
141//! - [`utils`] - Utility types and error definitions
142//! - [`log`] - Logging macros
143//! - `traits` - Private module defining the trait abstractions
144//! - `freertos` - Private FreeRTOS implementation (enabled with `freertos` feature)
145//! - `posix` - Private POSIX implementation (enabled with `posix` feature, planned)
146//!
147//! ## Features
148//!
149//! - `freertos` - Enable FreeRTOS support (default)
150//! - `posix` - Enable POSIX support (planned)
151//! - `std` - Enable standard library support for testing
152//! - `disable_panic` - Disable the default panic handler and allocator
153//!
154//! ## Requirements
155//!
156//! When using with FreeRTOS:
157//! - FreeRTOS kernel must be properly configured
158//! - Link the C porting layer from `osal-rs-porting/freertos/`
159//! - Set appropriate `FreeRTOSConfig.h` options:
160//!   - `configTICK_RATE_HZ` - Defines the tick frequency
161//!   - `configUSE_MUTEXES` - Must be 1 for mutex support
162//!   - `configUSE_COUNTING_SEMAPHORES` - Must be 1 for semaphore support
163//!   - `configUSE_TIMERS` - Must be 1 for timer support
164//!   - `configSUPPORT_DYNAMIC_ALLOCATION` - Must be 1 for dynamic allocation
165//!
166//! ## Platform Support
167//!
168//! Currently tested on:
169//! - ARM Cortex-M (Raspberry Pi Pico/RP2040, RP2350)
170//! - ARM Cortex-M4F (STM32F4 series)
171//! - ARM Cortex-M7 (STM32H7 series)
172//! - RISC-V (RP2350 RISC-V cores)
173//!
174//! ## Thread Safety
175//!
176//! All types are designed with thread safety in mind:
177//! - Most operations are thread-safe and can be called from multiple threads
178//! - Methods with `_from_isr` suffix are ISR-safe (callable from interrupt context)
179//! - Regular methods (without `_from_isr`) must not be called from ISR context
180//! - Mutexes use priority inheritance to prevent priority inversion
181//!
182//! ## ISR Context
183//!
184//! Operations in ISR context have restrictions:
185//! - Cannot block or use timeouts (must use zero timeout or `_from_isr` variants)
186//! - Must be extremely fast to avoid blocking other interrupts
187//! - Use semaphores or queues to defer work to task context
188//! - Event groups and notifications are ISR-safe for signaling
189//!
190//! ## Safety
191//!
192//! This library uses `unsafe` internally to interface with C APIs but provides
193//! safe Rust abstractions. All public APIs are designed to be memory-safe when
194//! used correctly:
195//! - Type safety through generic parameters
196//! - RAII patterns for automatic resource management
197//! - Rust's ownership system prevents data races
198//! - FFI boundaries are carefully validated
199//!
200//! ## Performance Considerations
201//!
202//! - Allocations happen on the FreeRTOS heap, not the system heap
203//! - Stack sizes must be carefully tuned for each thread
204//! - Priority inversion is mitigated through priority inheritance
205//! - Context switches are triggered by blocking operations
206//!
207//! ## Best Practices
208//!
209//! 1. **Thread Creation**: Always specify appropriate stack sizes based on usage
210//! 2. **Mutexes**: Prefer scoped locking with guards to prevent deadlocks
211//! 3. **Queues**: Use type-safe `QueueStreamed` when possible
212//! 4. **Semaphores**: Use binary semaphores for signaling, counting for resources
213//! 5. **ISR Handlers**: Keep ISR code minimal, defer work to tasks
214//! 6. **Error Handling**: Always check `Result` return values
215//!
216//! ## License
217//!
218//! GPL-3.0 - See LICENSE file for details
219
220#![cfg_attr(not(feature = "std"), no_std)]
221
222// Suppress warnings from FreeRTOS FFI bindings being included in multiple modules
223#![allow(clashing_extern_declarations)]
224#![allow(dead_code)]
225
226extern crate alloc;
227
228/// FreeRTOS implementation of OSAL traits.
229///
230/// This module contains the concrete implementation of all OSAL abstractions
231/// for FreeRTOS, including threads, mutexes, queues, timers, etc.
232///
233/// Enabled with the `freertos` feature flag (on by default).
234#[cfg(feature = "freertos")]
235mod freertos;
236
237/// POSIX implementation of OSAL traits (planned).
238///
239/// This module will contain the implementation for POSIX-compliant systems.
240/// Currently under development.
241///
242/// Enabled with the `posix` feature flag.
243#[cfg(feature = "posix")]
244mod posix;
245
246pub mod log;
247
248/// Trait definitions for OSAL abstractions.
249///
250/// This private module defines all the trait interfaces that concrete
251/// implementations must satisfy. Traits are re-exported through the `os` module.
252mod traits;
253
254pub mod utils;
255
256/// Select FreeRTOS as the active OSAL backend.
257#[cfg(feature = "freertos")]
258use crate::freertos as osal;
259
260/// Select POSIX as the active OSAL backend.
261#[cfg(feature = "posix")]
262use crate::posix as osal;
263
264/// Main OSAL module re-exporting all OS abstractions and traits.
265///
266/// This module provides a unified interface to all OSAL functionality through `osal_rs::os::*`.
267/// It re-exports:
268/// - Thread management types (`Thread`, `ThreadNotification`)
269/// - Synchronization primitives (`Mutex`, `Semaphore`, `EventGroup`)
270/// - Communication types (`Queue`, `QueueStreamed`)
271/// - Timer types (`Timer`)
272/// - System functions (`System`)
273/// - All trait definitions from the `traits` module
274/// - Type definitions and configuration from the active backend
275///
276/// The actual implementation (FreeRTOS or POSIX) is selected at compile time via features.
277///
278/// # Examples
279///
280/// ```ignore
281/// use osal_rs::os::*;
282///
283/// fn main() {
284///     // Create and start a thread
285///     let thread = Thread::new("worker", 4096, 5, || {
286///         println!("Worker thread running");
287///     }).unwrap();
288///     
289///     thread.start().unwrap();
290///     System::start();
291/// }
292/// ```
293pub mod os {
294
295    #[cfg(not(feature = "disable_panic"))]
296    use crate::osal::allocator::Allocator;
297
298    /// Global allocator using the underlying RTOS heap.
299    ///
300    /// This static variable configures Rust's global allocator to use the
301    /// RTOS heap (e.g., FreeRTOS heap) instead of the system heap.
302    ///
303    /// # Behavior
304    ///
305    /// - All allocations via `alloc::vec::Vec`, `alloc::boxed::Box`, `alloc::string::String`, etc.
306    ///   will use the RTOS heap
307    /// - Memory is managed by the underlying RTOS (e.g., `pvPortMalloc`/`vPortFree` in FreeRTOS)
308    /// - Thread-safe: can be used from multiple tasks safely
309    ///
310    /// # Feature Flag
311    ///
312    /// - Active by default
313    /// - Disabled with `disable_panic` feature if you want to provide your own allocator
314    ///
315    /// # FreeRTOS Configuration
316    ///
317    /// Ensure your `FreeRTOSConfig.h` has:
318    /// - `configSUPPORT_DYNAMIC_ALLOCATION` set to 1
319    /// - `configTOTAL_HEAP_SIZE` configured appropriately for your application
320    ///
321    /// # Example
322    ///
323    /// ```ignore
324    /// use alloc::vec::Vec;
325    ///
326    /// // This allocation uses the FreeRTOS heap via ALLOCATOR
327    /// let mut v = Vec::new();
328    /// v.push(42);
329    /// ```
330    #[cfg(not(feature = "disable_panic"))]
331    #[global_allocator]
332    pub static ALLOCATOR: Allocator = Allocator;
333
334    /// Duration type and time conversion utilities.
335    #[allow(unused_imports)]
336    pub use crate::osal::duration::*;
337    
338    /// Event group synchronization primitives.
339    pub use crate::osal::event_group::*;
340    
341    /// Mutex types and guards for mutual exclusion.
342    pub use crate::osal::mutex::*;
343    
344    /// Queue types for inter-task communication.
345    pub use crate::osal::queue::*;
346    
347    /// Semaphore types for signaling and resource management.
348    pub use crate::osal::semaphore::*;
349    
350    /// System-level functions (scheduler, timing, critical sections).
351    pub use crate::osal::system::*;
352    
353    /// Thread/task management and notification types.
354    pub use crate::osal::thread::*;
355    
356    /// Software timer types for periodic and one-shot callbacks.
357    pub use crate::osal::timer::*;
358    
359    /// All OSAL trait definitions for advanced usage.
360    pub use crate::traits::*;
361    
362    /// RTOS configuration constants and types.
363    pub use crate::osal::config as config;
364    
365    /// Type aliases and common types used throughout OSAL.
366    pub use crate::osal::types as types;
367    
368}
369
370/// Default panic handler for `no_std` environments.
371///
372/// This panic handler is active when the `disable_panic` feature is **not** enabled.
373/// It prints panic information and enters an infinite loop to halt execution.
374///
375/// # Behavior
376///
377/// 1. Attempts to print panic information using the `println!` macro
378/// 2. Enters an infinite empty loop, halting the program
379///
380/// # Feature Flag
381///
382/// - Enabled by default in library mode
383/// - Disabled with `disable_panic` feature when users want to provide their own handler
384/// - Automatically disabled in examples that use `std`
385///
386/// # Safety
387///
388/// This handler is intentionally simple and does not attempt cleanup or recovery.
389/// In production embedded systems, consider:
390/// - Logging panic info to persistent storage
391/// - Performing safe shutdown procedures
392/// - Resetting the system via watchdog
393///
394/// # Custom Panic Handler
395///
396/// To provide your own panic handler, enable the `disable_panic` feature:
397///
398/// ```toml
399/// [dependencies]
400/// osal-rs = { version = "*", features = ["disable_panic"] }
401/// ```
402///
403/// Then define your own `#[panic_handler]` in your application.
404#[cfg(not(feature = "disable_panic"))]
405#[panic_handler]
406fn panic(info: &core::panic::PanicInfo) -> ! {
407    println!("Panic occurred: {}", info);
408    #[allow(clippy::empty_loop)]
409    loop {}
410}
411