赞
踩
最近需要使用 RT-Thread smart 开发调试一些软件功能,由于软件功能平台无关,使用实际硬件操作,会耗费较多的时间在程序烧写环节。
打算使用 BSP qemu-virt64-aarch64 搭建一个 RT-Thread smart 的开发调试环境,可以开发验证一些平台无关的软件功能
Win10 64位
VMware Workstation Pro
VS Code (ssh 远程)
ubuntu 20.04
RT-Thread master 最新分支: BSP qemu-virt64-aarch64
这里使用 gitee 的 RT-Thread 仓库,先通过 fork 的方式,把 RT-Thread fork 到自己的账号下
ubuntu 中安装好 git
qemu
,通过 git
克隆一份 RT-Thread 最新代码
可以直接克隆 RT-Thread 官方的 git clone https://gitee.com/rtthread/rt-thread.git
rt-thread/bsp/qemu-virt64-aarch64
,直接 scons
可能会提示 scons
找不到,如果找不到,就安装一下 scons
zhangsz@zhangsz:~/rtt/smart/rt-thread/bsp/qemu-virt64-aarch64$ 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
软件包
scons
后,发现提示找不到 gcc 交叉编译工具链, aarch64-none-elf-gcc: not found
zhangsz@zhangsz:~/rtt/smart/rt-thread/bsp/qemu-virt64-aarch64$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: building associated VariantDir targets: build
CC build/applications/console.o
sh: 1: aarch64-none-elf-gcc: not found
scons: *** [build/applications/console.o] Error 127
scons: building terminated because of errors.
下载工具链:可以使用 get_toolchain.py
下载,不过这个脚本默认没有在 RT-Thread 工程里面,需要手动创建一个
在 rt-thread/bsp/qemu-virt64-aarch64
目录下,新建一个 tools
目录,然后进入这个 rt-thread/bsp/qemu-virt64-aarch64/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-aarch64/tools
目录下,创建一个 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)
qemu-virt64-aarch64
是 aarch64
平台$ python3 get_toolchain.py aarch64
就可以下载 aarch64 的 gcc 交叉编译工具链了
rt-thread/bsp/qemu-virt64-aarch64
目录下创建 一个设置环境变量的 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}"
下载 gcc 交叉编译工具链后, 在 rt-thread/bsp/qemu-virt64-aarch64
运行
设置 smart_env.sh
的执行权限 $ chmod +x smart_env.sh
$ source smart_env.sh aarch64
,即可设置 qemu-virt64-aarch64
的 gcc 交叉编译工具链
qemu-virt64-aarch64
scons
编译了qemu-virt64-aarch64
目录下有个 qemu.sh
,可以在 Linux shell 里面直接运行zhangsz@zhangsz:~/rtt/smart/rt-thread/bsp/qemu-virt64-aarch64$ ./qemu.sh 65536+0 records in 65536+0 records out 67108864 bytes (67 MB, 64 MiB) copied, 0.0898412 s, 747 MB/s [I/libcpu.aarch64.cpu] Using MPID 0x0 as cpu 0 [I/libcpu.aarch64.cpu] Using MPID 0x1 as cpu 1 [I/libcpu.aarch64.cpu] Using MPID 0x2 as cpu 2 [I/libcpu.aarch64.cpu] Using MPID 0x3 as cpu 3 \ | / - RT - Thread Operating System / | \ 5.0.0 build Mar 18 2023 19:11:05 2006 - 2022 Copyright by RT-Thread team [I/libcpu.aarch64.cpu] Secondary CPU 1 booted [I/libcpu.aarch64.cpu] Sec />ry CPU 2 booted [I/libcpu.aarch64.cpu] Secondary CPU 3 booted m[0m hello rt-thread msh /> msh />ls No such directory msh />QEMU: Terminated
CTRL + a
组合按一下,松开按键,再 按一下 x
键即可退出 qemu由于 Linux 的环境存在差异,如qemu 之前安装过,所以 qemu-virt64-aarch64
的交叉编译环境 搭建起来并没有遇到太多的问题,如果遇到环境依赖,需要根据提示,安装 ubuntu 相应的 软件包,如 qemu
与 qemu-system-aarch64
当前 RT-Thread master 分支的 qemu-system-aarch64
跑的是 RT-Thread,而不是 RT-Thread Smart,后面研究如何运行 RT-Thread Smart
,并用于软件组件的开发调试
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。