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.

```rust

![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 for Mstatus { #[inline] fn read() -> usize { let reg; unsafe { asm!("csrr {}, mstatus", out(reg) reg) } reg } }

impl RegisterWrite 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::definecpuregister! { 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

``rust // define one MMIO register whose base type isu16and name isReg`. rumio::definemmioregister! { 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::definemmiostruct! { pub struct Device { (0x00 => one: Reg), (0x08 => two: Reg), } }

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

// 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.