1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//! # mu_lib
//!
//! A library providing essential functionality for the XCENA system.
//! This library is designed to work with both C++ and Rust, providing a safe and efficient interface
//! for system operations.
//!
//! ✅ `mu_lib` version **0.2.2** and `mu_macro` version **0.1.4** or higher are considered **stable**.
//! ✅ `mu rustc nightly` toolchain version **1.86.0** or higher is required.
//! Please use these versions or above to ensure compatibility.
//!
//! ## Features
//!
//! - Safe Rust bindings for all system operations
//! - Thread-safe atomic operations
//! - Comprehensive logging system
//! - Task management utilities
//! - System clock access
//! - Message passing capabilities
//!
//! ## Modules
//!
//! - `assert`: Provides condition checking and program termination functions
//! - `atomic`: Provides thread-safe atomic operations
//! - `clock`: Provides system clock functionality
//! - `logger`: Provides logging functionality with various log levels
//! - `message`: Provides synchronous and asynchronous message handling functions
//! - `print`: Provides output functionality for UART, host, and general printing
//! - `task`: Provides task management functionality
//!
//! ## Example: Creating and Building a `myMuKernel` Project
//!
//! This guide walks you through creating a minimal kernel crate using `mu_macro` and `mu_lib`.
//!
//! ### 1. Project Initialization
//!
//! Create a new Rust binary project:
//!
//! ```bash
//! cargo new myMuKernel
//! ```
//!
//! This generates:
//!
//! ```text
//! myMuKernel/
//! ├── Cargo.toml
//! └── src/
//! └── main.rs
//! ```
//!
//! ### 2. Build Environment Setup
//!
//! ⚠️ Make sure to adjust all paths (`rustc`, `linker`, library paths, etc.) to match your own environment.
//! Using incorrect paths will cause the build to fail.
//!
//! **Important**: The `MU_LIB_PATH` environment variable is used as the base for finding the linker and library paths.
//! It is crucial to ensure that `MU_LIB_PATH` is properly set as an environment variable.
//!
//! #### 2.1 Using `.cargo/config.toml`
//!
//! Create the `.cargo/config.toml` file:
//!
//! ```text
//! myMuKernel/
//! ├── Cargo.toml
//! ├── .cargo/
//! │ └── config.toml
//! └── src/
//! └── main.rs
//! ```
//!
//! Example `config.toml`:
//!
//! ```toml
//! [build]
//! target = "/usr/local/mu_library/mu/script/rust/riscv64imfdxmetis-unknown-none-elf.json"
//!
//! [target.riscv64imfdxmetis-unknown-none-elf]
//! linker = "/usr/local/mu_library/mu_llvm/llvm-18.1/bin/ld.lld"
//! rustflags = [
//! # "-C", "opt-level=1", # required in debug build
//! # "-C", "debuginfo=2",
//! "-C", "link-args=-L/usr/local/mu_library/mu_llvm/llvm-18.1/picolibc-rv/newlib",
//! "-C", "link-args=-T/usr/local/mu_library/mu/script/mu_linker.ld",
//! "-C", "link-args=-L/usr/local/mu_library/mu/lib",
//! "-C", "link-args=-lmu_std",
//! # "-A", "warnings",
//! ]
//!
//! # [env]
//! # MU_LLVM_PATH = "/usr/local/mu_library/mu_llvm/llvm-18.1"
//! # MU_LIB_PATH = "/usr/local/mu_library/mu"
//! ```
//! **⚠️ Important:** `opt-level=1` is required for debug builds to ensure proper functionality.
//!
//! ```toml
//! [dependencies]
//! mu_macro = ">=0.1.3" // specify the version you want
//! mu_lib = ">=0.2.0" // specify the version you want
//! ```
//!
//! #### 2.2 Using Direct Build Command or CMake Integration
//!
//! Instead of using `.cargo/config.toml`, you can directly set all necessary environment variables in the build command:
//!
//! ##### Direct shell command:
//!
//! ```bash
//! RUSTFLAGS="-C opt-level=1 \ # Required for debug builds
//! -C link-args=-T${mu_lib_path}/script/mu_linker.ld \
//! CARGO_TARGET_RISCV64IMFDXMETIS_UNKNOWN_NONE_ELF_LINKER=${mu_llvm_path}/bin/ld.lld \
//! cargo +nightly-1.86.0-x86_64-unknown-linux-gnu build ${build_profile} \
//! -Z build-std=core,alloc \
//! --target=${mu_lib_path}/script/riscv64imfdxmetis-unknown-none-elf.json
//! ```
//! **Make sure to update all paths** (`rustc`, linker, libraries, etc.) according to your environment.
//! > **Note:** Avoid using `--extern` flags for `mu_macro` and `mu_lib` to prevent duplicate core library build errors.
//! > Use them only if you are linking to locally built versions.
//! > If you are using published crates from `crates.io`, declare them in `Cargo.toml` instead.
//!
//! ##### CMake integration:
//!
//! ```cmake
//! cmake_minimum_required(VERSION 3.11)
//! project(sort_kernel_rs)
//!
//! set(rust_flags "-C opt-level=1 \ # Required for debug builds
//! -C link-args=-T${MU_LIB_PATH}/script/mu_linker.ld" )
//! add_custom_target(${PROJECT_NAME} ALL
//! COMMAND ${CMAKE_COMMAND} -E env /bin/bash -l -c "cargo clean"
//! COMMAND ${CMAKE_COMMAND} -E env
//! MU_LIB_PATH=${MU_LIB_PATH}
//! RUSTFLAGS=${rust_flags}
//! CARGO_TARGET_RISCV64IMFDXMETIS_UNKNOWN_NONE_ELF_LINKER=${MU_LLVM_PATH}/bin/ld.lld
//! /bin/bash -l -c "cargo +nightly-1.86.0-x86_64-unknown-linux-gnu build -Z build-std=core,alloc --target=${MU_LIB_PATH}/script/rust/riscv64imfdxmetis-unknown-none-elf.json"
//! WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
//! )
//! ```
//!
//! ### 3. Kernel Code Example
//!
//! ```rust
//! #![no_main]
//! #![no_std]
//!
//! use mu_macro::mu_kernel;
//!
//! extern crate alloc;
//! use mu_lib::{host_println, uart_println};
//!
//! #[mu_kernel]
//! pub fn print_test_kernel(i: i32) {
//! uart_println!("uart_println i = {}, i + 1 = {}, i + 2 = {}", i, i + 1, i + 2);
//! host_println!("host_println i = {}, i + 1 = {}, i + 2 = {}", i, i + 1, i + 2);
//! }
//! ```
//!
//! ### 4. Building the Kernel
//!
//! ```bash
//! MU_LIB_PATH=${mu_lib_path}
//! MU_LLVM_PATH=${mu_llvm_path} # Or provide as an environment variable
//! RUSTFLAGS="-C opt-level=1 -C link-args=-T${MU_LIB_PATH}/script/mu_linker.ld"
//! CARGO_TARGET_RISCV64IMFDXMETIS_UNKNOWN_NONE_ELF_LINKER=${MU_LLVM_PATH}/bin/ld.lld
//! cargo +nightly-1.86.0-x86_64-unknown-linux-gnu build --${build_profile} \
//! -Z build-std=core,alloc \
//! --target=${mu_lib_path}/script/riscv64imfdxmetis-unknown-none-elf.json
//! ```
//!
//! The resulting binary will be located at:
//!
//! ```text
//! target/riscv64imfdxmetis-unknown-none-elf/${build_profile}/myMuKernel
//! ```
//!
//! Rename it to `myMuKernel.mubin` and provide it to your host-side loader or simulator.
//!
//! ## Safety
//!
//! This library contains unsafe code that interfaces with the system. While the Rust interface
//! provides safe abstractions, users should be aware of the underlying system requirements and
//! constraints.
extern crate alloc;