0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RT-Thread BSP qemu-virt64-riscv的编译环境搭建步骤

冬至子 来源:张世争 作者:张世争 2023-10-08 15:41 次阅读

前言
最近需要使用 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

建议手动搭建一个 qemu-virt64-riscv 的独立工程,修改一下构建与配置脚本的路径即可。

scons 构建
进入 rt-thread/bsp/qemu-virt64-riscv,直接 scons编译,如果第一次,可能提示 scons 找不到,找不到就安装一下 scons
$ scons
Command '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 软件包

1.jpg

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

下载工具链:可以使用 get_toolchain.py 下载,不过这个脚本默认没有在 RT-Thread 工程里面,需要手动创建一个

备注:可以在 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 platform
from ci import CI
toolchains_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 toolchain

if 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/' + zfile
except:
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 zipfile
class 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 = 0
count_tmp = 0
time1 = 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 * 100
speed = (count - count_tmp) / 1024 / 1024 / 2
count_tmp = count
print(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))
return
def 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()
return
def 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 = folder
cwd = 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)
return
def pkgsUpdate(self, env_folder):
self.touchDir(env_folder)
self.installEnv(env_folder)
os.environ['PKGS_DIR'] = env_folder
os.system('python %s package --update' % (os.path.join(env_folder, 'tools', 'script', 'env.py')))
return
def 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 == '':
continue
if item[0] == '-':
os.system(item[1:].lstrip())

keep current directory

os.chdir(cwd)
return
if 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-riscv 是 riscv64 平台
    $ 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 ]
then
def_arch="arm" # default arch is arm
else
for arch in $supported_arch
do
if [ $arch = $1 ]
then
def_arch=$arch
break
fi
done
fi

set env

case $def_arch in
"arm")
export RTT_CC=gcc
export RTT_EXEC_PATH=$(pwd)/tools/gnu_gcc/arm-linux-musleabi_for_x86_64-pc-linux-gnu/bin
export RTT_CC_PREFIX=arm-linux-musleabi-
;;
"aarch64")
export RTT_CC=gcc
export RTT_EXEC_PATH=$(pwd)/tools/gnu_gcc/aarch64-linux-musleabi_for_x86_64-pc-linux-gnu/bin
export RTT_CC_PREFIX=aarch64-linux-musleabi-
;;
"riscv64")
export RTT_CC=gcc
export RTT_EXEC_PATH=$(pwd)/tools/gnu_gcc/riscv64-linux-musleabi_for_x86_64-pc-linux-gnu/bin
export RTT_CC_PREFIX=riscv64-unknown-linux-musl-
;;
"i386")
export RTT_CC=gcc
export RTT_EXEC_PATH=$(pwd)/tools/gnu_gcc/i386-linux-musleabi_for_x86_64-pc-linux-gnu/bin
export RTT_CC_PREFIX=i386-unknown-linux-musl-
;;
*) echo "unknown arch!"
return 1
esac

export RTT_EXEC_PATH

export PATH=**PATH:**RTT_EXEC_PATH
echo "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 里面直接运行

1.jpg

当前 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

1.jpg

编译完 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

1.jpg

把 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

1.jpg

运行 qemu 效果
zhangsz@zhangsz:~/rtt/smart/rtt_qemu_aarch64/qemu-virt64-riscv$ ./qemu-nographic.sh
OpenSBI 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.0
Domain0 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 : yes
Boot 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:43
2006 - 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

1.jpg

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 配置选项即可!

1.jpg

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

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux系统
    +关注

    关注

    4

    文章

    464

    浏览量

    26619
  • Shell
    +关注

    关注

    1

    文章

    314

    浏览量

    22761
  • RT-Thread
    +关注

    关注

    29

    文章

    951

    浏览量

    38366
  • RAW
    RAW
    +关注

    关注

    0

    文章

    15

    浏览量

    3716
  • gcc编译器
    +关注

    关注

    0

    文章

    59

    浏览量

    3167
收藏 人收藏

    评论

    相关推荐

    如何在RT-Thread Smart下使用gcc交叉编译工具链呢

    RT-Thread Smart的BSP rt-smartspd1-allwinner-nezha,也全志D1s的哪吒开发板,基于RISCV64平台,需要CV64的就是交叉
    发表于 06-17 11:13

    在Ubuntu平台开发RT-Thread文档中步骤搭建QEMU环境

    QEMU 环境下搭配蓝牙 Control 芯片运行,目前在 Ubuntu 18.04 下运行成功。QEMU 环境搭建主要参考 在 Ubuntu 平台开发 RT-Thread 文档
    发表于 07-27 11:19

    基于RT-Thread操作系统的Env开发环境搭建

    环境进入到源码目录 rt-thread\\bsp\\qemu-vexpress-a9,鼠标右击打开 env 工具。输入指令 menuconfig,如果出现配置界面,说明开发环境初步搭建成功输入
    发表于 09-30 10:38

    如何在Window及Ubuntu平台使用QEMU运行 RT-Thread qemu-vexpress-a9 BSP工程

    BSP 文件夹下创建一份空白的 sd.bin 文件,这是虚拟的 sd 卡,大小为 64M。Env 命令行界面显示 RT-Thread 系统启动过程中打印的初始化信息及版本号信息等,qemu 虚拟机也运行
    发表于 10-26 15:19

    在Windows平台使用VSCode调试 RT-Thread qemu-vexpress-a9 BSP工程

    qemu-vexpress-a9 BSP 文件夹,如下图所示。步骤编译 RT-Thread点击 VS Code “查看 -&gt; 终端” 打开 VS Code 内部终端,在终端
    发表于 10-26 15:25

    在Windows平台使用Eclipse调试RT-Thread qemu-vexpress-a9 BSP工程

    qemu-vexpress-a9 切换到 RT-Thread 源码文件夹下的 qemu-vexpress-a9 BSP 根目录,然后输入 scons 命令编译工程,如果编译正确无误,会在 BSP 目录下生成 QEMU 下运行
    发表于 10-26 15:31

    请教大神qemu模拟cortex-A53运行rt-thread出错怎么解决呢?

    RT-Thread qemu-vexpress-a9 BSP 工程的方法自己配置了qemu-virt64-aarch64的工程模拟了cortex-A53的架构但是运行时
    发表于 02-15 10:51

    RT-Thread BSP qemu-virt64-aarch64编译环境搭建步骤

    RT-Thread smart 开发调试一些软件功能,由于软件功能平台无关,使用外部硬件操作,会耗费更多的时间在后台。  打算使用BSP qemu-virt64-aarch64搭建
    发表于 04-04 17:04

    RT-Thread BSP qemu-virt64-aarch64文件系统

    搭建RT-Thread BSP qemu-virt64-aarch64 的交叉编译环境,运行后发现,文件系统没有挂载上,感觉是没有 mkfs。   通过
    发表于 05-16 10:29

    RT-Thread BSP qemu-virt64-riscv编译环境搭建

    编译工具链了   在
    发表于 05-16 10:37

    AB32VG1 RT-Thread 开发环境搭建

    RT-Thread Studio 目前已经支持 AB32VG1开发板,所以,搭建一个RT-Thread的开发环境环境搭建先查找并下载开发板相关的资料https://gitee.com/bluetrum/bl
    发表于 12-20 19:09 22次下载
    AB32VG1 <b>RT-Thread</b> 开发<b>环境</b><b>搭建</b>

    如何在windows和linux平台使用RT-Thread QEMU BSP,并运行RT-ThreadGUI示例

    RT-ThreadRT-Thread使用QEMU模拟了ARM vexpress A9开发板,并提供了相关的板级支持包(BSP)。本文主要介绍在windows平台和linux平台使用RT-Thread提供的qemu-vexpress-a9
    的头像 发表于 02-08 08:50 1.3w次阅读
    如何在windows和linux平台使用<b>RT-Thread</b> <b>QEMU</b> <b>BSP</b>,并运行<b>RT</b>-ThreadGUI示例

    RT-Thread中的Github Actions

    RT-Thread中一共有五个Github Action(rt-thread/.github/workflow) 分别是: RT-Thread BSP build check(.github
    的头像 发表于 06-01 03:10 169次阅读
    <b>RT-Thread</b>中的Github Actions

    RT-Thread qemu mps2-an385 bsp移植制作 :环境搭建

    RT-Thread,包括 RT-Thread BSP 的移植,由于一直在使用 QEMU 进行一些软件功能的验证,qemu 支持很多的CPU 与 开发板,所以想移植一个新的 qemu board 到 RT-Thread,掌握
    的头像 发表于 08-02 14:45 144次阅读
    <b>RT-Thread</b> <b>qemu</b> mps2-an385 <b>bsp</b>移植制作 :<b>环境</b><b>搭建</b>篇

    RT-Thread Smart qemu-virt64-riscv用户态userapps的编译与运行

    rt-smart 上,为了实现用户态与内核态的分离,使用了【系统调用】,这个系统调用可以认为是个 sdk
    的头像 发表于 10-08 15:33 197次阅读
    <b>RT-Thread</b> Smart <b>qemu-virt64-riscv</b>用户态userapps的<b>编译</b>与运行