Embedded Rust: Converting C to Rust

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!

Links
https://github.com/sifive/freedom-metal/blob/v201908-branch/src/pmp.c

https://github.com/sifive/example-pmp/blob/57e15fee6a1dbbb06f0f615892488090a0b05d26/example-pmp.c

1 Like

Code with inline asm is not allowed by stable Rust (only nightly), and it's not something that Rust can guarantee to be safe anyway.

If it wasn't for asm, you could try c2rust as a starting point.

I suggest wrapping the C code like a sys crate and building it with the cc crate.

1 Like

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

2 Likes

Thanks, I will write a test program and debug it to see if it worked correctly. I will report back with results.

@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).

Unfortunately I can't advise on embedded/RISC-V.

4 Likes

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.

edit: FWIW, there is a board support crate for the hifive1 and a HAL for its e310x SoC. Unless you are somehow required to do everything from scratch, this might make things easier, or can at least be an example.

3 Likes

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.

1 Like

Thank you for the suggestion. I will review the link and hopefully get a better understanding.

A lot of folks are saying "never", but there's actually been more movement in this space recently than in years. An RFC was accepted to rename asm to llvm_asm as a means of stabilizing asm with a transitional path for existing code. A project group was started and has produced an rfc for asm with a path to stabilization, as well as an implementation.

We cannot say if this will be the final design, nor when it will be stable, but we're closer now than we ever have been.

4 Likes

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.

Thanks for the info, that's great news!

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

No need to write your own assembly code for this.

1 Like

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?

Yes, that's correct, I don't know at which version the particular registers were added but specifying 0.5.6 will do.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.