当前位置:   article > 正文

Renode:第一个RISC-V裸机demo_metal riscv

metal riscv

在Renode上跑通了一个裸机(baremetal)demo,记录一下过程,为后面的进一步开发做铺垫。

该Demo来自国外一个大神的代码仓库:https://github.com/y2kbugger/baremetal-riscv-renode

有兴趣的同学可以自行下载。

1. 准备工作

1.1 Renode安装

由于我们使用Renode作为仿真平台,因此首先需要完成Renode的安装。以上代码仓库中包含了所有的工程组件,包括Renode源码、RISC-V工具链源码,以及编译所需组件的Makefile,但是实际使用中,可能会出错,所以我选择逐项安装。

Renode的安装在之前的文章里面已经介绍过,在本Demo中可以直接使用,安装方法见之前的博客:初识Renode_牧羊女-CSDN博客

1.2 RISC-V toolchain安装

要想在x86平台上编译RISC-V的binaries,首先需要安装交叉编译工具。针对该Demo的需要,我们只需要安装riscv32-unknown-elf-gcc套件即可,之前的文章我们也介绍了riscv32-unknown-elf-gcc的编译安装过程:编译riscv32-unknown-elf-gcc_牧羊女-CSDN博客

2. 硬件组成和软件代码

该Demo非常简单,堪称嵌入式界的“Hello World”,功能是让一个虚拟LED闪烁。该Demo使用的硬件及软件代码见下面描述。

2.1 硬件组成

Demo使用的硬件组成非常简单,包括一块很小的memory、一个RISC-V CPU、一个GPIO以及两个LED,如下面平台描述文件(vexriscv.repl)所示:

  1. mem: Memory.MappedMemory @ sysbus 0x0
  2. size: 0x00040000
  3. cpu: CPU.VexRiscv @ sysbus
  4. gpio_out: GPIOPort.LiteX_GPIO @ sysbus 0x60000800
  5. type: Type.Out
  6. 0 -> led0@0
  7. 1 -> led1@0
  8. led0 : Miscellaneous.LED @ gpio_out 0
  9. led1 : Miscellaneous.LED @ gpio_out 1

关于平台描述文件的介绍,见前面的文章: Renode学习:平台描述文件REPL_牧羊女-CSDN博客

2.2 源代码

该Demo的软件代码(baremetal.s)为汇编语言,但也很简单,按照我有限的理解加了一点注释,如下:

  1. #这段有点像C中的宏定义哈
  2. .equ LED, 0x60000800
  3. .equ DELAY_COUNT, 9000000
  4. .equ LED_STATE_INITIAL, 0b00
  5. .equ LED_STATE_TOGGLE_MASK, 0b01
  6. .section .text #定义文本段
  7. .global _start #定义_start为外部程序可访问的标签,类似于我们常用的main()函数
  8. _start:
  9. li a5, LED # 将上面LED表示的值加载到a5寄存器
  10. li a4, LED_STATE_INITIAL # 同上,li为加载立即数指令
  11. li a6, LED_STATE_TOGGLE_MASK
  12. sw a4, 0x0(a5) # store word,将寄存器一个word大小的值存入堆栈,0x0为offset
  13. loop:
  14. li a0, DELAY_COUNT # reset counter
  15. delay_loop:
  16. addi a0, a0, -1 # count down
  17. bnez a0, delay_loop # 条件转移指令,不为0时发生
  18. toggle_led:
  19. lw a4, 0x0(a5) # read in old led state
  20. xor a4, a4, a6 # toggle led state word
  21. sw a4, 0x0(a5) # write new state
  22. jump loop, t0

3. 编译、运行

工程的运行需要三个步骤,分别是:

(1) 从源码baremetal.s中编译出目标二进制文件;

(2) 启动由以上REPL平台描述文件定义的硬件模拟环境;

(3) 将步骤(1)中编译出的elf文件加载到平台模拟器的内存中。

3.1 编译目标文件

目标文件的编译命令行如下:

riscv32-unknown-elf-gcc baremetal.s -ggdb -O0 -o image -ffreestanding -nostdlib

其中,

  • riscv32-unknown-elf-gcc为我们在1.2中编译安装的risc-v交叉编译器;
  • baremetal.s为软件源码,以上已有介绍;
  • -ggdb,使能GDB调试;
  • -o image,指定输出elf二进制文件的名称为“image”,可根据自己需要自由修改;
  • -ffreestanding,不使用main函数,不假定操作系统的存在;
  • -nostdlib,不依赖C标准库。

执行完以上编译命令后,会生成目标ELF文件image:

3.2 仿真脚本

Renode有一个非常方便的地方,就是可以通过一个RESC脚本将所有的步骤串联起来执行,而无需用户在命令行窗口中逐个输入命令,这就大大简化了我们的仿真操作步骤。

工程的仿真脚本(vexriscv.resc)如下:

  1. :name: 1_blinky_VexRiscv
  2. :description: Loader for the baremetal-riscv-renode project example 1 "blinky"
  3. $name?="vexriscv-machine"
  4. using sysbus
  5. mach create $name
  6. machine LoadPlatformDescription @vexriscv.repl
  7. sysbus LoadELF @image
  8. machine StartGdbServer 3333
  9. logLevel -1 sysbus.gpio_out.led0
  10. logLevel -1 sysbus.gpio_out.led1
  11. start

关于脚本中命令的介绍,见之前的文章:Renode学习:Working with machines_牧羊女-CSDN博客 

3.3 运行

代码仓库中已经将运行命令也集成到了Makefile文件中,所以我们只需要执行make launch即可使demo运行起来。

Makefile文件如下:

  1. image: baremetal.s
  2. riscv32-unknown-elf-gcc baremetal.s -ggdb -O0 -o image -ffreestanding -nostdlib
  3. launch: image
  4. renode vexriscv.resc
  5. debug:
  6. riscv32-unknown-elf-gdb -x gdbrc
  7. clean:
  8. rm image

运行界面如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/940024
推荐阅读
相关标签
  

闽ICP备14008679号