Skip to main content

freertos_in_rust/
lib.rs

1/*
2 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
26 *
27 * [AMENDMENT] This file is part of FreeRTOS-in-Rust, a Rust port of the FreeRTOS kernel.
28 * The original C code has been translated to Rust while preserving the original
29 * structure, control flow, and comments as much as possible.
30 */
31
32//! # FreeRTOS-in-Rust - FreeRTOS Kernel in Rust
33//!
34//! This crate provides a pure-Rust implementation of the FreeRTOS kernel,
35//! translated line-by-line from the original C source code.
36//!
37//! ## Features
38//!
39//! - `port-dummy` - Dummy port for compilation (default, panics at runtime)
40//! - `arch-32bit` - 32-bit architecture types (default)
41//! - `arch-64bit` - 64-bit architecture types
42//! - `tick-32bit` - 32-bit tick counter (default)
43//! - `tick-64bit` - 64-bit tick counter
44//! - `alloc` - Enable memory allocation via Rust's global allocator
45//! - `std` - Enable std for host testing (allocation is selected independently)
46//! - `port-test` - Deterministic host test port
47//! - `all-kernel-features` - Enable kernel capabilities without selecting a port,
48//!   integer width, allocator, or SMP mode
49//! - `list-data-integrity-check` - Enable list data integrity checks
50//!
51//! Production targets must set `default-features = false` and enable exactly
52//! one hardware port. The default `port-dummy` selection is compile-only and
53//! cannot start a scheduler.
54
55#![no_std]
56#![allow(non_snake_case)]
57#![allow(non_camel_case_types)]
58#![allow(non_upper_case_globals)]
59#![allow(dead_code)] // During development
60#![allow(static_mut_refs)] // TODO: Migrate to raw pointers for Rust 2024
61
62#[cfg(not(any(
63    feature = "port-cortex-m0",
64    feature = "port-cortex-m3",
65    feature = "port-cortex-m4f",
66    feature = "port-cortex-m7",
67    feature = "port-riscv32",
68    feature = "port-cortex-a9",
69    feature = "port-cortex-a53",
70    feature = "port-test",
71    feature = "port-dummy"
72)))]
73compile_error!("select exactly one FreeRTOS-in-Rust port feature");
74
75#[cfg(any(
76    all(
77        feature = "port-cortex-m0",
78        any(
79            feature = "port-cortex-m3",
80            feature = "port-cortex-m4f",
81            feature = "port-cortex-m7",
82            feature = "port-riscv32",
83            feature = "port-cortex-a9",
84            feature = "port-cortex-a53",
85            feature = "port-test",
86            feature = "port-dummy"
87        )
88    ),
89    all(
90        feature = "port-cortex-m3",
91        any(
92            feature = "port-cortex-m4f",
93            feature = "port-cortex-m7",
94            feature = "port-riscv32",
95            feature = "port-cortex-a9",
96            feature = "port-cortex-a53",
97            feature = "port-test",
98            feature = "port-dummy"
99        )
100    ),
101    all(
102        feature = "port-cortex-m4f",
103        any(
104            feature = "port-cortex-m7",
105            feature = "port-riscv32",
106            feature = "port-cortex-a9",
107            feature = "port-cortex-a53",
108            feature = "port-test",
109            feature = "port-dummy"
110        )
111    ),
112    all(
113        feature = "port-cortex-m7",
114        any(
115            feature = "port-riscv32",
116            feature = "port-cortex-a9",
117            feature = "port-cortex-a53",
118            feature = "port-test",
119            feature = "port-dummy"
120        )
121    ),
122    all(
123        feature = "port-riscv32",
124        any(
125            feature = "port-cortex-a9",
126            feature = "port-cortex-a53",
127            feature = "port-test",
128            feature = "port-dummy"
129        )
130    ),
131    all(
132        feature = "port-cortex-a9",
133        any(
134            feature = "port-cortex-a53",
135            feature = "port-test",
136            feature = "port-dummy"
137        )
138    ),
139    all(
140        feature = "port-cortex-a53",
141        any(feature = "port-test", feature = "port-dummy")
142    ),
143    all(feature = "port-test", feature = "port-dummy")
144))]
145compile_error!("FreeRTOS-in-Rust port features are mutually exclusive");
146
147#[cfg(any(
148    all(feature = "heap-4", feature = "heap-5"),
149    all(feature = "heap-4", feature = "alloc"),
150    all(feature = "heap-5", feature = "alloc")
151))]
152compile_error!("allocator features are mutually exclusive");
153
154#[cfg(feature = "std")]
155extern crate std;
156
157#[cfg(any(feature = "alloc", feature = "heap-4", feature = "heap-5"))]
158extern crate alloc;
159
160// Core modules
161pub mod config;
162pub mod trace;
163pub mod types;
164
165// Port layer
166pub mod port;
167
168// Memory management
169pub mod memory;
170
171// Kernel modules
172pub mod kernel;
173
174// Safe synchronization wrappers. Individual capabilities such as Mutex,
175// streams, and timers retain their own feature gates.
176pub mod sync;
177
178// Re-export commonly used items at crate root (like FreeRTOS.h does)
179pub use config::*;
180pub use types::*;
181
182// =============================================================================
183// Convenience Functions
184// =============================================================================
185
186/// Delays the current task for the specified number of ticks.
187///
188/// This is a safe wrapper around `vTaskDelay`. The context capability prevents
189/// task-only delay operations from being called through an ISR or timer
190/// callback API.
191#[inline]
192pub fn delay(context: &sync::TaskContext, ticks: TickType_t) {
193    assert!(context.current().is_some(), "delay requires a running task");
194    sync::assert_can_block("delay", ticks);
195    // Safety: TaskContext and the checks above establish a live current task,
196    // running scheduler, task context, and an unsuspended blocking path.
197    unsafe { kernel::tasks::vTaskDelay(ticks) };
198}
199
200/// Delays the current task for the specified number of milliseconds.
201///
202/// Converts milliseconds to ticks using the configured tick rate without
203/// narrowing the millisecond value first.
204///
205/// # Panics
206///
207/// Panics when the requested duration cannot be represented by `TickType_t`.
208/// Use [`milliseconds_to_ticks_checked`] when the duration is not known to fit.
209#[inline]
210pub fn delay_ms(context: &sync::TaskContext, ms: u32) {
211    let ticks = milliseconds_to_ticks_checked(u64::from(ms))
212        .expect("millisecond delay does not fit in TickType_t");
213    delay(context, ticks);
214}
215
216/// Starts the FreeRTOS scheduler.
217///
218/// This function does not return under normal operation. Tasks must be
219/// created before calling this function.
220#[inline]
221pub fn start_scheduler(_context: sync::TaskContext) -> ! {
222    sync::assert_task_context("start_scheduler");
223    assert_eq!(
224        kernel::tasks::xTaskGetSchedulerState(),
225        kernel::tasks::taskSCHEDULER_NOT_STARTED,
226        "start_scheduler requires exclusive pre-scheduler initialization context"
227    );
228    // Safety: consuming the non-sendable startup capability establishes the
229    // crate's exclusive pre-scheduler entry boundary, and the unconditional
230    // state check rejects a TaskContext obtained from a running task. Internal
231    // task creation failures are handled by the raw scheduler path before it
232    // returns.
233    unsafe { kernel::tasks::vTaskStartScheduler() };
234    // vTaskStartScheduler only returns if creating an internal task failed.
235    panic!("FreeRTOS scheduler failed to start")
236}