I'm doing my senior design project on IoT security focusing on RISC-V processors and embedded Rust. I'm new to Rust, but I'm spending lots of time on learning it. The development board I'm using is the HiFive1 RevB from SiFive. My first step is to configure the physical memory protection registers. SiFive has an example program to do this, but it is written in C and has two library dependencies.
I want to use all Rust code if possible because of the memory safety features. Even if the C code is "safe" my project is focusing on Rust, so that doesn't fit the project. Should/could I convert the libraries and program into Rust? If so would the libraries become crates? Any advice is appreciated!
Im not an expert by any means, but I think I can get it to work. This code maybe be a little more than I need. All I need to do is write to some registers. For example pmpcfg0 is address 0x3A0. Is assembly the only way to write to that register, or can Rust handle that? TockOS is written in Rust and has a pmp config program. It is specific for the TockOS ,which Im going to use eventually, but for now Im starting as simple as possible. https://github.com/tock/tock/blob/master/arch/rv32i/src/pmp.rs
In Rust you can make pointers from arbitrary addresses 0x1234 as *mut u8, and you can use write_volatile to write to them (or just dereference them if it's regular memory).
@kornel I attended the Oxidize 1k event and saw your talk. This was a verying interesting event. Any who, do you have any idea on a rough time table for stable inline asm support?
Also, Im a Rust and embedded system noob. Seeing as Im working with RISC-V, could you suggest to me the best resource for learning that you are aware of? Appeciate it!
Daniel
It's unlikely that inline asm will be stable anytime soon, if ever. The current state of "just do whatever LLVM wants" is unacceptable for stabilization, because Rust wants to be backend agnostic (e.g. Cranelift).
Instead of inline assembly, most of the current CPU-specific crates have a fallback to externally compiled and linked assembly code. See for example the riscv crate.
The problem is that stabilization in Rust first requires an acceptable, generic, architecture-neutral, backend-neutral assembly syntax, with associated semantic tags to convey to whichever highly-optimizing backend the additional optimization-support information that is now conveyed from MIR to LLVM via LLVM's IR.
Such a universal generic syntax (with relevant semantics tags) seems unlikely, given the increasing diversity of hardware architectures: RISC CPUs, x86-like CPUs, VLIW CPUs like Itanium, GPUs, TPUs, etc. Consider for example the complexity of the VOP3 encodings in Chapter 6 (p. 43) of the ISA for AMD's RDNA GPUs, including the large amount of use-related semantic information that would need to be conveyed to the optimizing backend.
Addendum: That is why assembly code is likely to require separately-assembled, separately-linked modules for the foreseeable future.
Thanks for the reminder. @Amanieu has made substantial progress since I last reviewed this, particularly in the implementation. I don't recall seeing SplitInOut before (though it may have been there); it's an alternative needed for some architectures.
BTW, you cannot program RISC-V CSR registers by writing memory addresses. They're not memory-mapped but can only be accessed through specific instructions.
However, as the pmpcfg* as pmpaddr* registers are part of the RISC-V standard, there's even already code in the riscv crate to program the pmp registers. See
Nice find! That helps me out a lot. So you are saying that this is apart of the riscv crate? Looks like it, I looked at the riscv crate earlier, but I never noticed this section.
In my cargo.toml file I will have to add riscv 0.5.6 as a dependency, is that correct?