[][src]Crate fomu_rt

Minimal startup / runtime for RISC-V Fomu CPU

Minimum Supported Rust Version (MSRV)

This crate is guaranteed to compile on stable Rust 1.31 and up. It might compile with older versions but that may change in any new patch release.


This crate provides

  • Before main initialization of the .bss and .data sections.

  • #[entry] to declare the entry point of the program

  • #[pre_init] to run code before static variables are initialized

  • A linker script that encodes the memory layout of a generic RISC-V microcontroller. This linker script is missing some information that must be supplied through a memory.x file (see example below). This file must be supplied using rustflags and listed before link.x. Arbitrary filename can be use instead of memory.x.

  • A _sheap symbol at whose address you can locate a heap.

$ cargo new --bin app && cd $_

$ # add this crate as a dependency
$ edit Cargo.toml && cat $_
fomu-rt = "0.0.1"
panic-halt = "0.2.0"

$ edit src/main.rs && cat $_
This example is not tested

extern crate panic_halt;

use fomu_rt::entry;

// use `main` as the entry point of this application
// `main` is not allowed to return
fn main() -> ! {
    // do something here
    loop { }
$ mkdir .cargo && edit .cargo/config && cat $_
rustflags = [
  "-C", "link-arg=-Tlink.x",

target = "riscv32i-unknown-none-elf"
$ cargo build

$ riscv32-unknown-elf-objdump -Cd $(find target -name app) | head

Disassembly of section .text:

20000000 <_start>:
20000000:	800011b7          	lui	gp,0x80001
20000004:	80018193          	addi	gp,gp,-2048 # 80000800 <_stack_start+0xffffc800>
20000008:	80004137          	lui	sp,0x80004

Symbol interfaces

This crate makes heavy use of symbols, linker sections and linker scripts to provide most of its functionality. Below are described the main symbol interfaces.


extern crate some_allocator;

extern "C" {
    static _sheap: u8;
    static _heap_size: u8;

fn main() {
    unsafe {
        let heap_bottom = &_sheap as *const u8 as usize;
        let heap_size = &_heap_size as *const u8 as usize;
        some_allocator::initialize(heap_bottom, heap_size);


This function is called from all the harts and must return true only for one hart, which will perform memory initialization. For other harts it must return false and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt).

This function can be redefined in the following way:

#[export_name = "_mp_hook"]
pub extern "Rust" fn mp_hook() -> bool {
   // ...

Default implementation of this function wakes hart 0 and busy-loops all the other harts.



Rust entry point (_start_rust)


Trap entry point rust (_start_trap_rust)

Attribute Macros


Attribute to declare the entry point of the program


Attribute to mark which function will be called at the beginning of the reset handler.