系统开发

更新历史
日期 版本 作者 更新内容
2023-05-12 v1.1 wonder
  • Depart docs
2023-05-08 v1.0 wonder
  • Release docs

Yocto Linux

TH1520 的官方开发环境是平头哥的基于 yocto 的开发环境,大家可以在这里获取开发环境: https://gitee.com/thead-yocto/

本节简单介绍如何搭建 Linux Yocto 环境并使用 Yocto 构建可在开发板上运行的完整镜像。

搭建Yocto编译环境

Linux SDK 使用 Yocto 构建镜像。Yocto 编译环境使用 Ubuntu18.04,推荐在 Linux 上使用 Docker 部署,也可直接在 Ubuntu18.04 下搭建环境(见T-Head曳影1520Yocto用户指南.pdf2.2)。

这里仅介绍 Linux 上使用 Docker 部署的方式。建议编译机器预留200G磁盘空间,内存为4G以上,编译时间因网络情况差异很大,在使用代理的情况下编译典型linux系统配置(最小系统加上必要的相关基础组件)时间约为1.5h(CPU为i5-11400,时间供参考)

  • 使用官方脚本安装 docker
    curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
    
  • 下载 dockerfile 并修改用户名和 ID
    点击下载 linux-dev-master.7z 并解压后,进入到 linux-dev-master 目录,打开 Dockerfile,找到如下语句
    ENV DOCKER_USER2 "your the same user name asyour host"`
    ENV USER2_ID "your user id"
    
    将 "your the same user name asyour host" 改为用户 host os 的用户名,"your user id" 的值对应该用户的密码。
  • 构建 docker 镜像环境
    docker build -t linux-dev-base:base .
    
    这里下载的软件包的时候可能会有些报错,可以在 Dockerfile 中进行相应的修改,等到创建好 docker 后登录到 docker 中再进行下载。这个 docker 镜像可以编译 thead 发布的 buildroot、yocto 等 Linux SDK。默认密码为 123
  • 启动 docker
    docker run -u thead -dt --name linux-dev-{your_name} -v {your_lock_home}:{your_home} linux-dev-base:base /bin/bash
    
    {your_name} 为容器名称,起名时不要重名。
    通过 -v 选项可以挂载宿主机的目录,起到类似共享文件的作用,{your_lock_home} 为宿主机的本地路径,{your_home} 为挂载在 docker 里的路径。
  • 查看启动的 docker 容器
    docker ps | grep linux-dev-base
    

就能够看到刚刚启动的 docker 容器。

  • 登录 docker
    docker exec -it linux-dev-{your_name} /bin/bash
    
  • 下载开源软件包(仅在第一次获取 SDK 时才需要下载)
    构建固件时会从网上下载开源软件包,若网络较差,下载时间会比较长。为了加速这一过程,可以先到 gitee 下载离线开源软件包(假设下载到用户目录)
    cd ~
    git clone https://gitee.com/thead-yocto/yocto-downloads.git
    
  • 下载 Yocto 构建包
    git clone https://gitee.com/thead-yocto/xuantie-yocto.git -b Linux_SDK_V1.1.2
    
  • 加载目标设备的配置文件和环境变量(编译前记得检查是否加载)
    cd xuantie-yocto
    source openembedded-core/oe-init-build-env thead-build/light-fm
    
  • 将前面下载的开源软件包通过共享 downloads 目录的方式软链接到 SDK 目录
    ln -s ~/yocto-downloads ../downloads
    
  • 打patch

由于写文档时xuantie-yocto的commit-d296c2345fe2c2521eb0e1a2772bcba637029bc8还未合并下述patch中的改动,所以需要手动打patch来同步这些改动再进行后续开发。patch文件请在下载站下载。

kernel的patch

0001-pca9557.patch:修改设备树中pcal9554b为pca9557
0002-cpufreq-to-2GHz.patch:增加cpu频率2GHz支持
0003-remove-audio-pcal9554b.patch:移除audio pcal9554b
0004-sync-audio-patch.patch:同步修改audio参数
0005-8G-ddr.patch:修改支持8g ddr
0006-set-cpu_max_frq-1.992GHz.patch:修改cpu最大频率支持
0007-set-cpu_max_frq-1.848GHz.patch:修改cpu最大频率支持
0008-RISC-V-Enable-container-related-kernel-configs.patch:增加内核配置选项
0009-remove-mipi-screen.patch:增加mipi屏幕设备树信息(这里本来应该是删除信息,patch0014会删除这里误增加的信息)
0010-Add-kernel-build-ci.patch:添加内核ci流程
0011-riscv-dts-thead-lpi4a-add-PWM-Fan.patch:增加PWM风扇支持
0012-riscv-defconfig-revyos-enable-kernel-PWM-fan.patch:增加内核配置选项
0013-ci-run-on-pull-requests.patch:ci流程中增加pull-request
0014-riscv-dts-thead-lpi4a-really-remove-mipi-screen.patch:删除之前的patch中误增加的mipi屏幕设备树信息
0015-fix-fix-iotop-not-working.patch:修复iotop问题
0016-drm-dc8200-disable-gamma-lut-now.patch:移除gamma lut
0017-drm-verisilicon-fix-fbcon.patch:修复 fbcon
0018-riscv-dts-thead-lpi4a-change-fan-PWM-frequency.patch:修改PWM频率参数,改善风扇噪声问题
0019-feat-ci-build-perf.patch:增加测试工具
0020-chore-add-commit-id.patch:增加commi-id信息
0021-chore-rename-perf-to-perf-thead.patch:修改测试工具存储路径

opensbi的patch

0001-lib-sbi_illegal_insn-Add-emulation-for-fence.tso.patch:增加fence.tso仿真
0002-lib-sbi_illegal_insn-Fix-FENCE.TSO-emulation-infinit.patch:修复 FENCE.TSO 无限循环问题

uboot的patch

0001-ENV_SETTINGS.patch:修改分区信息
0002-fix-fix-bootargs.patch:修改bootargs
0003-fix-ftbfs.patch:修复ftbfs中的变量定义问题
0004-feat-add-ci-build.patch:添加ci流程
0005-fix-set-fixed-mac-addrs-1.patch:修复随机mac地址问题,设置为固定mac地址

至此,编译环境已经配置完成。

Machine/Target支持列表

在上面的加载环境变量步骤中,设置完成后可看到以下信息

### Shell environment set up for builds. ###
You can now run 'bitbake <target>'
Common targets are:
    thead-image-linux
    thead-image-multimedia
    thead-image-gui
machines:
    light-beagle
    light-b-product
    light-a-val
    light-lpi4a

相关说明如下
target(SDK 支持的镜像列表):

命名 描述
thead-image-linux 典型linux系统配置,最小系统加上必要的相关基础组件
thead-image-multimedia 典型linux系统+视频视觉配置,加上视频子系统的组件(Gstreamer等)
thead-image-gui 加上GUI相关组件的完整配置版本,包括Gnome桌面、weston、QT等应用组件等等

machines(SDK 支持的板级配置):

命名 描述
light-a-val TH1520-A EVB板
light-b-product TH1520-B EVB板
light-beagle beagleV-Ahead开发板
light-lpi4a Lichee Pi 4A开发板

构建镜像

构建命令格式如下:

MACHINE={machine} bitbake {target}

将其中的 {machine} 和 {target} 部分替换为上面两个表格中对应的命名即可。例如,编译一个在 LicheePi 4A 开发板上运行的典型 Linux 镜像的命令如下:

MACHINE=light-lpi4a bitbake thead-image-linux

构建镜像时可能会出现的问题

  • 由于网络原因,这一步可能仍会出现下载失败或下载很慢的情况,有条件的话推荐使用代理。
  • 报错信息
    Please use a locale setting which supports utf-8.
    Python can't change the filesystem locale after loading so we need a utf-8 when python starts or things won't work.
    
    首先运行如下命令
    sudo apt-get install locales
    sudo dpkg-reconfigure locales 
    
    然后在打印出来的列表中找到en_US.UTF8这一项(大概在第158项),输入这一项对应的序号后回车,接下来也选择这一项后回车。
    完成上述设置步骤后接着运行如下命令(也可考虑将下面的命令加入到docker的.bashrc中)
    sudo locale-gen en_US.UTF-8
    sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
    export LANG=en_US.UTF-8
    
    完成上述步骤后再编译就不会出现原来的报错。
  • 报错信息
    please install them in order to proceed: lz4c pzstd zstd
    
    安装对应的依赖即可
    sudo apt update && sudo apt install -y zstd liblz4-tool
    

镜像打包

light_deploy_images 仓库中,包含了一些预发布镜像。对于刚刚编译好的镜像,可以利用这个仓库中的 sdk.sh 脚本来进行打包。
首先切换到已经编译好的镜像中的 light-fm 目录下,将该仓库中的 sdk.sh 移动到这里即可。直接运行该脚本 ./sdk.sh 即可,打包后会生成相应的镜像,相应文件的位置以及镜像目录的结构参考 light_deploy_images 仓库。
最后,可以将 docker 编译好的镜像及相关文件复制到先前通过 -v 选项挂载的共享文件夹中,宿主机即可使用该文件进行烧录。
到这里,我们已经完成了编译和打包,得到了一个可以烧录到开发板中运行的镜像。

简单介绍yocto中的常用概念和一些实用技巧。

基础概念

Yocto用来构建定制的Linux镜像,有广泛的硬件支持,它是一个集合了很多工具的开源项目。
先对Yocto在构建镜像时的大致工作流程简单介绍:
Fetch->Extract->Patch->Configure->Build->Install->Package
Fetch:在编译时获取需要的源码。
Extract:对获取到的源码进行解压。
Patch:应用补丁以修复bug和添加新功能。
Configure:配置开发环境。
Build:构建镜像,编译链接。
Install:拷贝文件到目标目录。
Package:镜像打包。
下图展示了流程中的一些具体步骤:

Yocto project的大概构成如下图,构建所用到的主要是OpenEmbedded构建系统(下文用OE简称),它的核心是任务执行器Bitbake。

常用到的一些概念如下:
recipes:以.bb结尾的文件,里面会包含下载软件包时需要的相关信息,如下载固定源码的文件位置,需要应用到该软件包的patch信息,编译需要的信息等。例如xuantie-yocto的中的gnome-shell,它的recipes文件存储在/home/thead/xuantie-yocto/meta-openembedded/meta-gnome/recipes-gnome/gnome-shell目录下。
build directory:该目录即为构建时的输出目录,同时也会存放一些环境配置文件,source命令指定编译环境时就会生成该目录,默认命名为build,也可在source时更改为其他名字,如sourece oe-init-build-env mybuild
configurations:以.conf结尾的文件,主要是配置文件。比如存储在build directoryconf目录中的local.conf,在编译时可能会在根据需要更改其中一些参数。
layers:通常会在这里存储所需要的各种metadata(如,.bb文件,patches和一些其他的附加文件),主要是用于告诉OE构建系统如何构建目标文件。将metadata按层分类有助于项目维护。
bitbake:OE构建系统中用来执行各种任务的任务执行器。

常用操作

常用task

Yocto以package为单位管理开源软件组件,如需要编译某个package,方法如下:

bitbake "package-name"

每个package都在recipes文件中定义支持的task,有些task如clean,是所有包通用的,可以用一下命令列出package支持的task:

bitbake "package-name" -c listtasks
查找编译后package的位置

Yocto集成了大量开源的package,这些 package 编译的时候的工作目录通常在以下目录:

  • tmp-glibc/work/riscv64-oe-linux
  • tmp-glibc/work/${MACHINE}

例如

thead@b9461db16a58:~/xuantie-yocto/thead-build/light-fm/tmp-glibc/work/light_lpi4a-oe-linux/u-boot$ tree -L 2
.
└── 1_2020.10-r0
    ├── 0001-no-strip-fw_printenv.patch
    ├── build
    ├── deploy-debs

可以通过bitbake -e linux-thead | grep ^S=命令查找package目录。例如,查看内核的编译目录

$ bitbake -e linux-thead | grep ^S=
S="/home/thead/xuantie-yocto/thead-build/light-fm/tmp-glibc/work/light_a_val-oe-linux/linux-thead/5.10.y-r0/linux-5.10.y"

编译完成后文件输出的位置,例如,镜像编译完成后相关的各类文件都位于light-fm/tmp/glibc/work/light_lpi4a-oe-linux下,例如镜像就位于该目录的linux-thead下,最后只需要打包即可。

编译时fetch包的速度过慢

在编译时,可能会遇到fetch包过慢问题,这是除了使用代理,也可以将包下载到本地,然后根据得到的包地址让fetch时直接使用本地的repo。例如:

WARNING: bzip2-native-1.0.8-r0 do_fetch: Failed to fetch URL git://sourceware.org/git/bzip2-tests.git;name=bzip2-tests;branch=master, attempting MIRRORS if available

那么可以使用如下命令找到包的下载地址

$ bitbake -e bzip2 | grep ^SRC_URI=
SRC_URI="https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz            git://sourceware.org/git/bzip2-tests.git;name=bzip2-tests;branch=master            file://configure.ac;subdir=bzip2-1.0.8            file://Makefile.am;subdir=bzip2-1.0.8            file://run-ptest            "

得到地址后,手动将该仓库clone下来,然后找到它对应的.bb文件

$ find -name bzip*.bb
./openembedded-core/meta/recipes-extended/bzip2/bzip2_1.0.8.bb

在该文件中找到SRC_URI这一项

SRC_URI = "https://sourceware.org/pub/${BPN}/${BPN}-${PV}.tar.gz \
           git://sourceware.org/git/bzip2-tests.git;protocol=file;name=bzip2-tests;branch=master \
           file://configure.ac;subdir=${BP} \
           file://Makefile.am;subdir=${BP} \
           file://run-ptest \
           "

加上protocol指定为file,若需要切换分支,直接在clone下来的本地repo中checkout到对应的分支即可,修改好后,直接fetch这个包即可。

bitbake bzip2 -c fetch

若编译速度过慢,找到build_directoryconf目录下的local.conf文件,修改相应的参数即可,参考此文档,例如,增加下载和编译时的速度,可以在文件中增加如下代码,将并行数量调大(注意根据CPU具体参数来)

BB_NUMBER_THREADS = '16'
PARALLEL_MAKE = '-j 12'

yocto编译后对package有缓存机制,可以在后面编译时减少所花费的时间。
除此之外,也可在编译前提前下载好一些包,放入某个文件夹,然后在build_directoryconf文件夹的local.conf找到DL_DIR这一项,这就是共享文件夹,更改到指定目录或软链接共享即可。

单独构建u-boot

在编译时将源码下载到light-fm/tmp-glibc/work/light_lpi4a-oe-linux/u-boot/1_2020.10-r0/git路径下(倒数第二级目录名为版本号),修改源码后执行该命令即可:

bitbake u-boot -C compile
单独构建opensbi

在编译时将源码下载到light-fm/tmp-glibc/work/light_lpi4a-oe-linux/opensbi/0.9-r0/git路径下,修改源码后执行该命令即可:

bitbake opensbi -C compile

编译完成后,为了简化打包流程,在light_deploy_images提供了打包脚本sdk.sh。编译完成后,在light-fm文件夹下创建一个sdk文件夹,将该镜像打包脚本下载到该文件夹下,运行即可。
打包后典型的目录结构应如下所示:

.
├── deb
│   ├── all
│   ├── light_lpi4a
│   └── riscv64
├── images
│   └── light-lpi4a
│       ├── boot.ext4
│       ├── light_fastboot_image_single_rank
│       │   └── u-boot-with-spl.bin
│       ├── rootfs.thead-image-linux.ext4
│       └── vmlinux
├── sdk.sh
└── tarball
    └── prebuild_light-lpi4a.tar.gz

烧录时主要是用images目录下的文件,如果少了哪个文件,也可以手动复制进去。tarball目录下为打包好的镜像文件的压缩包,deb目录下为软件包。
参考:
bitbake官方文档
yocto官方文档
T-Head 曳影 1520 Yocto 用户指南

设备树解析

TODO

其他参考资料

light_deploy_images 仓库:

documents 仓库:

欢迎投稿~ 投稿接受后可得¥5~150($1~20)优惠券!