T113S3系统移植(基于T113S3 TinaSDK5.0V1.2)

一、启动介质和启动框架

1. 启动介质确认 (Hardware Boot)

  • 逻辑:板载Flash选用W25N01GVZEIG,1Gbit,是SPI NAND FLASH所以基于 evb1_auto_nand 方案,明确硬件通过 SPI NAND 启动
  • 支撑:确保板子 BOOT 引脚电平正确,且 sys_config.fex 中的 storage_type = 5(SPI NAND)。

2. Init 启动框架切换 (Software Init)

  • 问题:由于我们选择方案时选用的是 evb1_auto_nand openwrt方案,此方案默认采用的是openwrtprocd启动,不便在 <sdk_dir>/openwrt/target/t113/<自己的方案> 目录下的 busybox-init-base-files 文件夹中的一些自动加载驱动脚本设置,故我们需要先将openwrt系统默认启动方式设置为busybox启动

  • 操作:(默认已经source build/envsetup.sh并且lunch完毕)

    • croot路径下执行:make menuconfig
    • 将procd-init修改为busybox-init
    • 进入Base system选项,取消procd勾选
    • 选中 Customize busybox init base files options ,会识别到target中自定义板卡配置文件夹
    • 取消选中setusbconfig
    • 保存退出后重新编译

二、方案原型克隆和注册自己的方案

第一步:硬件方案克隆 (device 目录)

核心动作:

cd <sdk_dir>/device/config/chips/t113/configs
cp -r evb1_auto_nand <your_board_name>
vim <your_board_name>/sys_config.fex

原理解析: 在全志的架构里,device/ 目录存放的是纯硬件的描述(比如 U-Boot 怎么起、引脚怎么分配、分区表怎么切)。

  • 为什么选 evb1_auto_nand 因为你的硬件使用的是 SPI NAND Flash。克隆这个目录,意味着你继承了原厂经过严格测试的 NAND 时序和驱动配置,能最大程度避免底层存储报错。
  • sys_config.fex 的作用:你把 machine 改成 custom_board,这相当于给你的板子发了一张“身份证”。后续全志独有的打包工具(pack)在生成镜像时,就是靠匹配这个名字来寻找对应的硬件配置文件的。如下
;---------------------------------------------------------------------------------
; version:版本1.00
; machine:板级文件名
;---------------------------------------------------------------------------------
[product]
version = "100"
machine = "<your_board_name>"

板级方案添加完成,后续外设调试涉及的文件修改将在 custom_board 目录下完成

第二步:系统文件目录克隆 (openwrt/target 目录)

核心动作: 建立并配置 OpenWrt 编译靶点。

cd <sdk_dir>/openwrt/target/t113
cp t113-evb1_auto_nand t113-<your_board_name> -r
cd t113-<your_board_name>
mv t113_evb1_auto_nand.mk t113_<your_board_name>.mk
vim t113_<your_board_name>.mk 
  • 修改t113_<your_board_name>.mk文件
$(call inherit-product-if-exists, target/allwinner/t113-common/t113-common.mk)

PRODUCT_PACKAGES +=

PRODUCT_COPY_FILES +=

PRODUCT_AAPT_CONFIG := large xlarge hdpi xhdpi
PRODUCT_AAPT_PERF_CONFIG := xhdpi
PRODUCT_CHARACTERISTICS := musicbox

PRODUCT_BRAND := allwinner
PRODUCT_NAME := t113_<your_board_name>
PRODUCT_DEVICE := t113-<your_board_name>
PRODUCT_MODEL := Allwinner t113 <your_board_name> board
  • 修改 defconfigdefconfig_ota 文件(打包openwrt文件系统使用的默认配置)
vim defconfig 
vim defconfig_ota

内容如下主要修改板名

#
# Automatically generated file; DO NOT EDIT.
# OpenWrt Configuration
#
CONFIG_MODULES=y
CONFIG_HAVE_DOT_CONFIG=y
# CONFIG_TARGET_t113_awol_evb1 is not set
# CONFIG_TARGET_t113_dev is not set
# CONFIG_TARGET_t113_evb1 is not set
# CONFIG_TARGET_t113_evb1_auto is not set
CONFIG_TARGET_t113_<your_board_name>=y
# CONFIG_TARGET_t113_evb1_auto_nor is not set
# CONFIG_TARGET_t113_pro is not set
CONFIG_TARGET_t113_<your_board_name>_Default=y
CONFIG_TARGET_BOARD="t113-<your_board_name>"
  • 修改 TinaProducts.mk 文件:
vim TinaProducts.mk
#
# Copyright (C) 2013 The Android Open-Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/t113_<your_board_name>.mk
  • 修改 vendorsetup.sh 文件
vim vendorsetup.sh
add_lunch_combo t113-<your_board_name>
  • 修改 Makefile文件:
vim Makefile
#
# Copyright (C) 2013-2016 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk

ARCH:=arm
BOARD:=t113-<your_board_name>
BOARDNAME:=t113-<your_board_name>
FEATURES:=fpu dt
CPU_TYPE:=cortex-a7
CPU_SUBTYPE:=neon
MAINTAINER:=Allwinner

KERNEL_PATCHVER:=5.4
UBOOT_PATCHVER:=2018
KERNELNAME:=zImage dtbs

include $(INCLUDE_DIR)/target.mk

TinaProducts.mkvendorsetup.sh

  • 这两个文件是 Android 风格编译系统的残留(Tina 融合了 Android 的 envsetup 和 OpenWrt 的底层)。它们的作用是把你的板卡名称暴露给全局环境,让你在敲 lunch 时能看到选项 2

第三步:环境初始化与方案选择 (envsetup.sh & lunch)

核心动作: 注入环境变量并锁定编译上下文。 原理解析:

  • source build/envsetup.sh:这不是简单的运行脚本,source(或 .)意味着将脚本里的变量和函数注入到你当前的终端窗口里。执行完这句,你的终端就拥有了超能力,多出了 croot(回到根目录)、cout(去输出目录)、pack(打包)等快捷命令。
  • lunch 2: 当你选择 t113-<your_board_name> 后,终端打印了一大堆 Log(比如 Prepare toolchainkernel defconfig: generate ...)。在这个瞬间,后台干了三件大事:
    1. 找到了交叉编译工具链的路径。
    2. 提取了 device 目录下的内核默认配置(config-5.4),将其复制到 out/.../kernel/build/.config 中。
    3. 将所有的路径变量(TINA_TOPDIR, TARGET_BOARD 等)设置完毕。

第四步:编译与打包 (make & pack)

核心动作: 生成二进制文件并合成最终固件。 原理解析:

  • make -j1 V=s
    • 这是 OpenWrt 最经典的单步调试编译命令。
    • -j1:强制使用单核单线程编译。如果你用 -j8 多线程编译,一旦某个组件报错,错误信息会被其他线程的输出淹没。首次编译新方案,强烈建议用 -j1,排错最准。
    • V=s:Verbose = stdout。打印出所有的编译细节和警告信息。
    • 它干了什么:它会依次编译 Toolchain(交叉编译器)、U-Boot、Kernel(生成 zImagedtb),最后编译所有的用户态软件包(生成 rootfs)。
  • pack 命令
    • 编译出来的 U-Boot、内核和文件系统是零散的文件。pack 是全志特有的打包脚本。
    • 它会读取你第一步修改的 sys_config.fexsys_partition.fex,计算分区大小,给镜像加上全志特有的文件头(Boot0、TOC0/TOC1 等),最后将它们全部“缝合”成一个可以直接用 PhoenixSuit 烧录到 NAND Flash 里的 t113_linux_<your_board_name>_uart0.img 镜像包。

三、核心硬件抽象层适配 (U-Boot & Kernel)

主要工作目录:<sdk_dir>/device/config/chips/t113/configs/<your_board_name>

ubuntu@ubuntu1804:~/tina5_sdk/T113-Tina5.0-V1.2/device/config/chips/t113/configs/custom_sym_board$ tree -L 2
.
├── bin
│   └── amp_dsp0.bin
├── board.dts -> linux-5.4/board.dts
├── bootlogo.bmp
├── bootlogo.bmp.old
├── boot-resource
│   └── bootlogo.bmp
├── bsp
│   ├── env.cfg
│   └── sys_partition.fex
├── buildroot
│   ├── BoardConfig.mk
│   ├── env.cfg
│   └── sys_partition.fex
├── linux-5.4
│   ├── board.dts
│   └── config-5.4
├── openwrt
│   ├── BoardConfig.mk
│   ├── env.cfg
│   └── sys_partition.fex
├── sys_config.fex
└── uboot-board.dts

6 directories, 17 files

核心硬件全局配置层 (Global Hardware Config)

这部分文件是整个板子的“总纲”,跨越了 Bootloader 和 Kernel,由全志专属的打包工具(pack)直接读取。

  • sys_config.fex
    • 专业解析:全志平台特有的硬件描述文件(FEX 格式)。它比 Linux 设备树(Device Tree)生效更早,是整个系统上电后第一道关卡,主要被 Boot0(SPL)和 U-Boot 解析与执行。
    • 核心功能:作为早期引导阶段的“硬件总闸”。根据当前板级配置,它主要负责四大核心任务:
      1. 确立启动介质:声明系统默认的存储类型(storage_type = 5,即锁定为 SPI NAND 启动)。
      2. 初始化内存:定义 DRAM 的运行频率(792MHz)、类型及几十项精细的阻抗与时序参数([dram_para]),确保主核能正确在内存中跑代码。
      3. 绑定调试通道:指定 Boot 阶段的底层调试串口([uart_para] 配置为 UART3 及 PB06/PB07 引脚),确保上电第一秒就能输出 Log。
      4. 配置刷机与测试接口:初始化用于量产烧录的 SD 卡控制器([card0_boot_para])以及底层的 JTAG 硬件调试接口([jtag_para])。
    • 适配重点:当你更换了不同容量/型号的内存颗粒、更改了存储芯片类型(如换成 eMMC),或者需要修改底层 Debug 串口位置时,必须优先修改此文件。
  • board.dts -> linux-5.4/board.dts
    • 专业解析:这是一个软链接(Symlink),指向底层特定内核版本里的设备树文件。
    • 核心功能:方便开发者在主目录下直接 vim board.dts 进行修改,而不需要每次都进入深深的内核目录。

Bootloader 与底层引导层 (Boot & Early Init)

决定了 U-Boot 阶段的硬件状态和视觉呈现。

  • uboot-board.dts
    • 专业解析:U-Boot 阶段专属的设备树源文件(Device Tree Source)。现代 U-Boot 引入了类似 Linux 内核的驱动模型(Driver Model),它不再强依赖代码中的硬件宏定义,而是通过解析这个独立的文件来识别和配置硬件。
    • 核心功能:为引导阶段提供最关键的底层驱动资源地图。结合源码,其核心功能分为三块:
      1. 存储总线挂载:初始化了 TF 卡/SD 卡 (&sdc0, &sdc2)、SPI NOR/NAND Flash (&spi0) 以及原始 NAND Flash (&nand0) 的引脚复用和控制器。这保证了 U-Boot 能顺利从对应介质中读取内核镜像。
      2. 显示系统先期点亮 (Early Display):包含了 &disp (显示引擎) 和 &lcd0 节点的完整配置。在这里,指定了屏幕驱动 (fl7707n_mipi)、MIPI DSI 的 4-lane 引脚、以及详细的时序参数(如 lcd_ht, lcd_vt 等)。正是有了这段配置,U-Boot 才能在进入内核前提前点亮屏幕并显示开机 Logo。
      3. 安全与内存保护:通过顶部的 firmware/optee 节点,为可信执行环境(TEE)划分了专用的安全共享内存(SHM)区域,保障系统的安全引导。
    • 适配重点
      • 启动介质变更:如果板子修改了 SPI 接口的引脚或换了存储芯片,必须在此文件修正 spi0_pins 并在 &target 节点中检查 storage_type
      • 屏幕更换这是一个高频踩坑点! 如果你更换了屏幕面板,不仅要在 Linux 内核设备树(board.dts)中修改参数,必须同时在这个文件中同步更新 &lcd0 的所有时序参数(hbp, vbp 等)和 Reset 引脚 (lcd_gpio_0)。如果两边参数不一致,会导致开机有 Logo,但进入内核瞬间黑屏或花屏的诡异现象。
  • bootlogo.bmp / bootlogo.bmp.old / boot-resource/bootlogo.bmp
    • 专业解析:开机第一屏的位图图像资源。
    • 核心功能:打包时,pack 工具会将这些 BMP 图片压入启动镜像包中。系统上电几百毫秒内,U-Boot 会直接将此图片推送到 Framebuffer 中显示。
  • bin/amp_dsp0.bin
    • 专业解析:T113 芯片内置了一颗 HiFi4 DSP(数字信号处理器),用于音频处理或实时算力卸载。
    • 核心功能:这是提供给 DSP 运行的裸机或 RTOS 固件(AMP 异构多核架构)。系统启动时,主核 Cortex-A7 会将这个 bin 文件加载到特定内存区域并唤醒 DSP。

Linux 内核配置层 (Kernel Domain)

进入 Linux 操作系统后,这里是硬件描述和底层驱动配置的**“总闸门”**。

  • linux-5.4/board.dts
    • 专业解析:Linux 内核真正的板级设备树文件。它彻底接管了 U-Boot 传递过来的硬件控制权,并以节点(Node)树的形式,向 Linux 内核极其详细地描述了所有外设的物理属性。
    • 核心功能:结合本方案源码,其核心功能体现在四大模块的深度定制:
      1. 外设驱动的实体化 (User Define):包含开发者自定义的硬件绑定。例如通过 GPIO 控制的心跳指示灯(led_sys on PD11)、带 20ms 消抖的用户独立按键(User Key on PD10),以及 256 级细腻调光的 PWM 背光通道(pwm 7)。
      2. 显示与触摸子系统:详细定义了 fb0 的分辨率(720x1424),挂载了 fl7707n_mipi 屏幕驱动及 &dsi4lane_pins 引脚复用;同时在 &twi1(I2C1)总线上挂载了 gt9xxnew_ts 触摸屏控制器,并分配了唤醒(PE4)和中断(PE5)引脚。
      3. USB 角色与通信:配置了 &usbc0 为 OTG 模式(usb_port_type = <0x2>),并绑定了 PE12 作为 VBUS/ID 状态检测引脚,这是实现后续 ADB 通信的物理基础。
      4. 异构多核内存映射:通过 reserved-memory 节点,为 T113 内部的 HiFi4 DSP(dsp0)和 RISC-V 协处理器划分了专用的物理内存区域和共享环形缓冲区(Vring),实现了基于 RPMSG 框架的核间通信。
    • 适配重点这是 BSP 工程师每天打交道最多的文件。 解决引脚冲突(同一 Pin 被多处占用)、适配屏幕时序、修改 I2C 从设备地址(如触摸屏的 reg = <0x5d>),全部在这里完成。
  • linux-5.4/config-5.4
    • 专业解析:内核的系统“菜单”快照(Defconfig 文件)。它记录了执行 make kernel_menuconfig 后的最终选择,直接决定了内核编译时哪些代码会参与构建。
    • 核心功能:统筹内核的驱动集与系统特性。在当前方案中:
      1. 模块化驱动加载 (=m):将 XR819/XR829/RTL8723DS Wi-Fi 驱动以及 GT9XX 触摸驱动编译为外置的 .ko 模块,方便在应用层通过脚本动态加载,优化了开机速度。
      2. 核心驱动内置 (=y):将显示引擎(DISP2_SUNXI)、MIPI 屏幕驱动(LCD_SUPPORT_FL7707N_MIPI)、PWM 背光直接编入内核,确保屏幕在开机第一梯队被点亮。
      3. 现代 USB Gadget 框架:开启了 CONFIG_USB_CONFIGFS 及其子宏(ADB、HID、FS),配合全志特有的 SUNXI_USB_MANAGER,使得通过脚本动态切换 USB 模式成为可能。
    • 适配重点(排坑提示):当前配置中 CONFIG_DEBUG_INFO=y 处于开启状态,这会生成庞大的带调试信息的内核镜像。如果在后续打包 SPI NAND(通常容量仅 128MB)时遇到 pack fail(固件体积过大),必须首选关闭此宏进行内核瘦身。另外,底层的低级调试串口已精准锁定为 CONFIG_DEBUG_SUNXI_UART3=y,保障了内核崩溃时的 Log 输出。

文件系统与构建环境层 (OS & Build System Domains)

Tina SDK 支持多种文件系统方案,因此在 configs/custom_sym_board/ 下会看到 bspbuildrootopenwrt 三个并列的文件夹。目前使用的是 openwrt 目录。

为什么这几个文件要分开放?因为不同的操作系统,其镜像大小和环境变量需求完全不同! 以下是你当前 OpenWrt 方案的核心配置解析:

  • openwrt/sys_partition.fex (分区表)
    • 专业解析:固件烧录时的物理存储分区地图。全志的打包工具 pack 会严格按照这个文件来切割 Flash 空间,并将编译好的二进制文件塞入对应的区域。
    • 核心功能与源码印证
      1. 逻辑大小分配:NAND 方案特有的 size 单位是“逻辑擦除块”的换算值。例如 rootfs 分区分配了 50400
      2. 双备份机制:定义了 envenv-redund 两个大小同为 504 的环境变量分区,这与之前配置的 UBI 双备份卷机制完美契合,防止掉电变砖。
      3. 用户数据区:预留了 rootfs_data(25200)和不限制大小的 UDISKuser_type = 0x8100),用于存放用户自己的应用数据或日志。
    • 适配重点:如果开启了大量内核 Debug 宏或装了太多 OpenWrt 软件包,导致 pack 时报错 size too large,必须来这里调大对应分区的 size,同时确保后面的分区不越界。
  • openwrt/env.cfg (环境变量)
    • 专业解析:U-Boot 传递给 Linux 内核的“第一句话”。系统上电后,U-Boot 会读取这个文件并执行里面的命令。
    • 核心功能与源码印证
      1. 控制台重定向console=ttyS3,115200loglevel=8 确保内核启动信息从物理 UART3 引脚全量输出。
      2. 根文件系统挂载nand_root=/dev/ubiblock0_5rootfstype=squashfs。这明确告诉内核:去第 5 个 UBI 块设备上,以只读压缩格式(SquashFS)挂载根目录。
      3. 启动命令流 (bootcmd):这是 U-Boot 的最终执行动作。代码中的 bootcmd=run setargs_nand boot_normal,表示先设置 NAND 启动的环境变量(setargs_nand),然后执行 boot_normal(将 boot 分区的镜像读入内存地址 43000000 并启动)。
    • 适配重点:如果修改了调试串口(比如改回 ttyS0),必须在这里同步修改 console= 的值,否则内核启动后串口将无输出。
  • openwrt/BoardConfig.mk (构建统筹配置)
    • 专业解析:Tina 编译框架的板级总纲。当你执行 lunch 选择方案时,构建系统会读取这个文件来确定所需的编译器和核心组件版本。
    • 核心功能与源码印证
      1. 内核与 U-Boot 绑定:声明内核使用 config-5.4,U-Boot (Brandy 2.0) 使用 sun8iw20p1_custom_sym_board_defconfig
      2. 环境变量空间LICHEE_REDUNDANT_ENV_SIZE:=0x20000(128KB),这与 sys_partition.fex 中分配给 env 分区的实际大小以及 /etc/fw_env.config 中的配置是严格对应的。
      3. 编译器指定:强制使用 gcc-linaro-5.3.1 交叉编译链。
    • 适配重点:如果需要更换内核版本(比如升级到 Linux 5.10),或者更换 U-Boot 的 defconfig 文件,必须在此处修改对应的 LICHEE_KERN_DEFCONF 等变量。

外设适配的流程

在通读了上述所有底层架构和配置文件后,我们在日常开发中进行任何外设适配(屏幕、触摸、Wi-Fi 等),都应严格遵循: 看原理图明确引脚 -> 修改设备树(描述硬件) -> menuconfig 勾选驱动(使能软件) -> 编译烧录验证。

如果系统原生已经包含了驱动,我们只需改设备树和勾选菜单;但如果遇到像 FL7707 MIPI 屏幕 这种全志原厂 SDK 未自带的非标外设,我们就需要进行驱动级移植

以下结合 FL7707 屏幕的移植过程,演示“无中生有”添加新驱动的标准流程:

1. 驱动源码注入 (Code Injection)

由于我需要在开机阶段显示 Logo,且在进入系统后持续显示,因此 U-Boot 和 Kernel 两端都必须移植该屏幕的驱动

  • U-Boot 端路径:通过 croot 回到根目录后,进入 <sdk>/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd
  • Kernel 端路径:进入 <sdk>/kernel/linux-5.4/drivers/video/fbdev/sunxi/disp2/disp/lcd
  • 动作:在这两个目录下,分别新建 fl7707n_mipi.cfl7707n_mipi.h 文件,并将屏幕厂商提供的初始化序列代码填入其中。
2. 构建系统注册 (Makefile & Kconfig)

放入了 .c 源码,编译系统是不知道的。必须修改同级目录下的构建文件,将其暴露给菜单。

  • 修改 Makefile: 在 Makefile 中添加编译规则,告诉编译器如果宏被打开,就把源码编译成 .o 文件:
disp-$(CONFIG_LCD_SUPPORT_FL7707N_MIPI) += lcd/fl7707n_mipi.o
  • 修改 Kconfig: 在 Kconfig 中添加菜单选项,让开发者能在界面里看到它:
config LCD_SUPPORT_FL7707N_MIPI
    bool "LCD support FL7707N_MIPI panel"
    default n
    help
        If you want to support FL7707N_MIPI panel for display driver, select it.
3. 配置菜单使能 (Menuconfig Activation)

源码和编译规则就绪后,接下来就是打开这个总闸。

  • U-Boot 配置:在<sdk_dir>/brandy/brandy-2.0/u-boot-2018/configs目录下找到你的方案所选中的defconfig文件并添加 CONFIG_LCD_SUPPORT_FL7707N_MIPI=y
  • Kernel 配置:执行 make kernel_menuconfig,在 Device Drivers -> Graphics support -> Frame buffer Devices -> Video support for sunxi -> LCD panels select 中勾选刚才添加的屏幕,并确保背光(Backlight)、触摸(Touchscreen)等相关依赖宏(如 CONFIG_BACKLIGHT_CLASS_DEVICE=y)也一并开启。
4. 设备树参数绑定 (DTS Binding)

最后一步,让设备树中的参数与你刚写的驱动“接头”。

  • 进入 uboot-board.dtsboard.dts
  • &lcd0 节点中,将 lcd_driver_name 严格设定为你刚才添加的驱动名:
&lcd0 {
    lcd_used        = <1>;
    lcd_driver_name = "fl7707n_mipi"; // 必须与源码中注册的名称一致
    lcd_if          = <4>;            // MIPI DSI 接口
    // ... 同步填入正确的时序参数 (hbp, vbp, width, height 等)
};

四、文件系统构建与运行环境初始化 (OpenWrt & Init Layer)

主要工作目录:<sdk_dir>/openwrt/target/t113/t113-<your_board_name>/

ubuntu@ubuntu1804:~/tina5_sdk/T113-Tina5.0-V1.2/openwrt/target/t113/t113-custom_sym_board$ tree -L 1
.
├── base-files
├── BoardRules.mk
├── busybox-init-base-files
├── busybox-init-base-files_generate
├── defconfig
├── defconfig_ota
├── Makefile
├── modules.mk
├── swupdate
├── t113_custom_sym_board.mk
├── tina_busybox-init-base-files.mk
├── TinaProducts.mk
└── vendorsetup.sh

4 directories, 9 files

ubuntu@ubuntu1804:~/tina5_sdk/T113-Tina5.0-V1.2/openwrt/target/t113/t113-custom_sym_board/busybox-init-base-files$ tree -L 3
.
├── bin
│   └── setusbconfig
├── data
├── etc
│   ├── asound.conf
│   ├── fw_env.config
│   ├── hostname
│   ├── init.d
│   │   ├── load_script.conf
│   │   ├── rc.final
│   │   ├── rc.modules
│   │   ├── rc.preboot
│   │   └── wifideamon
│   ├── inittab
│   ├── profile
│   ├── udhcpd.conf
│   └── wpa_supplicant.conf
├── home
├── mnt
│   ├── extsd
│   └── sdcard
├── squashfs
└── usr
    ├── bin
    └── lib
        ├── libbz2.so
        ├── libbz2.so.1.0
        ├── libmbedcrypto.so
        ├── libmbedcrypto.so.3
        ├── libmbedtls.so
        ├── libmbedtls.so.11
        ├── libmbedx509.so
        ├── libmbedx509.so.0
        └── libwpa_client.so
        
12 directories, 22 files

第一部分:构建系统与包管理控制台 (外层目录)

这层目录不参与板子的实际运行,它是给**编译器(Build System)**看的,决定了最终生成的固件(rootfs)里包含什么内容。

  • defconfig & defconfig_ota (系统菜单快照)
    • 专业解析:系统软件包的“采购清单”。当你执行 make menuconfig 并在 Base systemNetwork 等菜单中勾选了某些工具(如 adbwpa_supplicant)后,所有的选择最终都会沉淀并保存在这两个文件中。
    • 适配重点:如果系统缺命令(如敲 ifconfig 提示 command not found),第一反应就应该来这里检查对应的包有没有被选上。
  • modules.mk (内核模块打包规则)
    • 专业解析:内核 .ko 模块进入文件系统的“通行证”。你在 kernel_menuconfig 中将某个驱动编译成模块(=m),它仅仅会生成在内核目录下。想要让它随系统打包进 /lib/modules/ 并在开机时加载,必须在这里显式声明。
    • 源码印证:从提供的源码中可以看到两个核心模块的注册:
      1. 摄像头驱动 (sunxi-vin-n5_dvp):不仅声明了需要拷贝 videobuf2-memops.ko 等 5 个底层驱动文件,还用 KCONFIG 锁定了它对 CONFIG_MEDIA_SUPPORT 等内核宏的强制依赖。
      2. Wi-Fi 驱动 (net-rtl8723ds):声明了拷贝 8723ds.ko,更重要的是使用了 AUTOLOAD:=$(call AutoProbe,8723ds)。这句魔法代码告诉 OpenWrt 系统:不仅要把驱动打包进去,还要在开机时自动调用 modprobe 去加载它!
    • 适配重点高频踩坑点! 如果你发现内核编译出了 .ko 但板子里找不到,或者开机不会自动加载(比如你的 Wi-Fi 或触摸屏不工作),一定要来这里检查是否写漏了 $(eval $(call KernelPackage,xxx))
  • .mk 家族与构建骨架 (t113_custom_sym_board.mk, TinaProducts.mk)
    • 专业解析:编译框架的“粘合剂”与目标定义。
    • 源码印证
      • t113_custom_sym_board.mk 中极其关键的一句:PRODUCT_DEVICE := t113-custom_sym_board。这不仅是板子的名字,更是编译系统在 target/ 目录下寻址文件夹的唯一依据
      • TinaProducts.mk 则是 Android 编译系统的遗留产物,负责将上述 .mk 文件抛出给全局的 Makefile 树。
  • vendorsetup.sh
    • 专业解析:编译环境注册脚本。
    • 作用:里面只有一行代码 add_lunch_combo t113-custom_sym_board。执行 source build/envsetup.sh 后,它负责把你的方案挂到 lunch 的交互式选择菜单里。
  • tina_busybox-init-base-files.mk (自定义 Init 脚本生成器)
    • 专业解析:当我们将系统启动方式从 procd 切换为 busybox init 后,这个 Makefile 负责执行 hook 脚本(rootfs_hook_squash.sh)。
    • 作用:它会在编译的最后阶段,动态生成并清理 busybox-init-base-files 目录下的 /etc/init.d/ 脚本群(如你源码中注释掉的 S40networkS50usb 等),从而确保最终的根文件系统拥有干净、定制化的启动逻辑。
  • swupdate/
    • 专业解析:OTA 升级策略目录。
    • 作用:里面存放了 sw-description 等文件,定义了在双分区备份架构(如前面 sys_partition.fex 中划分的两个 env 分区)下,系统如何校验并安全地覆写远程下发的固件。

第二部分:文件系统骨架与开机脚本 (内层目录)

目录位置: .../busybox-init-base-files/

核心概念(Overlay 覆盖机制): 这个目录是一个“覆盖层”。编译时,这里面的所有文件会原封不动地、按照同等目录结构,直接拷贝到最终板子的根目录(/)下,覆盖掉 OpenWrt 原生的默认文件。

1. 系统生命周期控制 (etc/)

这是整个嵌入式系统启动的“大纲”。

  • etc/inittab
    • 专业解析:内核启动后接管系统的第一个配置文件。
    • 作用:它告诉 BusyBox 的 init 进程:开机先去执行 rc.preboot,最后把命令行的控制台(Shell)抛给哪个物理串口(例如 ttyS3)。
  • etc/init.d/ (启动脚本三部曲)
    • rc.preboot:最先执行。主要挂载 sysfsprocfs 等虚拟文件系统,初始化最基础的环境。
    • rc.modules重中之重! 按照顺序执行 insmod 来加载底层驱动(例如你的触摸屏 gt9xxnew_ts.ko 和 Wi-Fi 8723ds.ko)。
    • rc.final:开机前的临门一脚。通常在这里执行 amixer 设置音频通路音量,或者执行 setusbconfig adb 拉起调试服务。
2. 系统外围配置 (etc/)
  • etc/fw_env.config
    • 专业解析:U-Boot 与 Linux 的“翻译官”。
    • 作用:告诉 Linux 系统的 fw_printenv 命令,去 NAND Flash 的哪个物理块读取 U-Boot 的环境变量。没有它,Linux 下无法读写启动参数。
  • etc/wpa_supplicant.conf & udhcpd.conf
    • 作用:前者配置 Wi-Fi 的连接账号、密码和 Socket 路径;后者配置板子做 AP 热点时,给其他设备分配 IP 的 DHCP 服务器规则。
  • etc/asound.conf
    • 作用:ALSA 声卡的高级路由配置,比如软件混音或重采样。
3. 预编译二进制与动态库 (bin/ & usr/lib/)
  • bin/setusbconfig
    • 作用:全志提供的一个现成的二进制小工具。你在 rc.final 里就是调用它,通过操作 ConfigFS 快速把 USB 接口切换成 ADB 或 U 盘模式的。
  • usr/lib/ (如 libmbedtls.so, libwpa_client.so)
    • 专业解析:预置的共享动态链接库。
    • 作用:有些底层库(如 MbedTLS 加密库,供 Wi-Fi 使用)编译太慢或有特定的版本依赖,原厂直接把编译好的 .so 文件放在这里,打包时直接塞入固件,省去了重新编译的麻烦。

附录:BSP 硬核调试工具箱速查表

调试维度核心命令 / 工具集专业功能定义结合 T113 LVGL 智能面板项目的实战应用
源码编译配置检索`find . -name “*.mk”xargs grep -Hn “xxx”`构建规则与宏定义追踪:在高度耦合的 Makefile 树中执行深层文本匹配,定位内核宏或编译选项的声明位置。
方案版本控制git diff --no-index <Dir_A> <Dir_B>跨目录树差异比对:在脱离 Git 仓库的物理目录间进行逐行代码比对。Init 框架迁移验证:在将启动方式从 procd 切换至 busybox init 时,对比原 evb1 方案与 custom_sym_boardbusybox-init-base-files 差异,确认自启脚本覆盖情况。
打包流程校验`cat out/…/pack_out/sys_config.fexgrep lcd`固件打包前置校验:直接读取 pack 工具汇聚后的中间产物,验证硬件描述配置(FEX)的最终合成状态。
硬件级寄存器操作devmem <物理地址> [位宽] [值]物理内存与寄存器直接寻址:绕过内核保护机制,直接读写 SoC 内部控制寄存器。 (注:越界操作会引发 Kernel Panic)Pin Mux 硬件状态核验:若怀疑 board.dts 中的引脚复用未生效,直接读取 T113 手册中 PD20(LCD Reset)或 PD22(PWM7)的寄存器基地址,验证硬件层面的输入/输出状态及电平。
I2C 总线通信i2cdetect -y -r <总线号> i2cdump / i2cgetI2C 设备枚举与通信验证:扫描指定 I2C 总线上的从设备地址,验证时钟与数据线的电气连通性。GT9xx 触摸屏排障:在 LVGL 缺少触摸反馈时,扫描 T113 的 &twi1 (I2C1)。若显示 5d,证明 I2C 硬件通信正常;若显示 UU,证明该地址已被 gt9xxnew_ts.ko 驱动成功接管。
ALSA 音频链路aplay -l / arecord amixer音频子系统底层路由控制:脱离应用层(如 GStreamer/PulseAudio),直接控制 Codec 芯片的 DAC/ADC 增益及数据流。中控语音提示调试:在使用 LVGL 播放按键音前,先通过 amixer 设置底层通道,解除 DAC 静音状态并分配 HPOUT 路由,随后用 aplay 直接播放测试音频,隔离应用层错误。
网络栈与带宽wifi -o sta -c "SSID" "PWD" iperf -c <IP> -t 10WLAN 协议栈激活与吞吐量评估:在终端拉起 wpa_supplicant 进行鉴权,并通过 TCP/UDP 流量打压测试 SDIO 接口性能。OTA 及远程资源就绪:依赖 rc.modules 加载的 8723ds.ko 连接无线路由。通过 iperf 测试吞吐量,评估后续 LVGL 界面从网络拉取天气数据或进行整机 OTA 固件下载的网络可靠性。
USB 主从枚举lsusb adb kill-server / devicesUSB 总线拓扑分析与守护进程管理:查看设备枚举状态,重启上位机 ADB Server 清理僵尸进程及权限。无线/有线调试桥建立:验证 rc.final 中的 setusbconfig adb,hid 命令。确认 T113 的 OTG 接口(PE12 ID 引脚检测)成功作为 Device 被上位机识别(VID:18d1 PID:d002),为后续 adb push LVGL 编译产物提供通道。
内核态运行追踪`dmesggrep -i panel lsmod`内核环形缓冲区日志过滤与模块依赖审查:提取驱动 Probe 阶段的警告/错误上下文,确认 LKM(可加载内核模块)的驻留状态。
GPIO 伪驱动控制echo 118 > /sys/class/gpio/exportSysfs 虚拟文件系统 IO 控制:利用内核导出的 sysfs 节点,强行改变 GPIO 方向与电平,替代传统的硬连线测试。背光电路物理验证:当屏幕背光不亮时,绕过 PWM 软件驱动,将 PD22(118号引脚)强制配置为 out 并拉高至 1,以此区分是 T113 芯片端无输出,还是背光升压电路硬件损坏。
显示子系统同步cat /sys/class/disp/disp/attr/sys显示控制器(DE)状态查询:获取 Display Engine 的垂直同步(vsync)、图层(Layer)配置及硬件报错统计。LCD 时序握手诊断:在 LVGL 应用程序启动前,读取该节点确认 T113 的 DISP 模块是否在持续输出 vsync 信号,判定主板控制器与 FL7707 屏幕接口的物理同步状态。

五、 全局总结与后续开发展望

通过上述四个核心阶段的深度拆解与实战,我们完成了一块基于 T113-S3 芯片的新主板从“点亮”到“完全可用”的全链路移植闭环。

  • 向下扎根(底层破冰):理清了 SPI NAND 的启动逻辑,精准配置了 U-Boot 与 Linux Kernel 的软硬件交接点(FEX 与 DTS),并成功完成了 FL7707 MIPI 屏幕等非标外设的驱动级移植与时序同步。
  • 向上生长(系统重构):通过果断剥离 OpenWrt 黑盒的 procd,换用线性可控的 busybox init 框架,彻底接管了系统的启动生命周期。如今,Wi-Fi 动态加载、ADB 调试通道、底层的音视频路由均已在开机时顺畅就绪。
  • 排障体系建立:文档最后沉淀的“BSP 硬核调试工具箱”,将排错维度从单纯的看 Log 提升到了物理寄存器级(devmem)、总线级(i2c-tools)和状态机级(sysfs)。这套工具和排障逻辑,将是未来应对复杂客诉或莫名死机问题时的核心武器。

底层的“修路”工作已经圆满竣工,一块拥有健壮网络、顺畅交互与高清显示的系统基石已经搭建完毕。舞台准备就绪,系统的核心任务将正式由“驱动硬件”转向“业务实现”。

更多推荐