嵌入式开发 嵌入式 Linux 入门:在 Allwinner H616 上跑 Buildroot
搞嵌入式的朋友,迟早会走到这一步——从裸机/RTOS 跳到真正的 Linux 系统。
你可能已经玩过了 STM32、ESP32,写过 FreeRTOS 多任务,觉得”嵌入式也就这样了”。但当你需要跑一个 Web 服务器、处理视频流、或者用 Python 写应用逻辑的时候,RTOS 就不够用了。这时候,嵌入式 Linux 才是正解。
今天我们就用一块 Allwinner H616 开发板(比如 Orange Pi 3 LTS 或类似板子),配合 Buildroot 这个神器,从零构建一个完整的嵌入式 Linux 系统。
为什么选 Allwinner H616?
全志 H616 是一颗性价比极高的 ARM SoC:
| 参数 | 规格 |
|---|---|
| CPU | 四核 ARM Cortex-A53 @ 1.5GHz |
| GPU | Mali G31 MP2 |
| 内存 | 支持 DDR3/DDR4,最大 4GB |
| 视频 | 硬件解码 H.265/H.264,支持 4K@60fps |
| 接口 | HDMI 2.0a、USB 3.0、千兆以太网、WiFi/BT(部分板载) |
| 存储 | eMMC、SD 卡启动 |
关键优势:
- 便宜:开发板 100-200 元就能搞定
- 社区支持好:mainline Linux 内核已经支持 H6/H616
- 性能够用:四核 A53 跑 Linux 绰绰有余,还能做轻量级多媒体处理
- 适合学习:比树莓派更”原始”,需要自己构建系统,学到的东西更多
为什么选 Buildroot?
嵌入式 Linux 系统构建方案主要有三个:
| 方案 | 特点 | 适合场景 |
|---|---|---|
| Buildroot | 极简、快速、配置直观 | 产品固件、专用设备 |
| Yocto/OpenEmbedded | 功能强大、灵活但复杂 | 大型商业产品 |
| Debian/Ubuntu | 包管理完善、上手快 | 原型开发、通用设备 |
Buildroot 的核心哲学:用最简单的方式,生成一个刚好够用的嵌入式 Linux 系统。
它的优势在于:
- 配置简单:
make menuconfig一个界面搞定所有配置 - 构建快速:首次完整编译 20-40 分钟,增量编译几秒钟
- 产物精简:生成的 rootfs 可以小到 30MB 以内
- 可复现:一份配置生成完全一样的系统,适合量产
硬件清单
开始之前,你需要准备这些东西:
| 物品 | 说明 | 参考价格 |
|---|---|---|
| Orange Pi 3 LTS 或 H616 开发板 | 淘宝搜”Orange Pi 3 LTS” | ¥120-180 |
| MicroSD 卡(16GB+) | 推荐 SanDisk Class 10 | ¥25 |
| 5V/3A 电源 | Type-C 或 DC 口,看板子 | ¥15 |
| USB-TTL 串口线 | CH340 或 CP2102 芯片 | ¥8 |
| HDMI 线 + 显示器 | 调试时看输出(可选) | - |
| 网线 | 千兆以太网连接(可选) | - |
| SD 卡读卡器 | 电脑端烧录用 | ¥10 |
串口是必须的! 嵌入式 Linux 调试 90% 靠串口,没有串口等于瞎子摸象。
搭建编译环境
1. 安装依赖
推荐用 Ubuntu 22.04 或 24.04(物理机或虚拟机都行)。安装编译所需的依赖:
sudo apt update
sudo apt install -y \
build-essential gcc g++ make \
libncurses5-dev libncursesw5-dev \
wget curl git \
unzip bc cpio \
python3 python3-pip \
file bzip2 xz-utils \
rsync texinfo
2. 下载 Buildroot
# 下载最新稳定版(以 2026.05 为例)
wget https://buildroot.org/downloads/buildroot-2026.05.tar.gz
tar xf buildroot-2026.05.tar.gz
cd buildroot-2026.05
或者用 Git 获取最新代码:
git clone https://github.com/buildroot/buildroot.git
cd buildroot
3. 检查磁盘空间
Buildroot 编译需要 至少 10GB 磁盘空间,建议留 20GB 以上:
df -h .
配置 Buildroot
方法一:使用现成的 defconfig(推荐新手)
Buildroot 自带了很多开发板的默认配置。虽然没有直接的 orangepi_h616_defconfig,但我们可以基于通用的 aarch64 配置来改:
# 先看看有没有相关的配置
ls configs/ | grep -i "orange\|allwinner\|h6\|sun50i"
如果有类似的配置可以直接用:
make orangepi_3_defconfig # 如果有的话
方法二:从头配置(推荐学习)
make qemu_aarch64_virt_defconfig # 先用一个基础配置
make menuconfig
在 menuconfig 中,重点配置以下几项:
Target Architecture(目标架构)
Target Options --->
Target Architecture: AArch64 (little endian)
Target Architecture Variant: cortex-a53
Toolchain(工具链)
Toolchain --->
Toolchain type: Buildroot toolchain
C library: glibc
Kernel Headers: Linux kernel headers (from the kernel we're building)
GCC version: 13.x
Kernel(内核)
Kernel --->
[*] Linux Kernel
Kernel version: Custom version (选 6.6 或更新的 LTS)
Kernel configuration: sunxi defconfig
(sun50i-h616) Device Tree Source file name
注意:H616 的 Device Tree 文件名可能是
sun50i-h616-orangepi-3-lts,具体看内核源码中arch/arm64/boot/dts/allwinner/目录下有哪些。
Bootloader(引导加载程序)
Bootloaders --->
[*] U-Boot
U-Boot version: Custom version (选最新)
U-Boot configuration: orangepi_3_defconfig (或 orangepi_3_lts_defconfig)
Filesystem(文件系统)
Filesystem images --->
[*] ext4 root filesystem
[*] tar the root filesystem
配置要点速查
一个典型的 H616 Buildroot 配置(.config 关键项):
# 目标平台
BR2_aarch64=y
BR2_cortex_a53=y
# 工具链
BR2_TOOLCHAIN_BUILDROOT_GLIBC=y
# 内核
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.32"
BR2_LINUX_KERNEL_USE_DEFCONFIG=y
BR2_LINUX_KERNEL_DEFCONFIG="sunxi"
BR2_LINUX_KERNEL_DTS_SUPPORT=y
BR2_LINUX_KERNEL_INTREE_DTS_NAME="allwinner/sun50i-h616-orangepi-3-lts"
# U-Boot
BR2_TARGET_UBOOT=y
BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y
BR2_TARGET_UBOOT_CUSTOM_VERSION=y
BR2_TARGET_UBOOT_CUSTOM_VERSION_VALUE="2026.04"
BR2_TARGET_UBOOT_BOARD_DEFCONFIG="orangepi_3_lts"
BR2_TARGET_UBOOT_NEEDS_DTC=y
BR2_TARGET_UBOOT_NEEDS_PYTHON3=y
BR2_TARGET_UBOOT_FORMAT_CUSTOM=y
BR2_TARGET_UBOOT_FORMAT_CUSTOM_NAME="u-boot-sunxi-with-spl.bin"
# 文件系统
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_4=y
开始编译
配置完成后,一条命令开始编译:
make -j$(nproc)
提示:Buildroot 从 2020 版本开始支持顶层并行编译,
-j参数可以放心用。
编译过程会依次完成:
- 下载源码包(约 5-10 分钟,取决于网络)
- 解压并打补丁
- 配置并编译交叉编译工具链
- 编译 Linux 内核
- 编译 U-Boot
- 生成 rootfs
首次编译大约需要 30-60 分钟(取决于 CPU 性能)。
编译产物
编译完成后,在 output/images/ 目录下会生成:
output/images/
├── bl31.bin # ARM Trusted Firmware
├── Image # Linux 内核镜像
├── sun50i-h616-orangepi-3-lts.dtb # 设备树
├── u-boot-sunxi-with-spl.bin # U-Boot(含 SPL)
├── rootfs.ext4 # 根文件系统
└── sdcard.img # 完整的 SD 卡镜像(如果有配置)
烧录到 SD 卡
方法一:使用 sdcard.img(最简单)
如果 Buildroot 配置了生成 sdcard.img,直接烧录即可:
# 查看 SD 卡设备名(小心别写错!)
lsblk
# 烧录(假设 SD 卡是 /dev/sdb)
sudo dd if=output/images/sdcard.img of=/dev/sdb bs=4M status=progress
sync
方法二:手动分区烧录
如果没有 sdcard.img,需要手动操作:
# 1. 分区(假设 SD 卡是 /dev/sdb)
sudo fdisk /dev/sdb
# 创建一个 Linux 分区(/dev/sdb1)
# 2. 格式化
sudo mkfs.ext4 /dev/sdb1
# 3. 挂载并写入
sudo mount /dev/sdb1 /mnt
sudo cp output/images/rootfs.ext4 /mnt/
# 或者解压 tar:
# sudo tar xf output/images/rootfs.tar -C /mnt/
# 4. 拷贝内核和 DTB
sudo mkdir -p /mnt/boot
sudo cp output/images/Image /mnt/boot/
sudo cp output/images/*.dtb /mnt/boot/
# 5. 写入 U-Boot(SPL 在 8KB 偏移处)
sudo dd if=output/images/u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8
# 6. 卸载
sudo umount /mnt
sync
首次启动
1. 连接串口
# 接线:TX→RX, RX→TX, GND→GND
# 波特率:115200
# Linux/Mac:
screen /dev/ttyUSB0 115200
# Windows 用 PuTTY 或 MobaXterm
H616 开发板的串口引脚一般在板子边缘的排针上,具体看板子的原理图。Orange Pi 3 LTS 的 UART0 引脚:
| 引脚 | 功能 |
|---|---|
| Pin 6 (TX) | 串口发送 |
| Pin 8 (RX) | 串口接收 |
| Pin 10 (GND) | 地线 |
2. 插入 SD 卡,上电
你应该能在串口看到 U-Boot 启动信息:
U-Boot SPL 2026.04 (Jul 02 2026 - 04:00:00 +0800)
DRAM: 2048 MiB
Trying to boot from MMC1
U-Boot 2026.04 (Jul 02 2026 - 04:00:00 +0800) Allwinner Technology
CPU: Allwinner H616 (SUN50I)
Model: OrangePi 3 LTS
DRAM: 2 GiB
...
然后是 Linux 内核启动日志,最后到达登录提示符:
Welcome to Buildroot
buildroot login: root
#
恭喜!你的嵌入式 Linux 系统跑起来了!
3. 基础验证
# 查看系统信息
uname -a
# Linux buildroot 6.6.32 #1 SMP ... aarch64 GNU/Linux
# 查看 CPU 信息
cat /proc/cpuinfo
# 查看内存
free -h
# 查看磁盘
df -h
# 网络(如果板子有网口)
ifconfig eth0 up
udhcpc -i eth0
ping -c 3 8.8.8.8
添加自定义应用
Buildroot 最强大的地方在于可以轻松添加你需要的软件包。
方法一:通过 menuconfig 添加
make menuconfig
# 进入以下路径选择需要的包:
# Target packages --->
# [*] Networking applications --->
# [*] openssh
# [*] Text editors and viewers --->
# [*] vim
# [*] Interpreter languages and scripting --->
# [*] python3
然后重新编译:
make
方法二:添加自定义程序
创建一个简单的 C 程序:
mkdir -p package/hello-world
创建 package/hello-world/Config.in:
config BR2_PACKAGE_HELLO_WORLD
bool "hello-world"
help
A simple hello world program
创建 package/hello-world/hello-world.mk:
HELLO_WORLD_VERSION = 1.0
HELLO_WORLD_SITE = $(TOPDIR)/../custom-packages/hello-world
HELLO_WORLD_SITE_METHOD = local
define HELLO_WORLD_BUILD_CMDS
$(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) all
endef
define HELLO_WORLD_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 $(@D)/hello $(TARGET_DIR)/usr/bin/hello
endef
$(eval $(generic-package))
在 package/hello-world/ 目录下创建源码 hello.c:
#include <stdio.h>
int main(void) {
printf("Hello from Allwinner H616!\n");
printf("Running embedded Linux with Buildroot.\n");
return 0;
}
以及 Makefile:
CC ?= gcc
CFLAGS ?= -Wall -O2
all: hello
hello: hello.c
$(CC) $(CFLAGS) -o $@ $<
clean:
rm -f hello
重新配置并编译:
make menuconfig
# Target packages --->
# Miscellaneous --->
# [*] hello-world
make
常见问题排查
问题 1:串口没有输出
排查步骤:
- 检查 TX/RX 是否接反(交叉连接)
- 确认波特率是 115200
- 检查板子的 UART 引脚定义是否正确
- 用万用表量一下 TX 引脚是否有电平变化
问题 2:U-Boot 启动后找不到内核
=>
卡在 U-Boot 命令行,说明内核加载失败。
解决方法:
# 在 U-Boot 命令行手动指定启动参数
setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p1 rootwait
fatload mmc 0 0x40080000 boot/Image
fatload mmc 0 0x4fa00000 boot/sun50i-h616-orangepi-3-lts.dtb
booti 0x40080000 - 0x4fa00000
问题 3:内核 Panic - not syncing: VFS: Unable to mount root fs
原因:rootfs 分区找不到或格式不对。
解决:
- 检查
bootargs中的root=参数是否与实际分区匹配 - 确认 SD 卡分区格式正确(ext4)
- 查看 U-Boot 的
boot.cmd/boot.scr配置
问题 4:编译报错 “No rule to make target”
通常是 .config 配置有误。解决方法:
# 清理并重新配置
make clean
make menuconfig
make
问题 5:网络不通
# 检查网卡是否识别
ip link show
# 手动配置 IP
ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up
route add default gw 192.168.1.1
# 或者用 DHCP
udhcpc -i eth0
如果 ip link 看不到 eth0,可能是内核没编译对应的网卡驱动。回到 menuconfig 检查:
Kernel --->
[*] Linux Kernel
Kernel configuration: sunxi defconfig
sunxi defconfig 应该包含了 H616 的 GMAC 驱动,但如果你用了自定义内核配置,需要确认:
CONFIG_STMMAC_ETH=y
CONFIG_DWMAC_SUNXI=y
Buildroot 进阶技巧
1. 使用 overlay 目录
overlay 可以让你在生成的 rootfs 上叠加自定义文件,而不需要修改 Buildroot 源码:
# 在 menuconfig 中设置
# System configuration --->
# (/path/to/overlay) Root filesystem overlay directories
# 然后在 overlay 目录下创建跟 rootfs 一样的目录结构
overlay/
├── etc/
│ └── hostname
├── root/
│ └── .bashrc
└── usr/
└── bin/
└── my-script.sh
2. 使用 post-build 脚本
在编译完成后自动执行脚本:
# System configuration --->
# (board/h616/post-build.sh) Run a post-build script
# board/h616/post-build.sh
#!/bin/bash
TARGET_DIR=$1
echo "Customizing rootfs..."
echo "h616-board" > ${TARGET_DIR}/etc/hostname
# 添加自定义配置等
3. 使用 br2-external
如果你有多个产品共用同一个 Buildroot 版本,用 br2-external 机制把板级配置分离出来:
# 创建外部配置目录
mkdir -p br2-external-h616/{configs,board/h616,package}
# 创建 desc 文件
cat > br2-external-h616/external.desc <<EOF
name: H616
desc: Allwinner H616 board support
EOF
# 使用时
make BR2_EXTERNAL=/path/to/br2-external-h616 menuconfig
4. 加速编译
# 使用 ccache 缓存编译结果
# Toolchain --->
# [*] Enable compiler cache (ccache)
# 或者设置 DL_DIR 共享下载目录
# 在 .config 中:
BR2_DL_DIR="/home/user/buildroot-dl"
从 Buildroot 到产品
Buildroot 构建的系统适合做专用设备,比如:
- 智能网关:跑 MQTT 客户端 + 协议转换
- 数字标牌:HDMI 输出 + 轻量 Web 浏览器
- 工业控制器:Modbus 通信 + 本地 HMI
- 边缘 AI 盒子:摄像头接入 + 推理引擎
产品化注意事项:
- 安全加固:禁用 root 登录、启用 SSH 密钥认证
- 看门狗:配置硬件看门狗防止死机
- OTA 更新:使用 A/B 分区方案实现远程升级
- 日志管理:用 tmpfs 存放日志,保护 SD 卡寿命
- 电源管理:配置 cpufreq 降低功耗
总结
今天我们完成了从零开始的嵌入式 Linux 之旅:
- ✅ 了解了 Allwinner H616 和 Buildroot 的基本概念
- ✅ 搭建了交叉编译环境
- ✅ 配置并编译了完整的 Linux 系统
- ✅ 烧录到 SD 卡并成功启动
- ✅ 学会了添加自定义应用和常见问题排查
下一步建议:
- 尝试给系统添加 Python 支持,写一些 IoT 应用
- 研究 Device Tree,了解硬件是如何被描述的
- 学习 U-Boot 的环境变量和启动流程
- 尝试用 Buildroot 的 legal-info 功能生成软件许可证报告
嵌入式 Linux 的世界很大,Buildroot 是你最好的入门工具。它足够简单让你快速上手,又足够灵活让你做到产品级。
有什么疑问欢迎留言讨论,我们下篇文章见!