riscv32 qemu rt-thread

riscv32 qemu rt-thread的最小移植实现(1) - bigmagic的个人空间 - OSCHINA - 中文开源技术交流社区

riscv32 qemu rt-thread的最小移植实现(1)

2021-02-08阅读 3070

riscv32 qemu rt-thread的最小移植实现(1)

Booting RISC-V on QEMU | Juraj’s Blog

  • 1.说明
  • 2.工具准备
    • 2.1 安装riscv32交叉编译工具链
    • 2.2 安装qemu
    • 2.3 获取rt-thread的代码
  • 3.移植整体思路规划
  • 4.riscv32工程模板的构建
  • 5.代码正常的跳转
  • 6.栈帧布局设计
  • 7.本文小结

1.说明

本文主要梳理riscv32在qemu的移植过程,将通过几天时间将其整理和最小系统的bring up。为了保证代码的可维护性,所有修改符合rt-thread bsp制作规范。目标就是riscv32 qemu 上运行rt-thread。以RT-Thread v4.0.3 released为工程代码的基线,进行开发移植工作。

2.工具准备

目前在Ubuntu20.04上面进行开发调试工作,需要下载qemu,riscv的交叉编译工具链即可。

qemu的可以到官网上下载https://www.qemu.org/

编译和运行环境在Ubuntu20.04平台上。

2.1 安装riscv32交叉编译工具链

Install RISC-V toolchains

$ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain 

国内下载地址,每天更新一次
#git clone --recursive [email protected]:mirrors/riscv-gnu-toolchain.git

$ cd riscv-gnu-toolchain/
$ mkdir build && cd build
$ ../configure --prefix=/opt/riscv --enable-multilib
$ sudo make
$ export PATH=$PATH:/opt/riscv/bin

编译和下载过程很慢,可以直接下载直接编译好的

https://www.sifive.com/software

然后导入环境变量

export PATH=/xxxx/riscv64-unknown-elf-gcc-8.3.0-2020.04.0-x86_64-linux-ubuntu14/bin/:$PATH

设置完成后,在该终端可以生效。

2.2 安装qemu

首先需要下载qemu,可以到qemu的官网上下载。

https://www.qemu.org/

可选择最新版本下载即可。

解压后进入qemu-5.2

$ ./configure --target-list=riscv32-softmmu
$ make
$ sudo make install

可以输入qemu-system-riscv32 --version验证是否成功。

2.3 获取rt-thread的代码

RT-Thread v4.0.3 released为基线,进行riscv32 qemu开发工作的代码已经推到gitee上。

https://gitee.com/bigmagic/riscv32_rtt.git

不定时持续推进开发工作。

3.移植整体思路规划

第一阶段的任务是将riscv32最小系统在qemu-system-riscv32上bring up起来,第二阶段会考虑将其适配到具体的硬件平台上。

对于第一阶段的任务划分,规划如下:

1.riscv32工程模板的构建

输出目标:工程编译正常

该工作主要适配scons工程、目录结构、编译脚本,链接脚本、文件组织。

2.代码正常跳转

输出目标:可以通过gdb跟踪代码运行

该工作主要整理底层汇编代码,对芯片的状态进行设置,让其正常执行C代码

3.串口输出rt-thread logo

输出目标:可以看到rt-thread logo正常输出

该工作适配opensbi的服务函数,通过ecall系统调用使用M-Mode的终端输出

4.栈帧布局

输出目标:可以正常进行压栈和出栈操作,并可进入main函数

该工作主要对现场栈的存放布局以及恢复进行设计

5.中断设计和定时器正常

输出目标:定时器可以正常的工作

该工作主要在于对定时器和中断外设的理解。

6.串口输入

输出目标:系统可以正常响应命令

该工作测试系统的整体移植情况。

通过上述6个里程碑将任务进行细化,每个节点的目标明确,工作内容明确,节点与节点之间环环相扣,可以作为测试的依据。

4.riscv32工程模板的构建

rt-thread是以scons脚本进行编译和链接的,所以在制作bsp时需要依据scons的构建规则进行统筹规划。

可以根据之前的

https://gitee.com/bigmagic/riscv64_rtt

工程进行修改和整理,只留下必要的文件即可。并且移除掉其他无关的bsp以减少工程项目体积。

首先,在bsp目录添加一个riscv32-virt的bsp包。

最简单的工程只需要包括

1.scons构建的必须文件

Sconscript、SConstruct

2.menuconfig配置文件

Kconfig

3.链接脚本文件

link.lds

4.rtt配置文件

.config、rtconfig.h

5.编译脚本

rtconfig.py

接着在libcpu/risc-v下新建一个virt目录。

上述目录结构基本是这样。接着就需要进行设计将代码能够正常的编译通过。

不改变其他工程代码,经过一些列的调整,将代码能够通过scons编译即可。

5.代码正常的跳转

如果要代码正常的运行起来,主要需要注意的是目前qemu上运行riscv32的代码是在S-Mode,所以修改部分代码。

首先可以在BSP的Kconfig中添加一个宏定义

因为目前libcpu\risc-v\common基本上都是实现的M-Mode下的操作,所以部分逻辑需要进行调整。

修改代码libcpu/risc-v/common/context_gcc.S, S-Mode中断的屏蔽与使能:

执行运行脚本,就可以看到rt-thread的logo正常的执行起来了。

qemu-system-riscv32 -M virt -kernel rtthread.elf -nographic

效果如下所示:

6.栈帧布局设计

在rt-thread中,栈的出和入的顺序十分重要,这里需要非常的清楚。

与操作系统来说,在调度器还没开始工作时,线程首先会被压入栈空间中。

也就是会执行rt_hw_stack_init函数。每个线程在创建的时候,都会将寄存器压入到栈顶,因为目前是S-Mode,所以需要将寄存器进行修改。

将将入栈寄存器还是按照这种方式进行,主要改动的地方如下:

另外就是压入:

出栈则是与压栈一一对应的关系。

libcpu/risc-v/common/context_gcc.S

也就是将该文件下所有的M-Mode下的寄存器,替换成S-Mode下的寄存器即可。

替换完成后,入栈出栈顺序就可以对应上了,然后开始测试代码。

OK!此时已经可以看到任务正常的切换了。

7.本文小结

实验进行到这里已经基本搭建完成系统的骨架,系统的后续还有几件事比较麻烦:

  • 中断
  • 串口终端输入
  • 系统定时器

这三块也是riscv架构中最核心与最复杂的部分,会单独用一篇文章分析其设计和使用,文章中代码实现已经提交至

https://gitee.com/bigmagic/riscv32_rtt

代码部分还有一些细节需要完善,但目前第一阶段主要以bring up为首要目标,后续会在第二篇文章专门描述中断、串口输出、系统定时器、三者在不同架构的设计与rt-thread的之间的处理逻辑。也会在近期选择riscv32的硬件平台进行选型以及移植测试。

你可能感兴趣的:(RISC-V,linux,ubuntu,git,linux)