riscv bare-metal c

17 篇文章 6 订阅



riscv - How can I compile C code to get a bare-metal skeleton of a minimal RISC-V assembly program? - Stack Overflow

riscv64 裸机编程实践与分析 - 云+社区 - 腾讯云

I have the following simple C code:

   void main(){
    int A = 333;
    int B=244;
    int sum;
    sum = A + B;  
}

When I compile this with

$riscv64-unknown-elf-gcc code.c -o code.o

If I want to see the assembly code I use

$riscv64-unknown-elf-objdump -d code.o 

But when I explore the assembly code I see that this generates a lot of code which I assume is for Proxy Kernel support (I am a newbie to riscv). However, I do not want that this code has support for Proxy kernel, because the idea is to implement only this simple C code within an FPGA.

I read that riscv provides three types of compilation: Bare-metal mode, newlib proxy kernel and riscv Linux. According to previous research, the kind of compilation that I should do is bare metal mode. This is because I desire a minimum assembly without support for the operating system or kernel proxy. Assembly functions as a system call are not required.

However, I have not yet been able to find as I can compile a C code for get a skeleton of a minimal riscv assembly program. How can I compile the C code above in bare metal mode or for get a skeleton of a minimal riscv assembly code?

17

Warning: this answer is somewhat out-of-date as of the latest RISC-V Privileged Spec v1.9, which includes the removal of the tohost Control/Status Register (CSR), which was a part of the non-standard Host-Target Interface (HTIF) which has since been removed. The current (as of 2016 Sep) riscv-tests instead perform a memory-mapped store to a tohost memory location, which in a tethered environment is monitored by the front-end server.


If you really and truly need/want to run RISC-V code bare-metal, then here are the instructions to do so. You lose a bunch of useful stuff, like printf or FP-trap software emulation, which the riscv-pk (proxy kernel) provides.

First things first - Spike boots up at 0x200. As Spike is the golden ISA simulator model, your core should also boot up at 0x200.

(cough, as of 2015 Jul 13, the "master" branch of riscv-tools (https://github.com/riscv/riscv-tools) is using an older pre-v1.7 Privileged ISA, and thus starts at 0x2000. This post will assume you are using v1.7+, which may require using the "new_privileged_isa" branch of riscv-tools).

So when you disassemble your bare-metal program, it better start at 0x200!!! If you want to run it on top of the proxy-kernel, it better start at 0x10000 (and if Linux, it’s something even larger…).

Now, if you want to run bare metal, you’re forcing yourself to write up the processor boot code. Yuck. But let’s punt on that and pretend that’s not necessary.

(You can also look into riscv-tests/env/p, for the “virtual machine” description for a physically addressed machine. You’ll find the linker script you need and some macros.h to describe some initial setup code. Or better yet, in riscv-tests/benchmarks/common.crt.S).


Anyways, armed with the above (confusing) knowledge, let’s throw that all away and start from scratch ourselves...

hello.s:
 .align 6
 .globl _start
 _start:
 # screw boot code, we're going minimalist
 # mtohost is the CSR in machine mode
 csrw mtohost, 1;
 1:
 j 1b

and link.ld:

 OUTPUT_ARCH( "riscv" )
 ENTRY( _start )
 SECTIONS
 {
 /* text: test code section */
 . = 0x200;
 .text :
 {
 *(.text)
 }
 /* data: Initialized data segment */
 .data :
 {
 *(.data)
 }
 /* End of uninitalized data segement */
 _end = .;
 }

Now to compile this…

riscv64-unknown-elf-gcc -nostdlib -nostartfiles -Tlink.ld -o hello hello.s

This compiles to (riscv64-unknown-elf-objdump -d hello):

 hello: file format elf64-littleriscv

 Disassembly of section .text:

 0000000000000200 <_start>:
 200: 7810d073 csrwi tohost,1
 204: 0000006f j 204 <_start+0x4>

And to run it:

spike hello

It’s a thing of beauty.

The link script places our code at 0x200. Spike will start at 0x200, and then write a #1 to the control/status register “tohost”, which tells Spike “stop running”. And then we spin on an address (1: j 1b) until the front-end server has gotten the message and kills us.

It may be possible to ditch the linker script if you can figure out how to tell the compiler to move <_start> to 0x200 on its own.


For other examples, you can peruse the following repositories:

The riscv-tests repository holds the RISC-V ISA tests that are very minimal (https://github.com/riscv/riscv-tests).

This Makefile has the compiler options: https://github.com/riscv/riscv-tests/blob/master/isa/Makefile

And many of the “virtual machine” description macros and linker scripts can be found in riscv-tests/env (https://github.com/riscv/riscv-test-env).

You can take a look at the “simplest” test at (riscv-tests/isa/rv64ui-p-simple.dump).

And you can check out riscv-tests/benchmarks/common for start-up and support code for running bare-metal.

Share

Improve this answer

Follow

edited Sep 3 '16 at 21:16

answered Jul 13 '15 at 21:32

Chris

3,4091818 silver badges2929 bronze badges

  • Hi Chris, thank you for your answer, it was very completed. In bare metal mode I lose a bunch of stuff, like printf, but what happen if I want to use aritmetic functions in C like "pow"? Arithmetic functions like pow are inside the math library. If I compile it use $riscv-unknown-elf-gcc -nostdlib -nostartfiles -T.link.ld -o code code.c -lm, I suppose that it does not work in bare metal model. I suppose that Should I be linking this library in bare metal mode? Or what happen in this case?

    – Adrian

    Jul 14 '15 at 14:58
  • Given its high experience in risc-v, Do you recommend me better to work at the proxy kernel level when I use for example math libraries?

    – Adrian

    Jul 14 '15 at 15:08
  • I don't have experience in linking in other library functions; I suspect you'd do better to ask on some gcc/compiler forum instead (it's not really a RISC-V question). I don't think there's any reason why it wouldn't work though.

    – Chris

    Jul 15 '15 at 22:39
  • If you are going to be running your code on your own simple RISC-V processor, then I'd at least start with running bare metal. It's easier to only support M-mode and you can understand every instruction it executes.

    – Chris

    Jul 15 '15 at 22:44

Add a comment

5

The "extra" code is put there by gcc and is the sort of stuff required for any program. The proxy kernel is designed to be the bare minimum amount of support required to run such things. Once your processor is working, I would recommend running things on top of pk rather than bare-metal.

In the meantime, if you want to look at simple assembly, I would recommend skipping the linking phase with '-c':

riscv64-unknown-elf-gcc code.c -c -o code.o
riscv64-unknown-elf-objdump -d code.o

For examples of running code without pk or linux, I would look at riscv-tests.

Share

Improve this answer

Follow

answered Jul 13 '15 at 20:15

user2548418

1,46199 silver badges1616 bronze badges

Add a comment

0

I'm surprised no one mentioned gcc -S which skips assembly and linking altogether and outputs assembly code, albeit with a bunch of boilerplate, but it may be convenient just to poke around.

riscv64 裸机编程实践与分析 - 云+社区 - 腾讯云

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值