4. Linux6.6_SDK编译#

4.1. 获取源码#

从网盘资源 4-SDK源码压缩包 中获取最新日期的LubanCat_Hi3403_Linux6.6_SDK源码压缩包,使用下面的命令将源码压缩包解压到当前用户的家目录,方便后续操作。

 1# 将源码压缩包移动到用户家目录,xxxxxxxx为源码压缩包发布日期
 2mv LubanCat_Hi3403_Linux6.6_SDK_xxxxxxxx.tgz ~/LubanCat_Hi3403_Linux6.6_SDK.tgz
 3
 4# 进入用户家目录
 5cd ~
 6
 7# 解压源码压缩包
 8tar -xf LubanCat_Hi3403_Linux6.6_SDK.tgz
 9
10# 进入SDK源码目录
11cd ~/LubanCat_Hi3403_Linux6.6_SDK
../../_images/tar-sdk-6.6.png

如图所示,解压后的源码各文件夹。

4.2. SDK目录介绍#

提示

以下目录结构不需要深入了解,只需要在修改对应项目时找得到即可。

SDK源码目录结构,部分路径需要再编译后才会出现

 1.
 2├── open_source     # SDK使用到的第三方开源项目源码
 3   ├── buildroot           # Buildroot目录
 4      ├── buildroot-2024.02.10        # Buildroot源码
 5      ├── buildroot-2024.02.10.tar.gz # Buildroot源码压缩包
 6      ├── dl                          # Buildroot下载的源码压缩包保存位置
 7      ├── Makefile                    # Buildroot项目的Makefile,对接SDK的Makefile
 8      ├── overlay                     # Buildroot根文件系统配置文件覆盖层
 9      ├── readme.txt                  # Buildroot源码压缩包下载说明
10      └── ss928_lbc_defconfig         # Buildroot编译时的配置文件
11   ├── linux               # Linux内核
12      ├── linux-6.6.86.patch          # Linux内核补丁
13      ├── linux-6.6.y                 # Linux内核源码目录
14      ├── Makefile                    # Linux项目的Makefile,对接SDK的Makefile
15      └── readme.txt                  # Linux源码下载说明
16   ├── lvgl                # LVGL图形框架
17      ├── lv_port_linux               # LVGL的Linux系统适配接口
18         └── lvgl                    # LVGL源码目录
19      └── Makefile                    # LVGL的Makefile,对接SDK的Makefile
20   ├── mbedtls             # 加密库
21   ├── trusted-firmware-a  # 可信固件
22   ├── u-boot              # U-Boot
23   └── ubuntu              # Ubuntu根文件系统构建脚本
24├── osdrv           # 操作系统相关目录
25   ├── BoardConfig         # 板级配置文件目录
26      └── BoardConfig配置说明         # 配置项说明文件
27   ├── components
28      ├── boot            # boot相关工具
29         ├── gsl             # GSL源码
30         └── image_map       # boot镜像制作工具
31      └── secure_c            # 安全函数库源码
32   ├── lunch               # 板级配置选择脚本
33   ├── Makefile            # SDK编译入口
34   ├── pub                 # 编译生成的镜像等文件存放位置
35   └── tools               # 系统工具源码
36       ├── board               # 板卡工具
37          └── reg-tools-1.0.0         # 寄存器读写工具、i2c读写工具
38       └── pc                  # 编译机工具
39           ├── kdf_customer
40           ├── nand_production
41           ├── rootfs_tools    # 根文件系统镜像打包脚本
42           ├── uboot_env       # env镜像制作工具
43           └── uboot_tools
44               ├── regbin-v1.0.2       # regbin转换工具,将xlsm格式的u-boot表格转换为bin文件
45               └── SS928V100_LubanCat_LPDDR4x_3733M-8GB_32bitx2-A55_1400M-emmc.xlsm    # u-boot表格,寄存器配置表
46├── README_zh.md
47└── smp     # smp目录
48    └── a55_linux       # arm核代码
49        ├── interdrv        # 主芯片外设驱动
50        ├── mpp             # mpp源码
51        └── osal            # 操作系统适配层

4.3. 一键编译Linux系统#

提示

如果没有特别说明,本章节中Linux系统的编译命令都在osdrv目录下执行。

4.3.1. 选择板级配置文件#

由于不同存储类型,不同DDR容量、不同系统都要设置不同的编译参数,配置项众多。

为了便于用户使用,添加了配置文件选择机制。将配置参数写入预设的板级配置文件中,只需要在编译前选择不同的配置文件,就可以直接编译出对应方案的镜像了。

在osdrv目录中执行 ./lunch 命令

 1# 配置文件选择命令
 2./lunch
 3
 4# 根据提示信息,输入配置文件对应的数字
 5==================================================
 6启动存储:EMMC/SPI-NAND/SPI-NOR
 7内存类型:LPDDR4x-4GB/LPDDR4x-8GB
 8板卡名称:Hi3403
 9系统类型:Ubuntu/Buildroot
10==================================================
11请选择一个 BoardConfig 文件:
121) BoardConfig-EMMC-LPDDR4x_4GB-Hi3403-Buildroot.mk
132) BoardConfig-EMMC-LPDDR4x_4GB-Hi3403-Ubuntu_Lite.mk
143) BoardConfig-EMMC-LPDDR4x_8GB-Hi3403-Buildroot.mk
154) BoardConfig-EMMC-LPDDR4x_8GB-Hi3403-Ubuntu_Lite.mk
16输入数字选择: 0
17已选择 BoardConfig.mk -> BoardConfig-EMMC-LPDDR4x_4GB-Hi3403-Buildroot.mk
../../_images/boardconfig-6.6.png

配置文件选择完成。如果想查看当前的配置文件,可以用 ls -al 命令查看osdrv目录下BoardConfig.mk指向的配置文件

以下是配置文件中各配置项的说明:

备注

文档可能更新不及时,以 osdrv/BoardConfig/BoardConfig配置说明 中的内容为准。

 1# Target CHIP
 2# 目标芯片,默认为ss928v100
 3export CHIP=
 4
 5# Kernel config
 6# 内核配置文件,编译内核时使用
 7export KERNEL_CFG=
 8
 9# Target rootfs: buildroot/ubuntu
10# 目标根文件系统,可选buildroot、ubuntu
11export TARGET_ROOTFS=
12
13# Target version: ubuntu: lite/xfce
14# 根文件系统版本,仅在TARGET_ROOTFS=ubuntu时有效,可选lite、xfce
15export TARGET_VERSION=
16
17# set rootfs type: ubifs/jffs2/ext4
18# 根文件系统镜像分区格式,支持ubifs(nand-flash)、jffs2(nor-flash)、ext4(emmc)
19export ROOTFS_TYPE=
20
21# Set buildroot config only TARGET_ROOTFS=buildroot
22# buildroot配置文件,编译buildroot时使用,仅在TARGET_ROOTFS=buildroot时有效
23export BUILDROOT_CFG=
24
25# Target boot medium: spi(Nand/Nor)/emmc
26# 目标存储芯片,可选spi(Nand-flash/Nor-flash)或emmc
27export BOOT_MEDIA=
28
29# Nand chip size
30# 生成镜像适配SPI_NAND的大小,仅在ROOTFS_TYPE=ubifs时有效。
31# 设置多个值表示同时生成多个对应的下载配置文件和env镜像,中间用英文字符逗号隔开。
32# 目前仅支持128M和256M两个值可供配置,不配置则使用默认值
33export NAND_CHIPSIZE=128M,256M
34
35# U-boot xlsm
36# u-boot配置文件表格,不建议修改
37export REGBIN_XLSM=
38
39# mpp module and lib install rootfs: smp/a55_linux/mpp/out
40# mpp模块和库,设置为yes则安装到根文件系统中
41export HI_MPP_KO_LIB=
42
43# mpp sample enable when HI_MPP_KO_LIB=yes: smp/a55_linux/mpp/sample
44# mpp示例程序,设置为yes则安装到根文件系统中
45export HI_MPP_SAMPLE=
46
47# lvgl project enable
48# lvgl示例程序,设置为yes则安装到根文件系统中
49export LVGL_PROJECT=

4.3.2. 一键编译命令#

配置文件选择完成之后,可以使用一键编译命令来构建系统镜像,将会自动构建boot、env、kernel和rootfs镜像。

在osdrv目录下执行下面的命令

1# 一键编译命令
2make

以BoardConfig-EMMC-LPDDR4x_4GB-Hi3403-Buildroot.mk为例,编译完成后生成的镜像文件保存在osdrv/pub/ss928v100_emmc_image_glibc目录下。

文件名称

说明

boot_image_4GB.bin

boot镜像(GSL+U-Boot)

emmc_burn_table.xml

烧录工具分区配置表

emmc_env.bin

env分区镜像

rootfs_ss928v100_buildroot.ext4

ext4格式buildroot根文件系统镜像

u-boot-ss928v100.bin

U-Boot镜像

uImage_ss928v100

kernel镜像(ATF+uImage+dtb)

以上编译生成的文件仅针对当前配置方案,更详细的生成文件列表请查看 分区镜像文件说明

镜像烧录方法请查看: 系统镜像烧录 章节

4.4. 分区镜像编译#

当我们修改SDK的部分内容后需要重新编译生成镜像,如果还是完整的去编译SDK会耗费很多时间, 此时可以单独编译修改的部分生成镜像,来增加开发效率。

一键编译命令 章节中生成的镜像文件,有4个文件用于板卡烧录,对应存储中的4个分区:

  • boot镜像:boot_image.bin

  • env镜像:env.bin

  • kernel镜像:uImage_ss928v100

  • rootfs镜像:rootfs_ss928v100.ext4

下面对各分区镜像的作用和编译步骤做详细说明

4.4.1. boot镜像编译#

boot镜像包含GSL和U-Boot两部分,用于一步一步初始化芯片,最后启动内核。

当芯片上电后,先运行位于固化在芯片内部的代码BootROM,进行最基础的初始化,并根据启动模式配置加载对应存储中的GSL运行。

GSL根据U-boot表格(uboot寄存器配置表格)中的寄存器配置继续对DDR、时钟、引脚等外设进行初始化,然后加载U-boot并运行。

到U-Boot就能更全面的对系统外设进行初始化了,并支持一些高级操作,如网络通信、存储设备读写等。一切准备就绪,U-Boot将内核镜像加载到内存中,然后跳转到内核开始启动内核。

整个过程从BootROM → GSL → U-Boot → 内核,像阶梯一样逐级完成初始化,我们通常将BootROM到内核启动之间的全部阶段统称为BootLoader。

在osdrv目录下执行下面的命令构建boot镜像

1make gslboot_build

在osdrv/Makefile中可以看到

1prepare:                        # 准备工作
2regbin_prepare:                 # 将U-boot寄存器配置表格转换为{chip}_reg_info.bin
3boot: prepare regbin_prepare    # 编译U-Boot源码,生成u-boot-{chip}.bin
4gslboot_build: boot             # 编译gsl源码,生成gsl.bin,然后将这三个文件合并成一个boot镜像boot_image.bin

根据 Makefile 的语法规则,冒号前的名称是目标(target),冒号后的内容是该目标的依赖(prerequisites)。 在执行某个目标之前,Make 会自动先执行它的所有依赖。

在执行gslboot_build时,会先执行他的依赖boot,而boot又依赖于prepare和regbin_prepare。

所以运行 make gslboot_build 命令的完整流程是 prepare regbin_prepare boot gslboot_build

U-Boot和GSL代码一般不用修改,uboot表格仅在修改ddr配置或初始引脚复用时修改。在SDK开发过程中,相对来说很少修改boot相关的内容。

4.4.2. env镜像编译#

我们将U-Boot的环境变量打包成一个镜像,在U-Boot中对env镜像中保存的环境变量自动读取,可以更灵活的对U-Boot环境变量进行设置,方便用户使用。

在osdrv目录下执行下面的命令构建env镜像

1make uboot_env

查看osdrv/Makefile中的 uboot_env: prepare 可知,当我们执行命令时, 会根据存储的类型和存储的大小将u-boot环境变量(env)从文本转换成可直接烧写的二进制镜像env.bin, 并根据env中的bootargs的分区信息生成烧录工具分区配置文件burn_table.xml。

此工具的路径是osdrv/tools/pc/uboot_env,其中env_text目录下保存的是原始的env文本文件, 当我们想要修改默认的u-boot环境变量时可以修改对应的文本文件并重新生成env镜像进行烧录。

烧录env镜像可以给U-boot传递预先定义好的U-Boot环境变量,如果我们在板卡运行时需要修改, 还可以通过串口登录到U-boot命令行终端,使用命令进行修改。

U-boot环境变量相关的命令如下:

 1# 打印当前环境变量
 2printenv
 3
 4# 新增或修改环境变量
 5setenv [变量名] [变量值]
 6
 7# 删除环境变量
 8setenv [变量名]
 9
10# 保存环境变量
11saveenv

4.4.3. kernel镜像编译#

Linux 内核(Linux Kernel)在整个操作系统中是核心组件,它介于硬件和应用程序之间,负责管理系统资源、提供底层服务、实现硬件抽象,是软件与硬件沟通的桥梁。

在Linux系统开发过程中,我们经常要对内核功能进行裁剪,为硬件添加驱动支持、为软件提供运行环境,所以需要经常修改并编译内核。

在osdrv目录下执行下面的命令构建kernel镜像

1make atf

在osdrv/Makefile中可以看到

1prepare:            # 准备工作
2kernel: prepare     # 编译内核源码并生成内核镜像uImage
3atf: kernel         # 编译atf,并将生成的文件与uImage一起打包为完整的kernel镜像uImage_{chip}

需要注意的是,当我们修改内核配置文件时:

  • 将配置项设置为[y]:对应代码会直接编译进内核镜像uImage

  • 将配置项设置为[m]:对应代码会被编译成独立的内核模块(.ko)

上面命令生成的uImage_{chip}镜像中不包含被编译为模块[m]的驱动,在编译内核时这些模块会单独生成,需要放在rootfs的/usr/lib/modules目录中,由系统在启动时按需加载。

所以在修改内核代码后要注意,需要更新内核镜像还是更新rootfs中的ko文件。

除了上面编译kernel镜像的命令外,还有几个辅助命令可以提高效率:

1# 修改内核配置文件(完整命令)
2make kernel_menuconfig
3
4# 修改内核配置文件(简短命令)
5make kconfig
6
7# 清理内核
8make kernel_clean

4.4.4. rootfs镜像构建#

rootfs(Root File System,根文件系统)是Linux用户空间的基础环境,包含系统运行所需的程序、库和配置文件。 内核启动后会挂载rootfs,并在其中启动用户空间的第一个进程。因此,我们在Linux系统上的所有用户操作(包括执行命令、运行程序、文件管理等)都是在rootfs环境中进行的。

在开发过程中,如果我们希望将某些配置文件、脚本、驱动模块(.ko)或应用程序预置到rootfs镜像中,就必须重新构建rootfs才能将这些内容打包进去。

以Buildroot系统为例,由于它不支持在线包管理,所有的软件包和文件内容都需要在构建时选定并打包,因此在开发过程中需要频繁重新构建 rootfs。

在osdrv目录下执行下面的命令构建rootfs镜像

1make rootfs_build

除了上面编译kernel镜像的命令外,还有几个辅助命令可以提高效率:

 1# 构建ubuntu根文件系统基础压缩包
 2make ubuntu
 3
 4
 5# 构建buildroot根文件系统基础压缩包
 6make buildroot
 7
 8# 清理buildroot
 9make buildroot_clean
10
11# 修改buildroot配置文件(完整命令)
12make buildroot_menuconfig
13
14# 修改buildroot配置文件(简短命令)
15make bconfig

在osdrv/Makefile中可以看到

 1prepare:
 2rootfs_prepare: prepare
 3
 4kernel: prepare
 5
 6TARGET_ROOTFS=ubuntu或buildroot
 7ubuntu: prepare rootfs_prepare
 8buildroot: prepare rootfs_prepare
 9
10secure_libs:
11reg_tools: rootfs_prepare secure_libs
12
13TARGET_ALL=hi_mpp、lvgl
14hi_mpp:
15lvgl:
16
17rootfs_build: rootfs_prepare kernel $(TARGET_ROOTFS) reg_tools $(TARGET_ALL)

根据Makefile的规则整理一下,当我们运行 make rootfs_build 时流程如下:

  1. prepare:创建工作目录

  2. rootfs_prepare:清理rootfs构建目录,创建工作目录

  3. kernel:编译内核模块

  4. $(TARGET_ROOTFS):根据TARGET_ROOTFS的值,运行对应的根文件系统构建命令、安装内核模块、处理目录路径

  5. secure_libs:生成libsecurec.a安全函数库供reg_tools使用

  6. rootfs_build:将生成的命令工具打包进行rootfs,并按照存储类型生成rootfs镜像

  7. $(TARGET_ALL):根据配置文件中的配置项,编译额外的组件添加到rootfs中

$(TARGET_ROOTFS)是核心操作,根据变量值的不同,调用对应的根文件系统构建脚本,生成基础的根文件系统压缩包。

$(TARGET_ALL)则是根据配置文件中的配置项,追加不同的目标到rootfs_build,来实现对rootfs功能的裁剪。

4.4.5. 分步构建注意事项#

  • 分步构建ubuntu rootfs时,为了增加构建效率,默认会使用已经构建好的历史版本的ubuntu基础根文件系统压缩包。 如果修改了除mk-base-ubuntu.sh之外的文件,则需要删除ubuntu-jammy-lite-arm64-rootfs.tar.gz, 如果修改了mk-base-ubuntu.sh,则还需要删除ubuntu-base-lite-arm64-${date}.tar.gz。 删除open_source/ubuntu中的上述文件后再执行 make ubuntumake rootfs_build 来重新构建ubuntu基础根文件系统压缩包。