Skip to content

Control your MMIO and CPU registers without pain using Rust.

License

Unknown, MIT licenses found

Licenses found

Unknown
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

Stupremee/rumio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rumio

Crates.io Documentation

Control your MMIO and CPU registers without pain.

Documentation | Crate | Examples

This crate provides various macros to generate a nice API for MMIO blocks and CPU registers. It's mainly meant as a replacement for the register crate to provide a better API and make the work easier.

Usage

For more updated and larger examples take a look at the tests.

Defining CPU registers

The CPU registers are only useful for control registers which store their data using bitfields. For example the Control-Status-Register of the RISC-V architecture.

#![feature(asm)]

mod mstatus {
  use rumio::cpu::{RegisterRead, RegisterWrite};

  // first we need to define a register, and a way to read/write to it.
  // we will use the `mstatus` CSR from the RISC-V architecture as an example
  struct Mstatus;

  // the `usize` argument indicates the underyling value of the register.
  impl RegisterRead<usize> for Mstatus {
      #[inline]
      fn read() -> usize {
          let reg;
          unsafe { asm!("csrr {}, mstatus", out(reg) reg) }
          reg
      }
  }

  impl RegisterWrite<usize> for Mstatus {
      #[inline]
      fn write(val: usize) {
          unsafe { asm!("csrw mstatus, {}", in(reg) val) }
      }

      #[inline]
      fn set(mask: usize) {
          // `impl_cpu_set` and `impl_cpu_clear` can generated `set` and `clear`
          // by performing a read, setting the bits and then write the value again.
          rumio::impl_cpu_set!(Self, mask);
      }

      #[inline]
      fn clear(mask: usize) {
          rumio::impl_cpu_clear!(Self, mask);
      }
  }

  // now define the different bits and fields of this register
  rumio::define_cpu_register! { Mstatus as usize =>
    /// Globally enables interrupts in U-Mode.
    rw UIE: 0,
    /// Globally enables interrupts in S-Mode.
    rw SIE: 1,
    /// Globally enables interrupts in M-Mode.
    rw MIE: 3,

    /// The privilege mode a trap in M-Mode was taken from.
    r MPP: 11..12 = enum PrivilegeMode [
      User = 0b00,
      Supervisor = 0b01,
      Machine = 0b11,
    ],

    /// This is not an actual flag of the `mstatus` register, but
    /// we add it here for showing the usage of `flags`
    rw FLAGS: 13..16 = flags CpuFlags [
      A = 0b0001,
      B = 0b0010,
      C = 0b0100,
      D = 0b1000,
    ],
  }
}

// the generated api then can be used like this.
// to explore the full api generated by this macro, check the `example_generated`
// module on docs.rs, and check the examples (the tests are the examples)

mstatus::modify(mstatus::UIE::SET | mstatus::SIE::SET | mstatus::MIE::SET);
println!("Trap was taken from {:?}", mstatus::MPP::get());

Defining MMIO registers

// define one MMIO register whose base type is `u16` and name is `Reg`.
rumio::define_mmio_register! {
    Reg: u16 {
        rw MODE: 0..1 = enum Mode [
            A = 0b00,
            B = 0b01,
            C = 0b10,
            D = 0b11,
        ],

        r FOO: 2,

        rw BAR: 3,
        rw BAZ: 4,

        rw FLAGS: 5..8 = flags Flags [
            A = 0b0001,
            B = 0b0010,
            C = 0b0100,
            D = 0b1000,
        ],
    }
}

rumio::define_mmio_struct! {
    pub struct Device {
        (0x00 => one: Reg),
        (0x08 => two: Reg),
    }
}

// create a new `Device` at address `0xF00D_BABE
let mmio = unsafe { Device::new(0xF00D_BABE) };

// access the `one` register
let one = mmio.one();

// now `one` can be used similarly to the cpu register
one.MODE().set(Mode::B);
one.FLAGS().set(Flags::B | Flags::C);

one.modify(Mode::A | BAR::SET);

License

Licensed under either Apache License or the MIT license.

About

Control your MMIO and CPU registers without pain using Rust.

Resources

License

Unknown, MIT licenses found

Licenses found

Unknown
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

No packages published