Crate mu_lib

Crate mu_lib 

Source
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 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:

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 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_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
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