Expand description
§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 functionsatomic
: Provides thread-safe atomic operationsclock
: Provides system clock functionalitylogger
: Provides logging functionality with various log levelsmessage
: Provides synchronous and asynchronous message handling functionsprint
: Provides output functionality for UART, host, and general printingtask
: 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:
cargo new myMuKernel
This generates:
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:
myMuKernel/
├── Cargo.toml
├── .cargo/
│ └── config.toml
└── src/
└── main.rs
Example config.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.
[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:
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 formu_macro
andmu_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 fromcrates.io
, declare them inCargo.toml
instead.
§CMake integration:
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
#![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
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:
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.
Modules§
- assert
- Assertion module providing condition checking functionality
- atomic
- Atomic operations module providing thread-safe operations
- bindings
- clock
- Clock module providing system clock functionality
- logger
- Logger module providing logging functionality
- message
- Message handling module providing synchronous and asynchronous message operations
- ndarray
- Equivalent to
mu::ndarray::NDArray<T>
in C++ Same memory layout and API patterns - panic_
info - Print module providing output functionality
- task
- Task module providing task management functionality
Macros§
- host_
print - Macro for printing a single string to the host
- host_
println - Macro for printing a single string to the host followed by a newline
- log_
print - Macro for logging output
- log_
print_ with_ level - Macro for logging output with a specified level
- uart_
print - Macro for printing a single string to UART
- uart_
println - Macro for printing a single string to UART followed by a newline