Reading RISC-V CSR

I'm a Rust noob and trying to get started in embedded systems. I'm using the HiFive1 RevB micro controller and trying to read the misa register then print it out over UART. Using an example from the RISC-V Rust quick start guide This is what I've got so far. Any help is appreciated.
riscv register crate reference

#![no_std]
#![no_main]

extern crate panic_halt;

use riscv_rt::entry;
use hifive1::hal::prelude::*;
use hifive1::hal::DeviceResources;
use hifive1::{sprintln, pin};
use riscv::register::*;

#[entry]
fn main() -> ! {
    let dr = DeviceResources::take().unwrap();
    let p = dr.peripherals;
    let pins = dr.pins;

    // Configure clocks
    let clocks = hifive1::clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());

    // Configure UART for stdout
    hifive1::stdout::configure(p.UART0, pin!(pins, uart0_tx), pin!(pins, uart0_rx), 115_200.bps(), clocks);

    //Read the misa CSR to see all implemented extensions
    let ext = riscv::register::misa.read();  //pretty sure this isn't right
    sprintln!({},ext);

    loop {}
}

It would help to know what compile or runtime errors you're running into.

Note that misa::read returns an Option<Misa>, which is None if the read value is 0 so if you want to print the raw value of the register you'd have to unwrap it and call .bits(), so e.g.

to sprintln!("{}", ext.map_or(0, |v| v.bits()));

1 Like

Thanks for the reply @vmedea These are the build errors

error[E0423]: expected value, found module `riscv::register::misa`
  --> examples/read_extensions.rs:25:15
   |
25 |     let ext = riscv::register::misa.read();
   |               ^^^^^^^^^^^^^^^^^^^^^-----
   |               |
   |               help: use the path separator to refer to an item: `riscv::register::misa::read`

warning: unused import: `riscv::register::misa`
  --> examples/read_extensions.rs:10:5
   |
10 | use riscv::register::misa;
   |     ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(unused_imports)]` on by default

error: language item required, but not found: `eh_personality`

error: aborting due to 2 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0423`.
error: could not compile `zero-risc`.

Did you try what the nice compiler error suggested?

Use riscv::register::misa::read not riscv::register::misa.read

I did have an error and this fixed it

let ext = riscv::register::misa::read();

but i still can't get the import to work

warning: unused import: `riscv::register::misa`
  --> examples/read_extensions.rs:10:5
   |
10 | use riscv::register::misa;
   |     ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(unused_imports)]` on by default

error: language item required, but not found: `eh_personality`

That 'use' statement is probably working just fine.

The warning only says you are not using what it imports.

Which is true because you are calling:

let ext = riscv::register::misa::read();

Which does not use the import. Instead of just :

let ext = read();

Which would.

But you have an error about "not found: eh_personality" which is a different issue.

I have no idea but others have seen this. Perhaps this will help:
https://github.com/rust-embedded/embedonomicon/issues/43

I finally got it to compile

#![no_std]
#![no_main]

extern crate panic_halt;

use riscv_rt::entry;
use hifive1::hal::prelude::*;
use hifive1::hal::DeviceResources;
use hifive1::{sprintln, pin};
use riscv::register::{misa};

#[entry]
fn main() -> ! {
    let dr = DeviceResources::take().unwrap();
    let p = dr.peripherals;
    let pins = dr.pins;

    // Configure clocks
    let clocks = hifive1::clock::configure(p.PRCI, p.AONCLK, 320.mhz().into());

    // Configure UART for stdout
    hifive1::stdout::configure(p.UART0, pin!(pins, uart0_tx), pin!(pins, uart0_rx), 115_200.bps(), clocks);

    //Read the misa CSR to see all implemented extensions
    let ext = misa::read();
    sprintln!("MISA register contents: {}", ext.map_or(0, |v| v.bits()));

    loop {}
}

The personality error came from the toml file. I cloned the quickstart github again then added my program and it built fine. Now to upload... Thanks!

Could someone walk me through this line?

.map(…) can change data in Option, if it exists, without having to unwrap and wrap it again.

map_or(default value, …) is a shortcut for map(…).unwrap_or(default value).

3 Likes

Appreciate the help everyone. I built and uploaded the program with success. The MISA register details all of the extensions available on a particular RISC-V implementation. bits 0-25 correspond to A-Z. The register read as
MISA register contents: 1074794757
It printed as a decimal number, which converted binary means that the HiFive1 Rev B uses the following extensions: IMACU (RV32 base ISA, multiply/divide, atomic, compressed, and user mode implemented)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.