rumio
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};
struct Mstatus;
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) {
rumio::impl_cpu_set!(Self, mask);
}
#[inline]
fn clear(mask: usize) {
rumio::impl_cpu_clear!(Self, mask);
}
}
rumio::define_cpu_register! { Mstatus as usize =>
rw UIE: 0,
rw SIE: 1,
rw MIE: 3,
r MPP: 11..12 = enum PrivilegeMode [
User = 0b00,
Supervisor = 0b01,
Machine = 0b11,
],
rw FLAGS: 13..16 = flags CpuFlags [
A = 0b0001,
B = 0b0010,
C = 0b0100,
D = 0b1000,
],
}
}
mstatus::modify(mstatus::UIE::SET | mstatus::SIE::SET | mstatus::MIE::SET);
println!("Trap was taken from {:?}", mstatus::MPP::get());
Defining MMIO registers
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,
}
}
let mmio = unsafe { Device::new(0xF00D_BABE) };
let one = mmio.one();
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.