8 releases

0.1.7 Apr 29, 2025
0.1.6 Apr 17, 2025
0.1.4 Mar 12, 2025
0.1.0 Feb 24, 2025

#1 in #atomic-swap

Download history 104/week @ 2025-02-19 101/week @ 2025-02-26 269/week @ 2025-03-05 203/week @ 2025-03-12 59/week @ 2025-04-09 206/week @ 2025-04-16 67/week @ 2025-04-23 62/week @ 2025-04-30

394 downloads per month

Apache-2.0

79KB
1.5K SLoC

MU Library - Rust Bindings

This Rust library provides a safe and idiomatic interface to the core MU Library, which is written in C++. It includes essential functionalities for developing with Rust in the MU programming environment.

Overview

rust mu_lib wraps various hardware and system features of the MU system, making them easily accessible from Rust code. It aims to enhance development productivity by ensuring memory safety and leveraging Rust's type system and error handling mechanisms.

Requirements

The MU Rust compiler is based on rustc 1.79.0, so it is recommended to use this version.

Key Features

  • Safe Rust bindings for all system operations
  • Thread-safe atomic operations
  • Comprehensive logging system
  • Task management utilities
  • System clock access
  • Message passing capabilities

Build

cargo build

lib.rs:

mu_lib

mu_lib version 0.1.6 and mu_macro version 0.1.2 or higher are considered stable.
Please use these versions or above to ensure compatibility.

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.

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.

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 = "riscv64imfdxmetis-unknown-none-elf"
rustc = "/mnt/media/mu_compiler/rust_build/x86_64-unknown-linux-gnu/stage1/bin/rustc"

[target.riscv64imfdxmetis-unknown-none-elf]
linker = "/mnt/media/mu_compiler/llvm-18.1/bin/ld.lld"
rustflags = [
    "-C", "link-args=-L/mnt/media/mu_compiler/llvm-18.1/picolibc-rv/newlib",
    "-C", "link-args=-L/mnt/media/mu_compiler/llvm-18.1/builtins-rv -lclang_rt.builtins-riscv64",
    "-C", "link-args=-T/usr/local/mu_library/mu/script/mu_linker.ld",
    "-C", "link-args=-lmu_std -L../../../../mu_lib/mu/lib",
    "-C", "target-feature=+xmetis",
    # "--extern", "mu_macro=../../../../mu_lib/mu/lib/libmu_macro.so",
    # "--extern", "mu_lib=../../../../mu_lib/mu/lib/libmu_lib.rlib",
]

Optionally, if you want to use locally built versions of mu_macro and mu_lib, add the following to your rustflags:

"--extern", "mu_macro=/path/to/libmu_macro.so", "--extern", "mu_lib=/path/to/libmu_lib.rlib",

⚠️ Use --extern only if using locally built mu_macro or mu_lib directly. If using crates from crates.io, add them to Cargo.toml instead:

[dependencies]
mu_macro = ">=0.1.2" // specify the version you want
mu_lib = ">=0.1.6" // 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:

RUSTC=${rustc_path} \
RUSTFLAGS="-C link-args=-L${mu_llvm_path}/picolibc-rv/newlib \
           -C link-args=-L${mu_llvm_path}/builtins-rv -lclang_rt.builtins-riscv64 \
           -C link-args=-T${mu_lib_path}/script/mu_linker.ld \
           -C link-args=-lmu_std -L${mu_lib_path}/lib \
           -C target-feature=+xmetis \
           # --extern mu_macro=${mu_lib_path}/lib/libmu_macro.so \ # this is also an option
           # --extern mu_lib=${mu_lib_path}/lib/libmu_lib.rlib" \ # this is also an option
CARGO_TARGET_RISCV64IMFDXMETIS_UNKNOWN_NONE_ELF_LINKER=${mu_llvm_path}/bin/ld.lld \
cargo build --release --target=riscv64imfdxmetis-unknown-none-elf

Make sure to update all paths (rustc, linker, libraries, etc.) according to your environment.

Note: The --extern flags for mu_macro and mu_lib are optional.
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 link-args=-L${MU_LLVM_PATH}/picolibc-rv/newlib \
                -C link-args=-L${MU_LLVM_PATH}/builtins-rv -lclang_rt.builtins-riscv64 \
                -C link-args=-T${MU_LIB_PATH}/script/mu_linker.ld \
                -C link-args=-lmu_std -L${MU_LIB_PATH}/lib \
                -C target-feature=+xmetis \
                --extern mu_macro=${MU_LIB_PATH}/lib/libmu_macro.so \
                --extern mu_lib=${MU_LIB_PATH}/lib/libmu_lib.rlib")

add_custom_target(${PROJECT_NAME} ALL
    COMMAND ${CMAKE_COMMAND} -E env /bin/bash -l -c "cargo clean"
    COMMAND ${CMAKE_COMMAND} -E env
        RUSTC=${RUSTC_PATH}
        RUSTFLAGS=${rust_flags}
        CARGO_TARGET_RISCV64IMFDXMETIS_UNKNOWN_NONE_ELF_LINKER=${MU_LLVM_PATH}/bin/ld.lld
        /bin/bash -l -c "cargo build --release --target=riscv64imfdxmetis-unknown-none-elf"
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

3. Kernel Code Example

#![no_main]

extern crate mu_macro;
use mu_macro::mu_kernel;

extern crate mu_lib;
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

cargo build --release
# or
cargo build

The resulting binary will be located at:

target/riscv64imfdxmetis-unknown-none-elf/release/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.

No runtime deps

~0–2MB
~38K SLoC