前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >riscv32 qemu rt-thread的最小移植实现(1)

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

作者头像
bigmagic
发布2021-02-08 09:36:36
1.4K0
发布2021-02-08 09:36:36
举报
文章被收录于专栏:嵌入式iot

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

  • 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交叉编译工具链

代码语言:javascript
复制
Install RISC-V toolchains

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

国内下载地址,每天更新一次
#git clone --recursive git@gitee.com: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

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

代码语言:javascript
复制
https://www.sifive.com/software

然后导入环境变量

代码语言:javascript
复制
export PATH=/xxxx/riscv64-unknown-elf-gcc-8.3.0-2020.04.0-x86_64-linux-ubuntu14/bin/:$PATH

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

2.2 安装qemu

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

代码语言:javascript
复制
https://www.qemu.org/

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

解压后进入qemu-5.2

代码语言:javascript
复制
$ ./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上。

代码语言:javascript
复制
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的构建规则进行统筹规划。

可以根据之前的

代码语言:javascript
复制
https://gitee.com/bigmagic/riscv64_rtt

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

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

最简单的工程只需要包括

1.scons构建的必须文件

代码语言:javascript
复制
Sconscript、SConstruct

2.menuconfig配置文件

代码语言:javascript
复制
Kconfig

3.链接脚本文件

代码语言:javascript
复制
link.lds

4.rtt配置文件

代码语言:javascript
复制
.config、rtconfig.h

5.编译脚本

代码语言:javascript
复制
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正常的执行起来了。

代码语言:javascript
复制
qemu-system-riscv32 -M virt -kernel rtthread.elf -nographic

效果如下所示:

6.栈帧布局设计

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

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

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

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

另外就是压入:

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

代码语言:javascript
复制
libcpu/risc-v/common/context_gcc.S

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

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

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

7.本文小结

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

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

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

代码语言:javascript
复制
https://gitee.com/bigmagic/riscv32_rtt

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式IoT 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • riscv32 qemu rt-thread的最小移植实现(1)
    • 1.说明
      • 2.工具准备
        • 2.1 安装riscv32交叉编译工具链
        • 2.2 安装qemu
        • 2.3 获取rt-thread的代码
      • 3.移植整体思路规划
        • 4.riscv32工程模板的构建
          • 5.代码正常的跳转
            • 6.栈帧布局设计
              • 7.本文小结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档