TinaSDK Linux Kernel 基本使用(全志T113开发板)

TinaSDK Linux Kernel 基本使用(全志T113开发板)

本文基于全志Tina-SDK,详细介绍如何配置、编译、修改Linux内核,涵盖内核源码位置、设备树、环境变量、Kconfig/menuconfig配置、打印等级调整、打包烧录等完整流程。你将会学到:在Tina-SDK中单独编译内核、用make kernel_menuconfig裁剪/配置内核、修改内核打印级别、打包生成镜像并烧录验证。文末附面试高频题。


文章目录

    • [TinaSDK Linux Kernel 基本使用(全志T113开发板)](#TinaSDK Linux Kernel 基本使用(全志T113开发板))
    • [一、Tina-SDK Linux系统启动流程简介](#一、Tina-SDK Linux系统启动流程简介)
    • 二、内核源码与设备树的位置
      • [2.1 内核源码目录](#2.1 内核源码目录)
      • [2.2 板级内核配置文件(defconfig片段)](#2.2 板级内核配置文件(defconfig片段))
      • [2.3 板级设备树文件(board.dts)](#2.3 板级设备树文件(board.dts))
    • 三、环境变量(bootargs)配置
    • 四、设备树打包与U-Boot中的fdt切换
      • [4.1 boot_package.cfg 描述设备树位置](#4.1 boot_package.cfg 描述设备树位置)
      • [4.2 U-Boot中切换生效的设备树](#4.2 U-Boot中切换生效的设备树)
    • 五、单独编译Linux内核
      • [5.1 准备环境](#5.1 准备环境)
      • [5.2 执行单独编译](#5.2 执行单独编译)
    • [六、Kconfig 配置方法(menuconfig 使用详解)](#六、Kconfig 配置方法(menuconfig 使用详解))
      • [6.1 进入内核配置界面](#6.1 进入内核配置界面)
      • [6.2 菜单符号含义](#6.2 菜单符号含义)
      • [6.3 实际操作示例:进入 Device Drivers 并理解符号](#6.3 实际操作示例:进入 Device Drivers 并理解符号)
      • [6.4 修改选项:以 Multimedia support 为例](#6.4 修改选项:以 Multimedia support 为例)
      • [6.5 查看选项依赖关系(Help界面)](#6.5 查看选项依赖关系(Help界面))
      • [6.6 搜索功能(/ 键)](#6.6 搜索功能(/ 键))
      • [6.7 实战任务:调整内核默认打印等级(从7改为4)](#6.7 实战任务:调整内核默认打印等级(从7改为4))
    • 七、打包内核生成最终烧录镜像
    • 八、烧录与验证
      • [8.1 烧录方式](#8.1 烧录方式)
      • [8.2 验证内核打印等级](#8.2 验证内核打印等级)
    • 九、面试官提问环节
    • 十、总结

一、Tina-SDK Linux系统启动流程简介

在全志T113平台中,整个系统从上电到应用运行的顺序为:

boot0 → optee → uboot → env → linux → dtb → dsp → rootfs → app

  • boot0:一级引导程序,初始化DDR等。
  • optee:可信执行环境(可选)。
  • uboot:U-Boot引导加载程序。
  • env:U-Boot环境变量。
  • linux:内核镜像(zImage / uImage)。
  • dtb:设备树二进制。
  • dsp:数字信号处理器固件(如有)。
  • rootfs:根文件系统。
  • app:用户应用程序。

理解这个顺序有助于排查启动卡在哪个阶段。


二、内核源码与设备树的位置

在Tina-SDK中,内核源码和设备树配置都位于特定目录,SDK提供了快捷命令方便跳转。

2.1 内核源码目录

路径 :lichee/linux-5.4

bash

复制代码
# 进入SDK根目录后
cd lichee/linux-5.4

快捷命令 :在source build/envsetup.sh之后,任意目录下执行 ckernel 即可直接跳转到内核源码根目录。

bash

复制代码
source build/envsetup.sh
lunch 4   # 选择t113_100ask-tina
ckernel
pwd
# 输出:/home/ubuntu/tina-d1-h/lichee/linux-5.4

2.2 板级内核配置文件(defconfig片段)

路径 :device/config/chips/t113/configs/100ask/linux/config-5.4

这个文件是T113百问网开发板的内核配置文件 (实际是一个config fragment,与通用配置合并生成最终.config)。

快捷命令 :执行 ccconfigs 会直接进入该目录。

bash

复制代码
ccconfigs
ls
# board.dts  config-5.4  config-5.4-mem-optimize

2.3 板级设备树文件(board.dts)

路径 :device/config/chips/t113/configs/100ask/board.dts(实际是一个软链接指向 linux-5.4/board.dts)

bash

复制代码
ls -l board.dts
# board.dts -> linux-5.4/board.dts

该设备树文件包含 了父级芯片设备树 sun8iw20p1.dtsi,其完整路径为:

bash

复制代码
lichee/linux-5.4/arch/arm/boot/dts/sun8iw20p1.dtsi

快捷命令 :执行 cdts 可直接跳转到内核源码下的设备树目录。

bash

复制代码
cdts
pwd
# /home/ubuntu/tina-d1-h/lichee/linux-5.4/arch/arm/boot/dts

注意:board.dts 是最终板级设备树,其中通过 #include "sun8iw20p1.dtsi" 引入基础定义,然后追加或覆盖板级特性。


三、环境变量(bootargs)配置

内核启动命令行(bootargs)由U-Boot环境变量传递。在Tina-SDK中,默认启动参数定义在文件:

路径 :device/config/chips/t113/configs/100ask/env.cfg

打开该文件,你会看到以下关键片段:

bash

复制代码
#kernel command arguments
earlyprintk=sunxi-uart,0x02500C00
initcall_debug=0
console=ttyS3,115200
nand_root=/dev/ubiblock0_5
mmc_root=/dev/mmcblk0p5
mtd_name=sys
rootfs_type=squashfs
root_partition=rootfs
boot_partition=boot
init=/sbin/init
loglevel=8
cma=8M
...

# 定义nand启动时的bootargs
setargs_nand=setenv bootargs ubi.mtd=${mtd_name} ubi.block=0,${root_partition} earlyprintk=${earlyprintk} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${nand_root} rootfstype=${rootfs_type} init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1

# 定义mmc启动时的bootargs
setargs_mmc=setenv bootargs earlyprintk=${earlyprintk} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${mmc_root} init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1

# U-Boot自身配置
bootdelay=1
bootcmd=run setargs_nand boot_normal

重要参数解读:

  • console=ttyS3,115200:调试串口为UART3,波特率115200。
  • loglevel=8:内核打印级别最高(所有信息都输出)。
  • root=/dev/ubiblock0_5 或 /dev/mmcblk0p5:根文件系统所在分区。
  • rootwait(隐含在setargs中):等待设备就绪。
  • bootdelay=1:U-Boot倒计时1秒。

修改env.cfg后需要重新编译打包才会生效。也可以在U-Boot命令行中临时修改并保存。


四、设备树打包与U-Boot中的fdt切换

4.1 boot_package.cfg 描述设备树位置

文件 device/config/chips/t113/configs/default/boot_package.cfg 包含了打包时要合并的各个组件:

bash

复制代码
[package]
item=u-boot, u-boot.fex
item=optee, optee.fex
item=scp, scp.fex
item=logo, bootlogo.bmp.lzma
item=shutdowncharge, bempty.bmp.lzma
item=androidcharge, battery_charge.bmp.lzma
item=dtb, sunxi.fex

其中 item=dtb, sunxi.fex 表示设备树文件会被打包为 sunxi.fex,在U-Boot启动时会加载该设备树。

4.2 U-Boot中切换生效的设备树

U-Boot启动过程中,可能会使用两份设备树:一份是U-Boot自己的(用于驱动显示、存储等),另一份是内核设备树。在U-Boot命令行中,可以使用 set_working_fdt 命令切换当前生效的设备树(用于调试)。

bash

复制代码
=> set_working_fdt 0x7bebee58
change working_fdt 0x7be8ee58 to 0x7bebee58

这通常用于在烧录前验证设备树修改是否正确。


五、单独编译Linux内核

在Tina-SDK中,单独编译内核非常方便,使用 mkernel 命令即可。

5.1 准备环境

每次新开终端,都需要先加载环境:

bash

复制代码
source build/envsetup.sh
lunch
# 选择 4. t113_100ask-tina

如果之前编译过且有缓存问题,建议先清理:

bash

复制代码
make clean   # 清理整个SDK的编译产物

然后重新 lunch 选择正确的单板。

5.2 执行单独编译

bash

复制代码
mkernel

mkernel 会根据当前配置:

  • 合并板级配置文件(device/config/.../config-5.4)和通用配置,生成最终.config
  • 交叉编译内核,生成zImage(或uImage)和设备树
  • 自动挂载模块编译(如果需要)
  • 最后生成用于打包的内核镜像

编译成功时你会看到类似的结束信息:

bash

复制代码
#### make completed successfully (25 seconds) ####

注意 :mkernel 只会编译内核及设备树,不会重新编译U-Boot、rootfs等,因此非常快(几秒到半分钟)。如果你修改了内核Kconfig配置,它会自动检测并重新生成.config。


六、Kconfig 配置方法(menuconfig 使用详解)

这是本节最重要的技能:如何通过图形化菜单修改内核配置。

6.1 进入内核配置界面

bash

复制代码
make kernel_menuconfig

你会看到类似下面的菜单(蓝底白字):

6.2 菜单符号含义

在菜单中,每个选项前有不同的符号,表示该选项的状态和可能的操作。

符号 含义 操作键
[ ] 未选中(不编译) 按 Y 变为 [*];按 N 保持
[*] 编译进内核(built-in) 按 N 变为 [ ];按 M 变为 <M>(如果支持)
<M> 编译为模块(module) 按 Y 变为 [*];按 N 变为 [ ]
< > 未选中,但支持模块 按 Y 变为 [*];按 M 变为 <M>
-*- 被其他选项强制选中,无法修改 需查看依赖关系
-M- 被其他选项强制选为模块 需查看依赖关系

操作键:

  • Y:选中为 built-in
  • M:选中为 module(如果支持)
  • N:排除
  • 空格:循环切换(适用部分情形)
  • ?:查看当前选项的帮助信息(包括依赖关系)

6.3 实际操作示例:进入 Device Drivers 并理解符号

在 menuconfig 主界面,选择 Device Drivers ---> 回车进入。

你会看到很多驱动类目,有些前面是 < >,有些是 [ ],还有些是 <M>。例如:

text

复制代码
< >   Memory Technology Device (MTD) support
<*>   Block devices
[ ]   Network device support
<M>   USB support
  • < > MTD support:未选中,但可以编为模块。
  • <*> Block devices:已选中且为 built-in。
  • [ ] Network device support:未选中,且不支持模块(只能 built-in或排除)。
  • <M> USB support:已选为模块。

6.4 修改选项:以 Multimedia support 为例

使用方向键 移动到 Multimedia support 行。目前可能是 [ ] 或 < >。按下 空格 键或 Y 键:

  • 第一次按 空格:变为 <M>(模块)。
  • 第二次按 空格:变为 [*](built-in)。
  • 第三次按 空格:变回 [ ](排除)。

也可以直接按 Y 变成 [*],按 M 变成 <M>,按 N 变成 [ ]。

6.5 查看选项依赖关系(Help界面)

如果遇到某个选项是灰色的或者前面是 -*-(被强制选中),你可以查看它的依赖项。选中该选项后按 ? 键(或选择下方的 <Help>)。

例如 Hardware Monitoring support 选项,进入其 Help 页面会显示:

在这里插入图片描述

text

复制代码
Symbol: HWMON [=y]
Type : boolean
Prompt: Hardware Monitoring support
Location:
    -> Device Drivers
(1)   -> Hardware Monitoring support
  Depends on: HAS_IOMEM [=y]
  Selected by: SENSORS_ABITUGURU3 [=n] && HWMON [=y] ...

这告诉你:该选项依赖于 HAS_IOMEM,并且被其他选项(如 SENSORS_ABITUGURU3)选择。如果你试图取消它,需要先取消那些选中它的选项。

6.6 搜索功能(/ 键)

当你不确定某个配置项在哪里时,可以使用搜索。在 menuconfig 界面按 / 键,弹出搜索框。

例如搜索 icn6202(一款LCD驱动IC),输入后回车:

text

复制代码
Search Results
Symbol: LCD_SUPPORT_ICN6202 [=y]
Location:
  -> Device Drivers
    -> Graphics support
      -> Frame buffer Devices
        -> Video support for sunxi
          -> LCD support icn6202 panel (LCD_SUPPORT_ICN6202)

按对应的数字(比如 1)即可直接跳转到该选项位置。

6.7 实战任务:调整内核默认打印等级(从7改为4)

需求:降低内核默认控制台打印级别,减少启动时的冗余信息。

步骤:

  1. 在 menuconfig 中按 / 键,搜索 printk。
  2. 你会看到多个结果:
    • Enable support for printk(基本支持,保持y)
    • Delay each boot printk message(不重要)
    • Early printk(用于调试,保持y)
    • 关键项:CONFIG_MESSAGE_LOGLEVEL_DEFAULT
  3. 选择 CONFIG_MESSAGE_LOGLEVEL_DEFAULT,回车进入位置(在 Kernel hacking → printk and dmesg options)。
  4. 你会看到一行:

text

复制代码
(7) Default message log level (1-7)
  1. 按回车,将 7 改为 4,然后按 OK。
  2. 保存配置(退出时选择保存为 .config)。

修改后的效果:内核默认控制台打印级别从 KERN_WARNING (4) 变成了 KERN_ERR (3) 等更低级别,启动信息会大幅减少。

注意:loglevel 内核启动参数可以运行时覆盖;但修改默认值可以避免每个板子都要加参数。


七、打包内核生成最终烧录镜像

内核编译完成后(无论是否修改配置),执行打包命令:

bash

复制代码
pack

pack 命令会:

  • 收集 U-Boot、optee、内核镜像、设备树、rootfs 等
  • 按照分区表(sys_partition.fex)打包成单个 .img 文件
  • 最终输出路径类似:

text

复制代码
/home/ubuntu/tina-d1-h/out/t113-100ask/tina_t113-100ask_uart3.img

打包成功后,尾部会显示:

text

复制代码
pack finish

使用 ls -lh 可看到镜像大小(约43MB)。

bash

复制代码
ls -lh out/t113-100ask/tina_t113-100ask_uart3.img
# -rwxrwxr-x 1 ubuntu ubuntu 43M Mar 12 07:37 ...img

可以通过 VMware 拖拽、共享文件夹或 scp 将此镜像复制到 Windows,然后使用 PhoenixSuit 或 PhoenixCard(推荐线刷)烧录到开发板的 SPI NAND 或 TF 卡。


八、烧录与验证

8.1 烧录方式

  • 线刷(推荐) :使用 PhoenixSuit 将 tina_t113-100ask_uart3.img 烧录进 SPI NAND。开发板需进入烧录模式(按住烧录键然后上电)。
  • TF卡方式:使用 PhoenixCard 制作启动卡。

具体步骤参考官方文档或视频。

8.2 验证内核打印等级

启动开发板,进入系统后,执行:

bash

复制代码
cat /proc/sys/kernel/printk

输出四个数字,分别代表:当前控制台日志级别、默认消息日志级别、最低控制台日志级别、默认控制台日志级别。

如果你将 CONFIG_MESSAGE_LOGLEVEL_DEFAULT 改为4,那么第二个数字应该是4。实际输出示例:

text

复制代码
8    4    1    7

说明当前控制台级别仍是8(可能被内核命令行参数覆盖),但默认消息级别已变成4。若想令 quiet 生效,可以在U-Boot中修改 loglevel 环境变量。


九、面试官提问环节

第1问:Tina-SDK中如何单独编译Linux内核?用什么命令?

参考答案 :

使用 mkernel 命令。前提是需要先 source build/envsetup.sh 和 lunch 选择正确的单板。mkernel 只编译内核,不重新编译U-Boot和根文件系统,大大提高调试效率。


第2问:在内核配置 make kernel_menuconfig 中,选项前的 <*>、<M>、[ ] 分别代表什么?如何修改?

参考答案:

  • <*>:该功能编译进内核(built-in),内核镜像包含了它,无法卸载。
  • <M>:编译为内核模块(module),生成 .ko 文件,可动态加载/卸载。
  • [ ]:排除,不编译该功能。

使用 Y 键变为 <*>,M 键变为 <M>,N 键变为 [ ]。某些选项只支持 built-in 或排除,没有 <M>。


第3问:如果某个配置选项是灰色的无法修改,如何查看它的依赖关系?

参考答案 :

选中该选项后按 ? 键(或选择界面下方的 <Help>)。在帮助页面中,可以看到 Depends on 和 Selected by 信息。灰色表示依赖条件不满足(比如 depends on XXX 未选中),或者被其他选项强制选中。需要先修改那些依赖项或取消选中它的上游选项。


第4问:在 make kernel_menuconfig 中如何快速定位一个驱动选项(例如 icn6202)?

参考答案 :

按 / 键进入搜索模式,输入关键词 icn6202,搜索结果会列出匹配的符号及其路径。按对应数字可直接跳转到该选项所在位置。


第5问:内核默认的 printk 打印级别如何修改?修改后如何验证?

参考答案 :

进入 make kernel_menuconfig → Kernel hacking → printk and dmesg options → Default message log level (1-7),将值从7改为所需数字(例如4)。保存配置,重新编译内核并烧录。启动后执行 cat /proc/sys/kernel/printk,观察第二个数字是否变为修改的值。


十、总结

本文覆盖了Tina-SDK中Linux内核开发的完整流程:

  • 熟悉内核源码、设备树、环境变量的存放位置及快捷命令。
  • 学会单独编译内核(mkernel)。
  • 掌握 make kernel_menuconfig 修改配置:符号含义、依赖查看、搜索功能、打印级别调整。
  • 打包(pack)、烧录、验证。

这些技能是嵌入式Linux工程师的必备基础,在实际工作中会频繁使用。建议你在开发板上反复练习,直至能够熟练裁剪内核、调试启动参数。

相关推荐
雯宝11 小时前
mnt_init 函数
linux
律宏阔17 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔17 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴17 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千17 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei3717 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei3717 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei3717 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
judezh17 小时前
api 容器一直 unhealthy?我把一个 Agent 运行时的健康检查逐条拆了,查出四个问题
运维·docker
GeW17 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux