RT-Thread BSP qemu-virt64-riscv 的编译环境搭建
创始人
2025-05-30 17:40:50
0

前言

  • 最近需要使用 RT-Thread smart 开发调试一些软件功能,由于软件功能平台无关,使用实际硬件操作,会耗费较多的时间在程序烧写环节。

  • 打算使用 BSP qemu-virt64-aarch64 搭建一个 RT-Thread smart 的开发调试环境,可以开发验证一些平台无关的软件功能,但是当前的 RT-Thread smart 开放出来的 userapps 不支持 aarch64 平台。

  • 所以选择 qemu-virt64-riscv 平台进行编译环境的搭建,搭建的流程跟 qemu-virt64-aarch64 基本一致。

环境搭建

  • Win10 64位

  • VMware Workstation Pro

  • VS Code (ssh 远程)

  • ubuntu 20.04

  • RT-Thread master 最新分支: BSP qemu-virt64-riscv

下载 RT-Thread

  • 这里使用 gitee 的 RT-Thread 仓库,先通过 fork 的方式,把 RT-Thread fork 到自己的账号下

  • ubuntu 中安装好 git qemu,通过 git 克隆一份 RT-Thread 最新代码

  • 可以直接克隆 RT-Thread 官方的 git clone https://gitee.com/rtthread/rt-thread.git

scons 构建

  • 进入 rt-thread/bsp/qemu-virt64-riscv,直接 scons 可能会提示 scons 找不到,如果找不到,就安装一下 scons
zhangsz@zhangsz:~/rtt/smart/rt-thread/bsp/qemu-virt64-aarch64$ sconsCommand 'scons' not found, but can be installed with:sudo apt install scons
  • 安装 scons 的方法: $ sudo apt install scons

  • 运行 $ scons --menuconfig,进入Kconfig 图形配置界面,初步运行,会克隆 Linux 下的 RT-Thread env 工具 与 packages 软件包

在这里插入图片描述

交叉编译工具链

  • 再次运行 scons 后,发现提示找不到 gcc 交叉编译工具链, riscv64-unknown-linux-musl-gcc: not found

  • 下载工具链:可以使用 get_toolchain.py 下载,不过这个脚本默认没有在 RT-Thread 工程里面,需要手动创建一个,也可以在 userapps 仓库中 copy 一份出来,地址 https://github.com/RT-Thread/userapps

  • rt-thread/bsp/qemu-virt64-riscv 目录下,新建一个 tools 目录,然后进入这个 rt-thread/bsp/qemu-virt64-riscv/tools 目录,创建 get_toolchain.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-#
# Copyright (c) 2022, RT-Thread Development Team
#
# SPDX-License-Identifier: GPL-2.0
#
# Change Logs:
# Date           Author       Notes
# 2022-02-1      Bernard      The first version
#import os
import sys
import platformfrom ci import CItoolchains_config = {'arm':{'Linux': 'arm-linux-musleabi_for_x86_64-pc-linux-gnu_latest.tar.bz2','Windows': 'arm-linux-musleabi_for_i686-w64-mingw32_latest.zip'},'aarch64':{'Linux' : 'aarch64-linux-musleabi_for_x86_64-pc-linux-gnu_latest.tar.bz2','Windows' : 'aarch64-linux-musleabi_for_i686-w64-mingw32_latest.zip'},'riscv64':{'Linux': 'riscv64-linux-musleabi_for_x86_64-pc-linux-gnu_latest.tar.bz2','Windows': 'riscv64-linux-musleabi_for_i686-w64-mingw32_latest.zip'}
}if __name__ == '__main__':# download toolchainif len(sys.argv) > 1:target = sys.argv[1]else:target = 'arm'ci = CI()toolchain_path = os.path.join(os.path.abspath('.'), 'gnu_gcc')platform = platform.system()try:zfile = toolchains_config[target][platform]URL = 'http://117.143.63.254:9012/www/rt-smart/' + zfileexcept:print('not found target')exit(0)ci.downloadFile(zfile, URL)ci.extractZipFile(zfile, toolchain_path)ci.delFile(zfile)
  • rt-thread/bsp/qemu-virt64-riscv/tools目录下,创建一个 ci.py 脚本,因为 get_toolchain.py 依赖这个ci.py 脚本
#!/usr/bin/env python
# -*- coding: utf-8 -*-#
# Copyright (c) 2022, RT-Thread Development Team
#
# SPDX-License-Identifier: GPL-2.0
#
# Change Logs:
# Date           Author       Notes
# 2022-02-1      Bernard      The first version
#import os
import sys
import shutil
import platform
import requests
import time
import zipfileclass CI:def downloadFile(self, name, url):headers = {'Proxy-Connection':'keep-alive'}r = requests.get(url, stream=True, headers=headers)length = float(r.headers['content-length'])f = open(name, 'wb')count = 0count_tmp = 0time1 = time.time()for chunk in r.iter_content(chunk_size = 512):if chunk:f.write(chunk)count += len(chunk)if time.time() - time1 > 2:p = count / length * 100speed = (count - count_tmp) / 1024 / 1024 / 2count_tmp = countprint(name + ': ' + '{:.2f}'.format(p) + '%')time1 = time.time()print(name + ': 100%')f.close()def extractZipFile(self, zfile, folder):# self.delTree(folder)if not os.path.exists(folder):os.makedirs(folder)if platform.system() == 'Windows':zip_file = zipfile.ZipFile(zfile)zip_list = zip_file.namelist()for item in zip_list:print(item)zip_file.extract(item, folder)zip_file.close()elif platform.system() == 'Linux':if zfile.endswith('tar.gz'):os.system('tar zxvf %s -C %s' % (zfile, folder))elif zfile.endswith('tar.bz2'):os.system('tar jxvf %s -C %s' % (zfile, folder))elif zfile.endswith('.zip'):os.system('unzip %s -d %s' % (zfile, folder))returndef zipFolder(self, folder, zfile):zip_filename = os.path.join(folder)zip = zipfile.ZipFile(zfile, 'w', compression=zipfile.ZIP_BZIP2)pre_len = len(os.path.dirname(folder))for parent, dirnames, filenames in os.walk(folder):for filename in filenames:pathfile = os.path.join(parent, filename)arcname = pathfile[pre_len:].strip(os.path.sep)zip.write(pathfile, arcname)zip.close()returndef touchDir(self, d):if not os.path.exists(d):os.makedirs(d)def gitUpdate(self, url, folder, branch = 'master'):cwd = os.getcwd()if os.path.exists(folder):os.chdir(folder)os.system('git pull origin')if branch != 'master':os.system('git checkout -b %s origin/%s' % (branch, branch))os.system('git submodule init')os.system('git submodule update')else:os.system('git clone %s %s' % (url, folder))os.chdir(folder)os.system('git submodule init')os.system('git submodule update')os.chdir(cwd)def installEnv(self, folder):env_path = foldercwd = os.getcwd()os.chdir(env_path)self.touchDir(os.path.join(env_path, 'local_pkgs'))self.touchDir(os.path.join(env_path, 'packages'))self.touchDir(os.path.join(env_path, 'tools'))self.gitUpdate('https://gitee.com/RT-Thread-Mirror/env.git', 'tools/script')self.gitUpdate('https://gitee.com/RT-Thread-Mirror/packages.git', 'packages/packages')kconfig = open(os.path.join(env_path, 'packages', 'Kconfig'), 'w')kconfig.write('source "$PKGS_DIR/packages/Kconfig"')kconfig.close()os.chdir(cwd)returndef pkgsUpdate(self, env_folder):self.touchDir(env_folder)self.installEnv(env_folder)os.environ['PKGS_DIR'] = env_folderos.system('python %s package --update' % (os.path.join(env_folder, 'tools', 'script', 'env.py')))returndef delTree(self, folder):if os.path.exists(folder):shutil.rmtree(folder)def delFile(self, file):if os.path.exists(file):os.remove(file)def appendFile(self, srcFile, otherFile):f = open(otherFile, 'r')s = f.read()f.close()f = open(srcFile, 'a')f.write(s)f.close()def copyTree(self, srcTree, dstTree):if os.path.exists(dstTree):shutil.rmtree(dstTree)shutil.copytree(srcTree, dstTree)def run(self, cmds):cwd = os.getcwd()cmds = cmds.split('\n')for item in cmds:item = item.lstrip()if item == '':continueif item[0] == '-':os.system(item[1:].lstrip())# keep current directoryos.chdir(cwd)returnif __name__ == '__main__':ci = CI()env_folder = os.path.abspath(os.path.join('.', 'env_test'))# ci.pkgsUpdate(env_folder)cmds = '''# test- dir- dir tools'''ci.run(cmds)
  • 下载gcc 交叉编译工具链: qemu-virt64-riscvriscv64 平台

$ python3 get_toolchain.py riscv64 就可以下载 riscv64 的 gcc 交叉编译工具链了

  • rt-thread/bsp/qemu-virt64-riscv 目录下创建 一个设置环境变量的 shell 脚本,如 smart_env.sh
#!/bin/bash# usage:
# source smart-env.sh [arch]
# example: source smart-env.sh          # arm
# example: source smart-env.sh aarch64  # aarch64# supported arch list
supported_arch="arm aarch64 riscv64 i386"def_arch="unknown"# find arch in arch list
if [ -z $1 ]
thendef_arch="arm" # default arch is arm
elsefor arch in $supported_archdoif [ $arch = $1 ]thendef_arch=$archbreakfidone
fi# set env
case $def_arch in "arm")export RTT_CC=gccexport RTT_EXEC_PATH=$(pwd)/tools/gnu_gcc/arm-linux-musleabi_for_x86_64-pc-linux-gnu/binexport RTT_CC_PREFIX=arm-linux-musleabi-;;"aarch64")export RTT_CC=gccexport RTT_EXEC_PATH=$(pwd)/tools/gnu_gcc/aarch64-linux-musleabi_for_x86_64-pc-linux-gnu/binexport RTT_CC_PREFIX=aarch64-linux-musleabi-;;"riscv64")export RTT_CC=gccexport RTT_EXEC_PATH=$(pwd)/tools/gnu_gcc/riscv64-linux-musleabi_for_x86_64-pc-linux-gnu/binexport RTT_CC_PREFIX=riscv64-unknown-linux-musl-;;"i386")export RTT_CC=gccexport RTT_EXEC_PATH=$(pwd)/tools/gnu_gcc/i386-linux-musleabi_for_x86_64-pc-linux-gnu/binexport RTT_CC_PREFIX=i386-unknown-linux-musl-;;*)  echo "unknown arch!"return 1
esac# export RTT_EXEC_PATH
export PATH=$PATH:$RTT_EXEC_PATHecho "Arch      => ${def_arch}"
echo "CC        => ${RTT_CC}"
echo "PREFIX    => ${RTT_CC_PREFIX}"
echo "EXEC_PATH => ${RTT_EXEC_PATH}"
  • 设置 smart_env.sh 的执行权限 $ chmod +x smart_env.sh

  • 下载 gcc 交叉编译工具链后, 在 rt-thread/bsp/qemu-virt64-riscv 运行

$ source smart_env.sh riscv64,即可设置 qemu-virt64-riscv 的 gcc 交叉编译工具链

编译 qemu-virt64-aarch64

  • 配置好 gcc 交叉编译工具链后,就可以 scons 编译了

运行 qemu

  • qemu-virt64-riscv 目录下有个 qemu-nographic.sh,可以在 Linux shell 里面直接运行

在这里插入图片描述

  • 当前 qemu 启动失败,报如下的错误
zhangsz@zhangsz:~/rtt/smart/rtt_qemu_aarch64/qemu-virt64-riscv$ ./qemu-nographic.sh
qemu-system-riscv64: warning: No -bios option specified. Not loading a firmware.
qemu-system-riscv64: warning: This default will change in a future QEMU release. Please use the -bios option to avoid breakages when this happens.
qemu-system-riscv64: warning: See QEMU's deprecation documentation for details.
QEMU: Terminated
  • 退出 qemu 的方法: CTRL + a 组合按一下,松开按键,再 按一下 x 键即可退出 qemu

qemu 更新解决启动问题

  • 经过验证,确认 ubuntu 20.04 默认安装的 qemu 版本比较的老,需要更新最新的 qemu 版本,直接使用 sudo apt install qemu-system-riscv64 无法更新,只能手动更新。

  • 解决方法:下载 qemu 的代码,手动编译更新 qemu,使用新版本的 qemu-system-riscv64

  • qemu 下载地址:可以再 github 上下载,注意拉取更新 git 子仓库

  • 下载 qemu : $ git clone https://github.com/qemu/qemu.git

  • qemu 编译依赖: $ sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build

  • qemu git 子仓库 : $ git submodule update --init --force --recursive

  • 编译 qemu 的方法

进入 qemu 目录$ mkdir build
$ cd build
$ ../configure
$ make -j8

在这里插入图片描述

  • 编译完 qemu 后,会在 生成目录,如 build 目录下,生成新版本的 `qemu
zhangsz@zhangsz:~/rtt/qemu/build$ ./qemu-system-riscv64 --version
QEMU emulator version 7.2.90 (v8.0.0-rc0-27-g74c581b645-dirty)
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers

在这里插入图片描述

  • 把 qemu 新版本 qemu-system-riscv64 的执行路径,替换 qemu-virt64-riscv 中 qemu 的执行脚本中的 qemu-system-riscv64 即可。

  • 我当前可以运行的脚本,把 qemu-system-riscv64 替换为 /home/zhangsz/rtt/qemu/build/qemu-system-riscv64,由于提示 网络设备部分参数不支持,我暂时先把网络设备部分去掉了

if [ ! -f "sd.bin" ]; then
dd if=/dev/zero of=sd.bin bs=1024 count=65536
fi/home/zhangsz/rtt/qemu/build/qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin \
-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \
-device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0

运行 qemu 效果

zhangsz@zhangsz:~/rtt/smart/rtt_qemu_aarch64/qemu-virt64-riscv$ ./qemu-nographic.shOpenSBI v1.2____                    _____ ____ _____/ __ \                  / ____|  _ \_   _|| |  | |_ __   ___ _ __ | (___ | |_) || || |  | | '_ \ / _ \ '_ \ \___ \|  _ < | || |__| | |_) |  __/ | | |____) | |_) || |_\____/| .__/ \___|_| |_|_____/|____/_____|| ||_|Platform Name             : riscv-virtio,qemu
Platform Features         : medeleg
Platform HART Count       : 1
Platform IPI Device       : aclint-mswi
Platform Timer Device     : aclint-mtimer @ 10000000Hz
Platform Console Device   : uart8250
Platform HSM Device       : ---
Platform PMU Device       : ---
Platform Reboot Device    : sifive_test
Platform Shutdown Device  : sifive_test
Firmware Base             : 0x80000000
Firmware Size             : 212 KB
Runtime SBI Version       : 1.0Domain0 Name              : root
Domain0 Boot HART         : 0
Domain0 HARTs             : 0*
Domain0 Region00          : 0x0000000002000000-0x000000000200ffff (I)
Domain0 Region01          : 0x0000000080000000-0x000000008003ffff ()
Domain0 Region02          : 0x0000000000000000-0xffffffffffffffff (R,W,X)
Domain0 Next Address      : 0x0000000080200000
Domain0 Next Arg1         : 0x000000008fe00000
Domain0 Next Mode         : S-mode
Domain0 SysReset          : yesBoot HART ID              : 0
Boot HART Domain          : root
Boot HART Priv Version    : v1.12
Boot HART Base ISA        : rv64imafdch
Boot HART ISA Extensions  : time,sstc
Boot HART PMP Count       : 16
Boot HART PMP Granularity : 4
Boot HART PMP Address Bits: 54
Boot HART MHPM Count      : 16
Boot HART MIDELEG         : 0x0000000000001666
Boot HART MEDELEG         : 0x0000000000f0b509
heap: [0x802bbcb8 - 0x842bbcb8]\ | /
- RT -     Thread Smart Operating System/ | \     5.0.0 build Mar 19 2023 16:40:432006 - 2022 Copyright by RT-Thread team
lwIP-2.0.3 initialized!
[I/sal.skt] Socket Abstraction Layer initialize success.
[I/utest] utest is initialize success.
[I/utest] total utest testcase num: (0)
file system initialization done!
Hello RISC-V

qemu 支持 elm fat 文件系统

  • 运行 qemu 后,发现 ls 提示找不到文件,查看代码,发现没有 mnt 文件挂载的操作,所以从其他的bsp 中,如 qemu-virt64-aarch64 copy 过来一份 mnt.c,重新编译。

  • 第一次运行 qemu 会生成 sd.bin,这个 sd.bin 为 RAW 格式的,可以使用 Linux shell 命令:mkfs.fat sd.bin,格式化为 fat 格式,这样就可以正常的在RT-Thread 中挂载了

  • 就可以支持 elm fat 格式的文件系统了。

在这里插入图片描述

在这里插入图片描述

小结

  • 由于 ubuntu 20.04 默认安装的 qemu qemu-system-riscv64 版本较低,所以需要手动更新 qemu-system-riscv64 版本到最新,可以通过 qemu git 仓库手动编译

  • 当前 RT-Thread master 分支的 qemu-virt64-riscv 跑的是 RT-Thread,而不是 RT-Thread Smart,切换为 RT-Thread Smart,当前只需要配置使用 RT-Thread Smart 配置选项即可!

在这里插入图片描述

  • 后面尝试 把 RT-Thread 提供的 userapps 编译后,放到 qemu 中 RT-Smart 的文件系统中,运行用户态程序。

相关内容

热门资讯

女生古风伤感个性签名 女生唯美...   01、 相思难追 转动时光的椅背 旧日错过的年华与他来一杯  02、 那时回忆已成痂 初雪染白了...
中学生励志演讲稿范例 演讲稿三... 中学生励志演讲稿范例1  各位老师,各位同学,大家好。今天,我很荣幸站在这个舞台,来表达我从开学到现...
高冷霸气的qq个性签名 高冷霸...   01、 他和她住在同一栋楼 遗憾的是爱擦身而过。  02、 学历或专业而沾沾自喜,也不要因为你的...
高冷伤感个性签名经典 游戏个性... 01、 总归有人看不惯我,我能怎样,百般讨好还是杀人灭口.  02、 下雨了 我想起伞 也想起了你 ...
古风签名女生唯美句子 女生个性...   01、 一杯酒 一世意 了却长相思  02、 纵使相逢应不识  03、 相顾无言  04、 此生...
银行信贷员竞聘演讲稿范文 信贷... 银行信贷员竞聘演讲稿  竞聘人XX,我竞聘的岗位是信贷岗,竞聘理由如下:  我有一定的文字表达能力和...
关爱他人优秀演讲稿范文 关爱他... 关爱他人优秀演讲稿篇1  得到他人的的关爱是一种幸福,关爱他人更是一种美德。在我成长的岁月中,常常得...
颂歌献给党演讲稿范文 我把赞歌... 颂歌献给党演讲稿一  亲爱的党啊,在庆祝您华诞之际,请收下我,一名曾在死亡线上徘徊了好长一段时间后,...
励志演讲稿参考范文 励志演讲稿... 励志演讲稿参考范文【1】  各位领导、各位同事,大家下午好!  今天我要演讲的题目是《青春风采、励志...
银行营销岗位竞聘演讲稿 银行竞...   银行营销岗位竞聘演讲稿1  我是来自观音阁支行的李梦娜,我演讲的题目是学习、创新、团结。  每个...
logstash+elasti... 文章目录一.安装ELK 7.17二.为Elasticsearch设置密码三.配置logstash四....
华为OD机试题,用 Java ... 华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已...
银行竞聘副行长演讲稿 竞聘银行... 银行竞聘副行长演讲稿【1】  尊敬的各位评委、各位领导、同志们:  大家*午好!  首先,真诚的感谢...
关于低碳绿色环保演讲稿 节能低...  尊敬的各位领导,各位评委,敬爱的老师,亲爱的同学们:  大家晚上好!  我演讲的题目是《迈出那一小...
因果推断dowhy之-ihdp... 0x01. 案例背景 IHDP(Infant Health and Developme...
关于银行竞聘演讲稿三篇 银行营... 银行竞聘演讲稿1尊敬的各位领导、同志们:  大家好!  我叫xxx,现年32岁,金融本科文化,中国共...
加强师德师风教育演讲稿 师德师... 加强师德师风教育演讲稿一  今天,我们怀着喜悦的心情迎来了中国共产党的80华诞。中国共产党是中国工人...
环保先进个人演讲稿范文 环保工...   环保先进个人演讲稿  同学们:  我今天发言的主题是《保护环境,珍惜地球》。  我们生活在地球上...
医院借力泛微今承达实现数字化合...   国家卫健委印发的《公立医院内部控制管理办法》中要求“充分利用信息技术加强内部控制建设࿰...
设置jvm参数,验证结果 文章目录前言一、启动java项目二、开始验证设置项目的jvm参数总结 前言 书接上文上个博文 由于...