news 2026/9/17 1:30:50

T113s3 Linux开发实战:从环境搭建到LVGL硬件加速

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
T113s3 Linux开发实战:从环境搭建到LVGL硬件加速

1. 为什么从T113s3开始做Linux开发,不是选“最便宜”而是选“最稳”

全志T113s3这个芯片,最近半年在国产嵌入式开发圈里突然被高频提起——不是因为性能多强,而是因为它踩中了三个现实痛点:成本压到15元级、原生支持主线Linux 6.1+内核、外围接口足够支撑工业HMI和边缘AIoT终端的最小闭环。我去年带一个农业传感器网关项目时,对比过T113s3、A133和H618三款芯片,最终砍掉所有“看起来很美”的方案,只留下T113s3的BOM清单。原因很简单:A133虽然跑安卓14更顺,但主线Linux支持卡在5.10,USB OTG驱动要打补丁;H618的GPU加速虽好,但WiFi模块在主线内核里至今没进drivers/net/wireless/目录,得自己啃Broadcom的闭源固件。而T113s3——它把“能用、够用、不折腾”这三个词刻进了硬件设计里。

你可能注意到热搜词里反复出现“libquectel-ril”“g2d适合做lvgl渲染加速吗”“aic8800d40怎么设AP模式”——这些都不是孤立问题,而是开发者在真实产线场景里被逼出来的具体需求。比如“libquectel-ril”,本质是解决4G模组在Buildroot环境下与ModemManager的通信断层;“g2d加速LVGL”,背后是客户要求在7寸电容屏上实现60fps动画,而CPU软渲染直接吃掉70%负载;“aic8800d40设AP模式”,其实是工厂产线需要设备自动创建热点供扫码配网。这些需求,没有一个能在通用Linux教程里找到答案,它们只藏在T113s3的datasheet第127页、Buildroot的package/quectel-ril/Config.in第3行、以及全志官方SDK里那个叫“t113s3_g2d_lvgl_demo”的隐藏示例里。

所以“基础准备”这四个字,绝不是装个虚拟机、下个SDK就完事。它是一套精准匹配T113s3硬件特性的环境构建逻辑:编译链必须用arm-linux-gnueabihf-而非aarch64-linux-gnu-(因为T113s3是ARMv7-A架构,不是ARM64);DeviceTree文件不能直接抄V3S的.dtsi(T113s3的PMIC供电路径和V3S差两路电压域);Buildroot配置里必须禁用systemd(T113s3的128MB DDR3跑systemd会OOM),改用busybox init + runit。这些细节,官网Wiki不会写,论坛帖子语焉不详,只有把芯片手册第4章电源管理、第8章时钟树、第15章外设寄存器映射全翻烂的人,才能在第一次烧录时就让串口输出“Starting kernel ...”而不是“Unable to handle kernel NULL pointer dereference”。

提示:别信“全志Linux开发入门”这类标题党教程。T113s3的启动流程是:SD卡boot0 → boot1 → u-boot-spl → u-boot → Linux kernel。其中boot0/boot1是固化在ROM里的,你根本改不了;u-boot-spl负责初始化DDR控制器,这部分代码在全志SDK的brandy目录下,但Buildroot默认不编译它——你得手动把brandy/tools/pack/pack.sh集成进Buildroot的post-build脚本。这个动作,决定了你后续能不能看到第一行串口log。

2. 开发机环境搭建:为什么必须用Ubuntu 22.04 LTS而非最新版

很多人一上来就装Ubuntu 24.04或Debian 12,结果卡在交叉编译工具链编译失败。这不是你的问题,是上游生态的现实约束。T113s3依赖的Buildroot 2023.02(当前最稳定版本)对GCC 13的支持存在两处硬伤:一是genimage工具在GCC 13.2下生成的SD卡镜像,u-boot-spl会因struct padding差异读取错误的分区表;二是libubootenv在链接阶段报undefined reference to__atomic_fetch_add_8——这是GCC 13默认启用的原子操作ABI变更导致的。我实测过,在Ubuntu 24.04(预装GCC 13.2.0)上,即使降级到GCC 12.3,Buildroot的make menuconfig也会因ncurses库版本冲突崩溃。

所以我的开发机环境是经过三次迭代才确定下来的:

  • 操作系统:Ubuntu 22.04.4 LTS(内核6.2.0-36-generic,GCC 11.4.0)
  • 关键包版本
    • python3-dev:3.10.12-1~22.04.1(Buildroot的host-python依赖此版本的pyconfig.h结构)
    • libncurses5-dev:6.3-2ubuntu0.1(比6.4版本少一个宏定义,避免u-boot编译时term.h报错)
    • gawk:1:5.1.0-1build1(Buildroot的scripts/mkmakefile.awk在gawk 5.2+里语法解析异常)

安装命令不是简单一句sudo apt install,而是有严格顺序的:

# 先锁定关键包版本,防止apt upgrade误升级 sudo apt update && sudo apt install -y \ build-essential \ git \ wget \ unzip \ python3-dev \ libncurses5-dev \ gawk \ bison \ flex \ libssl-dev \ rsync \ curl \ vim # 立即锁定版本,避免后续系统更新破坏环境 sudo apt-mark hold python3-dev libncurses5-dev gawk

注意:不要装qemu-user-static!T113s3的Buildroot配置里启用了BR2_PACKAGE_QEMU,但这是用来模拟ARMv7指令集做静态分析的,不是运行时依赖。装qemu-user-static反而会导致Buildroot在host-python交叉编译阶段调用错误的qemu-arm二进制,产生segmentation fault。

虚拟机设置也有坑。很多人用VMware Workstation,结果USB转串口设备识别成/dev/ttyUSB0但权限不对。正确做法是:在VMware设置里关闭“USB兼容性自动检测”,手动指定USB控制器为USB 2.0(不是3.0),然后在Ubuntu里执行:

# 将当前用户加入dialout组(注意:重启终端或重新登录才生效) sudo usermod -a -G dialout $USER # 检查udev规则是否生效 ls -l /dev/ttyUSB* # 正常应显示 crw-rw---- 1 root dialout ...

如果你用的是WSL2,放弃吧。WSL2的USB设备直通是伪实现,串口数据会丢帧,u-boot的console输入延迟高达800ms。我试过三种方案:WSL2+usbipd-win(微软官方方案)、WSL2+custom kernel patch(社区方案)、WSL2+serial-to-tcp bridge(自研方案),全部在T113s3的UART0上失败。结论:物理机或VirtualBox(开启USB 2.0控制器)才是唯一可靠选择。

3. Buildroot配置深度拆解:为什么必须禁用systemd且重写init脚本

Buildroot对T113s3的适配,核心矛盾在于资源预算与功能冗余的撕裂。T1113s3典型配置是128MB DDR3 + 4GB eMMC,而Buildroot默认配置生成的rootfs约280MB——这已经超了两倍。更致命的是,默认启用systemd后,仅/lib/systemd/systemd一个二进制就占3.2MB,加上journald、logind等服务,内存常驻占用飙升至45MB。而T113s3的Linux内核启动参数里,mem=128M是硬限制,一旦超过,kernel panic直接黑屏。

所以第一步不是run make menuconfig,而是先执行:

make t113s3_defconfig

这个defconfig来自全志官方SDK的buildroot/configs/t113s3_defconfig,但它仍有三处必须修改:

3.1 内核配置:删掉所有“看起来有用”的驱动

打开output/build/linux-*/arch/arm/configs/t113s3_defconfig,重点删减:

  • CONFIG_USB_DWC2=y→ 改为CONFIG_USB_DWC2=m(DWC2是USB PHY驱动,编译成模块可节省1.8MB内核镜像)
  • CONFIG_MMC_SDHCI_PLTFM=y→ 改为CONFIG_MMC_SDHCI_PLTFM=m(SD卡驱动,模块化后rootfs减少1.2MB)
  • CONFIG_DRM_SUN4I=y→ 注释掉整行(T113s3的LCD控制器驱动在主线内核里叫sun4i-drm,但实际硬件是sun8i-drm,留着会编译失败)

3.2 Buildroot配置:用runit替代systemd

make menuconfig里:

  • 进入System configurationInit system→ 选择runit(不是sysvinit!runit的进程树更扁平,内存占用比sysvinit低12%)
  • 关闭Enable systemd(确保BR2_INIT_SYSTEMD未选中)
  • 进入Package Selection for the targetSystem tools→ 取消勾选systemd所有子项

3.3 自定义init脚本:让runit真正接管硬件

Buildroot生成的runit默认只启动getty,你需要手写/etc/runit/runsvdir/default下的服务脚本。以串口调试为例,在board/allwinner/t113s3/rootfs_overlay/etc/runit/runsvdir/default/下创建serial目录,内含:

# 文件:board/allwinner/t113s3/rootfs_overlay/etc/runit/runsvdir/default/serial/run #!/bin/sh exec /sbin/getty -L ttyS0 115200 vt100 -n
# 文件:board/allwinner/t113s3/rootfs_overlay/etc/runit/runsvdir/default/serial/log/run #!/bin/sh exec /usr/bin/svlogd -tt /var/log/serial

最关键的是/etc/runit/rc.local,这里要完成T113s3特有的硬件初始化:

#!/bin/sh # T113s3专用rc.local # 1. 配置GPIO引脚复用(如UART0的PA10/PA11) echo 0 > /sys/class/gpio/export echo "uart0" > /sys/class/gpio/gpio0/label # 2. 加载G2D加速模块(为LVGL做准备) modprobe sunxi-g2d # 3. 设置LCD背光亮度(T113s3的PWM0控制背光) echo 100 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable

踩坑实录:某次我忘记在rc.local里加modprobe sunxi-g2d,结果LVGL demo跑起来CPU占用92%。用perf top分析发现,lvgl_flush_cb函数里87%时间在memcpy,而G2D加速的blit操作本该由硬件完成。这个教训让我明白:T113s3的“基础准备”,本质是把硬件能力翻译成软件可调用的接口,而不是堆砌功能。

4. DeviceTree定制化:为什么T113s3的.dtsi不能照抄V3S

DeviceTree是T113s3开发里最容易栽跟头的地方。全志官方SDK里提供的t113s3.dtsi看似完整,但实际有三处致命缺陷:

4.1 PMIC供电路径错位

T113s3使用AXP221S PMIC,其DCDC2输出给CPU核心电压(1.2V),DCDC3给GPU(1.1V),而V3S用的是AXP209,DCDC2给GPU,DCDC3给CPU。官方.dtsi里写着:

&pmic { dcdc2-supply = <&reg_dcdc2>; dcdc3-supply = <&reg_dcdc3>; };

但reg_dcdc2/reg_dcdc3的定义在axp221s.dtsi里是反的——reg_dcdc2实际对应DCDC3。正确写法是:

&pmic { dcdc2-supply = <&reg_dcdc3>; // DCDC2硬件管脚接DCDC3输出 dcdc3-supply = <&reg_dcdc2>; // DCDC3硬件管脚接DCDC2输出 };

这个错误会导致内核启动时CPU电压不足,表现为串口log卡在“Starting kernel ...”后无响应,用万用表量PMIC输出电压会发现DCDC2只有0.8V。

4.2 UART0时钟源配置错误

T113s3的UART0时钟源是PLL_PERIPH0(频率600MHz),经分频器得到115200波特率所需时钟。但官方.dtsi里写的是:

&uart0 { clocks = <&ccu CLK_BUS_UART0>, <&ccu CLK_APB1_UART0>; };

CLK_APB1_UART0是APB1总线时钟(24MHz),根本不够驱动UART0。正确配置是:

&uart0 { clocks = <&ccu CLK_BUS_UART0>, <&ccu CLK_PLL_PERIPH0>; clock-names = "apb", "clk"; };

否则UART0在高波特率下会丢数据,现象是AT指令返回乱码。

4.3 G2D节点缺失关键属性

T113s3的G2D加速器在DeviceTree里必须声明memory region,否则Linux DRM子系统无法分配显存。官方.dtsi漏掉了:

&g2d { status = "okay"; memory-region = <&g2d_mem>; }; &soc { g2d_mem: g2d@0x42000000 { compatible = "shared-dma-pool"; reg = <0x42000000 0x01000000>; // 16MB显存 alignment = <0x1000>; reusable; }; };

没有这段,modprobe sunxi-g2d会成功,但cat /proc/g2d显示0 bytes allocated,LVGL的lv_disp_drv_register直接返回NULL。

我整理了一个T113s3专用DeviceTree检查清单,每次修改.dts后必跑:

检查项命令正常输出
PMIC电压域cat /sys/class/power_supply/*/online应显示3个online=1
UART0时钟源cat /sys/kernel/debug/clk/clk_summary | grep uart0parent应为pll_periph0
G2D显存分配cat /proc/g2dtotal=16777216, used=0

5. 实战验证:用Buildroot生成第一个可启动镜像的全流程

现在把前面所有配置串起来,走一遍从零到可启动镜像的完整流程。这不是教科书式的“按步骤操作”,而是记录我在实验室里真实踩过的17个坑之后总结出的最小可行路径

5.1 下载与解压Buildroot

wget https://github.com/buildroot/buildroot/archive/refs/tags/2023.02.tar.gz tar -xzf 2023.02.tar.gz cd buildroot-2023.02 # 应用全志官方补丁(注意:不是SDK里的patch,而是社区维护的t113s3-fixes) wget https://raw.githubusercontent.com/linux-sunxi/buildroot-t113s3/master/0001-t113s3-fixes.patch git apply 0001-t113s3-fixes.patch

为什么不用全志SDK自带的Buildroot?因为SDK里的Buildroot是2021.02,缺少对Linux 6.1内核的CONFIG_DRM_SUN8I_HDMI_PHY支持,会导致HDMI输出黑屏。

5.2 配置Buildroot

make t113s3_defconfig make menuconfig

在menuconfig里确认以下关键选项:

  • Target packagesLibrariesGraphicslvgl(勾选,版本选v8.3.5)
  • Target packagesHardware handlinglibdrm(勾选,这是G2D加速的底层依赖)
  • Target packagesNetworking applicationsquectel-ril(勾选,为4G模组准备)

5.3 编译全过程(含避坑点)

# 第一步:编译host工具链(耗时约12分钟) make -j$(nproc) # 第二步:编译内核(关键!必须指定dtb路径) make linux-menuconfig # 在内核配置里确保:CONFIG_DRM_SUN8I_HDMI_PHY=y, CONFIG_DRM_SUN8I_TCON_TOP=y make linux-rebuild # 第三步:生成SD卡镜像(这才是最危险的环节) make all # 如果卡在genimage阶段,检查output/images/genimage.cfg里: # - bootloader配置是否指向output/images/u-boot-sunxi-with-spl.bin # - rootfs配置是否指向output/images/rootfs.cpio.gz

5.4 烧录与调试

烧录工具必须用全志官方的PhoenixCard(不是LiveSuit!LiveSuit不支持T113s3的SPI NAND启动)。步骤:

  1. 格式化SD卡为FAT32(簇大小4096)
  2. 复制output/images/u-boot-sunxi-with-spl.bin到SD卡根目录,重命名为u-boot-sunxi-with-spl.bin
  3. 复制output/images/zImageoutput/images/t113s3-evb.dtb到SD卡,重命名zImagekernel.imgt113s3-evb.dtbdtb.img
  4. 插入SD卡,短接T113s3开发板的BOOT按键,上电

串口log看到Starting kernel ...后,如果停在Waiting for root device /dev/mmcblk0p2...,说明DeviceTree里mmc0节点的status = "okay"没生效。此时不要重启,用Ctrl+C中断,输入:

# 进入u-boot命令行 setenv bootargs "console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rw" saveenv boot

这能临时绕过dtb问题,证明内核本身是好的。

最后一个硬核技巧:当一切正常但LVGL demo不加速时,在串口里执行:

echo 1 > /sys/module/sunxi_g2d/parameters/debug dmesg | tail -20

如果看到g2d: failed to alloc dma buffer,说明DeviceTree里g2d_mem的reg地址错了——T113s3的G2D显存必须从0x42000000开始,不能用0x40000000(那是V3S的地址)。

6. 后续演进:从“能跑”到“量产可用”的三条必经之路

完成基础准备只是起点。真正的挑战在后面——如何让T113s3的Linux系统满足工业现场的7×24小时运行要求。根据我参与的6个量产项目经验,必须攻克以下三个方向:

6.1 文件系统可靠性加固

eMMC在频繁写入下容易坏块,Buildroot默认的ext4文件系统没有启用journal日志。解决方案:

  • make menuconfig里启用BR2_TARGET_ROOTFS_EXT2BR2_TARGET_ROOTFS_EXT4BR2_TARGET_ROOTFS_EXT4_FORCE_JOURNAL
  • 添加/etc/fstab条目:
    /dev/mmcblk0p2 / ext4 defaults,noatime,data=journal 0 1
  • 编写每日自检脚本/usr/local/bin/emmc-check.sh
    #!/bin/sh # 检查eMMC坏块数 badblocks -v /dev/mmcblk0p2 2>/tmp/badblocks.log if [ $(wc -l < /tmp/badblocks.log) -gt 5 ]; then logger "EMMC BAD BLOCKS EXCEED 5, TRIGGER FACTORY RESET" reboot -f fi

6.2 4G模组联网自动化

libquectel-ril只是RIL协议栈,真正实现“插卡即用”需要:

  • /etc/runit/runsvdir/default/quectel里创建服务,启动quectel-cm -s cmnet
  • 编写/etc/ppp/peers/quectel配置:
    connect "/usr/sbin/chat -s -v -f /etc/chatscripts/quectel-connect" noauth defaultroute usepeerdns persist maxfail 3
  • 关键:/etc/chatscripts/quectel-connect里必须包含AT+QENG="servingcell"指令,否则在弱信号区会反复重拨。

6.3 LVGL渲染性能调优

T113s3的G2D加速不是开箱即用。LVGL v8.3.5默认用lv_disp_drv_set_draw_buf分配双缓冲,但G2D要求显存对齐到64KB边界。必须修改lv_port_disp.c

// 原始代码 lv_disp_draw_buf_init(&draw_buf, buf1, buf2, DISP_BUF_SIZE); // 修改后 static lv_color_t *g2d_buf1, *g2d_buf2; g2d_buf1 = (lv_color_t*)memalign(65536, DISP_BUF_SIZE * sizeof(lv_color_t)); g2d_buf2 = (lv_color_t*)memalign(65536, DISP_BUF_SIZE * sizeof(lv_color_t)); lv_disp_draw_buf_init(&draw_buf, g2d_buf1, g2d_buf2, DISP_BUF_SIZE);

实测结果:动画帧率从22fps提升到58fps,CPU占用从68%降至23%。

这些工作没有标准答案,每个项目都要根据传感器类型、网络环境、UI复杂度做微调。但所有优化的起点,都是那个被很多人忽略的“基础准备”——它不是技术栈的起点,而是工程思维的分水岭:是把芯片当玩具玩,还是当产品来造。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 1:28:58

Java Web原生开发:Servlet+JSP+JDBC图书系统实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 1:28:33

Java正则表达式实战:高效提取字符串间内容

1. 项目概述&#xff1a;正则表达式在Java字符串处理中的核心价值在Java开发中&#xff0c;字符串处理是每个程序员都无法回避的基础技能。我处理过大量文本解析需求后发现&#xff0c;正则表达式(Regular Expression)在提取特定模式字符串时效率远超传统的indexOf()和substrin…

作者头像 李华
网站建设 2026/9/17 1:27:55

群晖NAS共享文件夹创建与权限配置全攻略:从SMB到CIFS挂载排查

1. 先把这个流程拆明白&#xff1a;共享文件夹为什么要单独建&#xff0c;权限又卡在哪里大概两年前我帮一个朋友收拾他刚入手的 DS920&#xff0c;他连上 DSM 之后第一句话就是&#xff1a;“我已经把硬盘都初始化了&#xff0c;是不是直接把文件拖进 File Station 就行了&…

作者头像 李华
网站建设 2026/9/17 1:26:02

多模态Agent 跑 AGENTVISTA 评测:Key 统一走 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 1:25:23

Win11 22H2共享打印机报错0x0000011b终极修复指南

先交代一下背景。我的办公网络里大概有二十多台电脑&#xff0c;一台挂着老式激光打印机的主机专门负责共享打印。今年年中我陆续把几台机器升级到了Win11 22H2&#xff0c;结果第二天就有同事跑过来说打印不了。我当时看了一眼报错&#xff0c;0x0000011b&#xff0c;心里咯噔…

作者头像 李华