嵌入式技术论坛
直播中

李桂英

7年用户 1375经验值
私信 关注
[经验]

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

  最近需要使用RT-Thread smart 开发调试一些软件功能,由于软件功能平台无关,使用外部硬件操作,会耗费更多的时间在后台。
  打算使用BSP qemu-virt64-aarch64搭建一个RT-Thread smart的开发调试环境,可以开发验证一些平台无关的软件功能
  环境搭建
  Win10 64位
  VMware 工作站专业版
  VS 代码(ssh 远程)
  Ubuntu 20.04
  RT-Thread master 最新支持: BSPqemu-virt64-aarch64
  下载 RT-Thread
  这里使用gitee的RT-Thread库,先通过fork的方式,把RT-Thread fork到自己的账号下
  ubuntu 中安安装好git qemu,通过git 克隆一份 RT-Thread 最新代码
  可以直接连接克隆RT-Thread 官方的git clone
  scons 结构
  进入rt-thread/bsp/qemu-virt64-aarch64,直接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软件包
2.jpg
2.jpg
  交叉编译工具链
  再次运行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 =  + 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(‘‘tools/script’)
  self.gitUpdate( ‘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-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交叉编译工具链
2.jpg
  编译qemu-virt64-aarch64
  配置好gcc交叉编译工具链接后,就可以scons编译了
2.jpg
  运行qemu
  qemu-virt64-aarch64目录下有一个qemu.sh,可以在Linux shell里面直接运行
2.jpg
  ./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
  退出qemu的方法:CTRL + a组合按一下,松开按键,再按一下x键即可退出qemu
  小结
  linux的的环境,如qemu之前之前安装安装安装,所以所以qemu-virt64-aarch64的交叉交叉编译环境环境搭建搭建起来起来并没有并没有并没有遇到太多,qemu如果 qemu-system-aarch64
  当前RT-Thread master 支持的qemu-system-aarch64跑的是RT-Thread,而不是RT-Thread Smart,后面研究如何运行RT-Thread Smart,并用于软件组的开发调试。



原作者:张世争

更多回帖

发帖
×
20
完善资料,
赚取积分