4. Linux6.6_SDK编译¶
4.1. 获取源码¶
从网盘资源 4-SDK源码压缩包 中获取最新日期的LubanCat_Hi3403_Linux6.6_SDK源码压缩包,使用下面的命令将源码压缩包解压到当前用户的家目录,方便后续操作。
1 2 3 4 5 6 7 8 9 10 11 | # 将源码压缩包移动到用户家目录,xxxxxxxx为源码压缩包发布日期
mv LubanCat_Hi3403_Linux6.6_SDK_xxxxxxxx.tgz ~/LubanCat_Hi3403_Linux6.6_SDK.tgz
# 进入用户家目录
cd ~
# 解压源码压缩包
tar -xf LubanCat_Hi3403_Linux6.6_SDK.tgz
# 进入SDK源码目录
cd ~/LubanCat_Hi3403_Linux6.6_SDK
|
如图所示,解压后的源码各文件夹。
4.2. SDK目录介绍¶
提示
以下目录结构不需要深入了解,只需要在修改对应项目时找得到即可。
SDK源码目录结构,部分路径需要再编译后才会出现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | .
├── open_source # SDK使用到的第三方开源项目源码
│ ├── buildroot # Buildroot目录
│ │ ├── buildroot-2024.02.10 # Buildroot源码
│ │ ├── buildroot-2024.02.10.tar.gz # Buildroot源码压缩包
│ │ ├── dl # Buildroot下载的源码压缩包保存位置
│ │ ├── Makefile # Buildroot项目的Makefile,对接SDK的Makefile
│ │ ├── overlay # Buildroot根文件系统配置文件覆盖层
│ │ ├── readme.txt # Buildroot源码压缩包下载说明
│ │ └── ss928_lbc_defconfig # Buildroot编译时的配置文件
│ ├── linux # Linux内核
│ │ ├── linux-6.6.86.patch # Linux内核补丁
│ │ ├── linux-6.6.y # Linux内核源码目录
│ │ ├── Makefile # Linux项目的Makefile,对接SDK的Makefile
│ │ └── readme.txt # Linux源码下载说明
│ ├── lvgl # LVGL图形框架
│ │ ├── lv_port_linux # LVGL的Linux系统适配接口
│ │ │ └── lvgl # LVGL源码目录
│ │ └── Makefile # LVGL的Makefile,对接SDK的Makefile
│ ├── mbedtls # 加密库
│ ├── trusted-firmware-a # 可信固件
│ ├── u-boot # U-Boot
│ └── ubuntu # Ubuntu根文件系统构建脚本
├── osdrv # 操作系统相关目录
│ ├── BoardConfig # 板级配置文件目录
│ │ └── BoardConfig配置说明 # 配置项说明文件
│ ├── components
│ │ ├── boot # boot相关工具
│ │ │ ├── gsl # GSL源码
│ │ │ └── image_map # boot镜像制作工具
│ │ └── secure_c # 安全函数库源码
│ ├── lunch # 板级配置选择脚本
│ ├── Makefile # SDK编译入口
│ ├── pub # 编译生成的镜像等文件存放位置
│ └── tools # 系统工具源码
│ ├── board # 板卡工具
│ │ └── reg-tools-1.0.0 # 寄存器读写工具、i2c读写工具
│ └── pc # 编译机工具
│ ├── kdf_customer
│ ├── nand_production
│ ├── rootfs_tools # 根文件系统镜像打包脚本
│ ├── uboot_env # env镜像制作工具
│ └── uboot_tools
│ ├── regbin-v1.0.2 # regbin转换工具,将xlsm格式的u-boot表格转换为bin文件
│ └── SS928V100_LubanCat_LPDDR4x_3733M-8GB_32bitx2-A55_1400M-emmc.xlsm # u-boot表格,寄存器配置表
├── README_zh.md
└── smp # smp目录
└── a55_linux # arm核代码
├── interdrv # 主芯片外设驱动
├── mpp # mpp源码
└── osal # 操作系统适配层
|
4.3. 一键编译Linux系统¶
提示
如果没有特别说明,本章节中Linux系统的编译命令都在osdrv目录下执行。
4.3.1. 选择板级配置文件¶
由于不同存储类型,不同DDR容量、不同系统都要设置不同的编译参数,配置项众多。
为了便于用户使用,添加了配置文件选择机制。将配置参数写入预设的板级配置文件中,只需要在编译前选择不同的配置文件,就可以直接编译出对应方案的镜像了。
在osdrv目录中执行 ./lunch 命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 配置文件选择命令
./lunch
# 根据提示信息,输入配置文件对应的数字
==================================================
启动存储:EMMC/SPI-NAND/SPI-NOR
内存类型:LPDDR4x-4GB/LPDDR4x-8GB
板卡名称:Hi3403
系统类型:Ubuntu/Buildroot
==================================================
请选择一个 BoardConfig 文件:
1) BoardConfig-EMMC-LPDDR4x_4GB-Hi3403-Buildroot.mk
2) BoardConfig-EMMC-LPDDR4x_4GB-Hi3403-Ubuntu_Lite.mk
3) BoardConfig-EMMC-LPDDR4x_8GB-Hi3403-Buildroot.mk
4) BoardConfig-EMMC-LPDDR4x_8GB-Hi3403-Ubuntu_Lite.mk
输入数字选择: 0
已选择 BoardConfig.mk -> BoardConfig-EMMC-LPDDR4x_4GB-Hi3403-Buildroot.mk
|
配置文件选择完成。如果想查看当前的配置文件,可以用 ls -al 命令查看osdrv目录下BoardConfig.mk指向的配置文件
以下是配置文件中各配置项的说明:
注解
文档可能更新不及时,以 osdrv/BoardConfig/BoardConfig配置说明 中的内容为准。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | # Target CHIP
# 目标芯片,默认为ss928v100
export CHIP=
# Kernel config
# 内核配置文件,编译内核时使用
export KERNEL_CFG=
# Target rootfs: buildroot/ubuntu
# 目标根文件系统,可选buildroot、ubuntu
export TARGET_ROOTFS=
# Target version: ubuntu: lite/xfce
# 根文件系统版本,仅在TARGET_ROOTFS=ubuntu时有效,可选lite、xfce
export TARGET_VERSION=
# set rootfs type: ubifs/jffs2/ext4
# 根文件系统镜像分区格式,支持ubifs(nand-flash)、jffs2(nor-flash)、ext4(emmc)
export ROOTFS_TYPE=
# Set buildroot config only TARGET_ROOTFS=buildroot
# buildroot配置文件,编译buildroot时使用,仅在TARGET_ROOTFS=buildroot时有效
export BUILDROOT_CFG=
# Target boot medium: spi(Nand/Nor)/emmc
# 目标存储芯片,可选spi(Nand-flash/Nor-flash)或emmc
export BOOT_MEDIA=
# Nand chip size
# 生成镜像适配SPI_NAND的大小,仅在ROOTFS_TYPE=ubifs时有效。
# 设置多个值表示同时生成多个对应的下载配置文件和env镜像,中间用英文字符逗号隔开。
# 目前仅支持128M和256M两个值可供配置,不配置则使用默认值
export NAND_CHIPSIZE=128M,256M
# U-boot xlsm
# u-boot配置文件表格,不建议修改
export REGBIN_XLSM=
# mpp module and lib install rootfs: smp/a55_linux/mpp/out
# mpp模块和库,设置为yes则安装到根文件系统中
export HI_MPP_KO_LIB=
# mpp sample enable when HI_MPP_KO_LIB=yes: smp/a55_linux/mpp/sample
# mpp示例程序,设置为yes则安装到根文件系统中
export HI_MPP_SAMPLE=
# lvgl project enable
# lvgl示例程序,设置为yes则安装到根文件系统中
export LVGL_PROJECT=
|
4.3.2. 一键编译命令¶
配置文件选择完成之后,可以使用一键编译命令来构建系统镜像,将会自动构建boot、env、kernel和rootfs镜像。
在osdrv目录下执行下面的命令
1 2 | # 一键编译命令
make
|
以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镜像
1 | make gslboot_build
|
在osdrv/Makefile中可以看到
1 2 3 4 | prepare: # 准备工作
regbin_prepare: # 将U-boot寄存器配置表格转换为{chip}_reg_info.bin
boot: prepare regbin_prepare # 编译U-Boot源码,生成u-boot-{chip}.bin
gslboot_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镜像
1 | make 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 2 3 4 5 6 7 8 9 10 11 | # 打印当前环境变量
printenv
# 新增或修改环境变量
setenv [变量名] [变量值]
# 删除环境变量
setenv [变量名]
# 保存环境变量
saveenv
|
4.4.3. kernel镜像编译¶
Linux 内核(Linux Kernel)在整个操作系统中是核心组件,它介于硬件和应用程序之间,负责管理系统资源、提供底层服务、实现硬件抽象,是软件与硬件沟通的桥梁。
在Linux系统开发过程中,我们经常要对内核功能进行裁剪,为硬件添加驱动支持、为软件提供运行环境,所以需要经常修改并编译内核。
在osdrv目录下执行下面的命令构建kernel镜像
1 | make atf
|
在osdrv/Makefile中可以看到
1 2 3 | prepare: # 准备工作
kernel: prepare # 编译内核源码并生成内核镜像uImage
atf: kernel # 编译atf,并将生成的文件与uImage一起打包为完整的kernel镜像uImage_{chip}
|
需要注意的是,当我们修改内核配置文件时:
将配置项设置为[y]:对应代码会直接编译进内核镜像uImage
将配置项设置为[m]:对应代码会被编译成独立的内核模块(.ko)
上面命令生成的uImage_{chip}镜像中不包含被编译为模块[m]的驱动,在编译内核时这些模块会单独生成,需要放在rootfs的/usr/lib/modules目录中,由系统在启动时按需加载。
所以在修改内核代码后要注意,需要更新内核镜像还是更新rootfs中的ko文件。
除了上面编译kernel镜像的命令外,还有几个辅助命令可以提高效率:
1 2 3 4 5 6 7 8 | # 修改内核配置文件(完整命令)
make kernel_menuconfig
# 修改内核配置文件(简短命令)
make kconfig
# 清理内核
make kernel_clean
|
4.4.4. rootfs镜像构建¶
rootfs(Root File System,根文件系统)是Linux用户空间的基础环境,包含系统运行所需的程序、库和配置文件。 内核启动后会挂载rootfs,并在其中启动用户空间的第一个进程。因此,我们在Linux系统上的所有用户操作(包括执行命令、运行程序、文件管理等)都是在rootfs环境中进行的。
在开发过程中,如果我们希望将某些配置文件、脚本、驱动模块(.ko)或应用程序预置到rootfs镜像中,就必须重新构建rootfs才能将这些内容打包进去。
以Buildroot系统为例,由于它不支持在线包管理,所有的软件包和文件内容都需要在构建时选定并打包,因此在开发过程中需要频繁重新构建 rootfs。
在osdrv目录下执行下面的命令构建rootfs镜像
1 | make rootfs_build
|
除了上面编译kernel镜像的命令外,还有几个辅助命令可以提高效率:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # 构建ubuntu根文件系统基础压缩包
make ubuntu
# 构建buildroot根文件系统基础压缩包
make buildroot
# 清理buildroot
make buildroot_clean
# 修改buildroot配置文件(完整命令)
make buildroot_menuconfig
# 修改buildroot配置文件(简短命令)
make bconfig
|
在osdrv/Makefile中可以看到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | prepare:
rootfs_prepare: prepare
kernel: prepare
TARGET_ROOTFS=ubuntu或buildroot
ubuntu: prepare rootfs_prepare
buildroot: prepare rootfs_prepare
secure_libs:
reg_tools: rootfs_prepare secure_libs
TARGET_ALL=hi_mpp、lvgl
hi_mpp:
lvgl:
rootfs_build: rootfs_prepare kernel $(TARGET_ROOTFS) reg_tools $(TARGET_ALL)
|
根据Makefile的规则整理一下,当我们运行 make rootfs_build 时流程如下:
prepare:创建工作目录
rootfs_prepare:清理rootfs构建目录,创建工作目录
kernel:编译内核模块
$(TARGET_ROOTFS):根据TARGET_ROOTFS的值,运行对应的根文件系统构建命令、安装内核模块、处理目录路径
secure_libs:生成libsecurec.a安全函数库供reg_tools使用
rootfs_build:将生成的命令工具打包进行rootfs,并按照存储类型生成rootfs镜像
$(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 ubuntu或make rootfs_build来重新构建ubuntu基础根文件系统压缩包。
