Build for FE310-G002 SoC

Now, its time to build for a specific RISC-V target. What does this mean? There can be many RISC-V target variants, though the RISC-V assembly code remains the same, the target might be 32-bit/64-bit with support for different ISA (Instruction Set Architecture) extensions (ex: RV32IMAC, RV32IMA etc) and with different memory size (both ON-Chip & OFF-Chip) & with different IO support.

As mentioned in the previous edition, HiFive1 RevB board with FE310-G002 SoC is the only hardware in my hands. So, lets build for it.

  1. Create linker for FE310-G002

Most common memory partitions are:

  • ROM - Read Only Memory

  • RAM - Random Access Memory

  • Peripheral Registers

  • External Bus Interface

  • System Control

  • Reserved

Remember the actual usable memory might differ from the memory map mentioned in the SoC data sheet.

For example, the Off-Chip Non Volatile Memory(NVM) is 512 Mebibytes(512 MiB, 1MiB = 2^ 20 bytes) in the FE310-G002 data sheet, but the actual usable memory on this SoC with Hifive1 RevB board is just 16 mebibytes as only 16MiB of memory is connected to the external bus.

Here is the simplified usable memory range & map for FE310-G002.

Memory

Start Address

Length

Size

On Chip RAM

0x80000000

0x4000

16 KiB

Off Chip NVM/Flash

0x20000000

0x1000000

16 MiB

This is enough now to link our code either to RAM or FLASH to load and execute from RAM or FLASH. Writing a linker from scratch is a different topic and don’t want to deviate. Here is the linker I wrote and lets call it hifive1-revb-ram.lscript . Please ask your questions about the linker in the comments if any.

  1. Feed fe310-g002 linker to cargo

So far the cargo workspace is not provided with any linker file. Now, its time to feed the linker to cargo so that the binary is linked with the linker hifive1-revb-ram.lscript. This can be achieved with link-args rustflags as below in .cargo/config file.

bootstrap-ws $cat .cargo/config 
[build]
target = "riscv32imac-unknown-none-elf"

rustflags = [

"-C", "link-dead-code",
"-C", "link-args=-Thifive1-revb-ram.lscript"
]

With the linker for fe310, cargo build should link symbols to the RAM memory section starting from 0×8000_0000 in the linker.

bootstrap-ws $riscv64-unknown-elf-objdump -d target/riscv32imac-unknown-none-elf/debug/execs

target/riscv32imac-unknown-none-elf/debug/execs:     file format elf32-littleriscv


Disassembly of section .text:

80000000 <rust_begin_unwind>:
80000000:	1141                	addi	sp,sp,-16
80000002:	c62a                	sw	a0,12(sp)
80000004:	a009                	j	80000006 <rust_begin_unwind+0x6>
80000006:	a001                	j	80000006 <rust_begin_unwind+0x6>

80000008 <_start>:
80000008:	8082                	ret

If no particular path is set for linker, cargo expects linker in cargo workspace root directory.

bootstrap-ws $tree
.
├── Cargo.lock
├── Cargo.toml
├── execs
│   ├── Cargo.toml
│   └── src
│       └── main.rs
├── hifive1-revb-ram.lscript
└── libs
    ├── Cargo.toml
    └── src
        └── lib.rs

Keep reading