Embedded Development Getting Started with Embedded Linux: Running Buildroot on Allwinner H616
If you work with embedded systems, you’ll eventually reach this point—jumping from bare metal/RTOS to a real Linux system.
You might have already played around with STM32, ESP32, written FreeRTOS multitasking code, and thought “that’s all there is to embedded systems.” But when you need to run a web server, process video streams, or write application logic in Python, RTOS just isn’t enough. That’s when embedded Linux becomes the right solution.
Today we’ll use an Allwinner H616 development board (like Orange Pi 3 LTS or similar) with Buildroot to build a complete embedded Linux system from scratch.
Why Choose Allwinner H616?
The Allwinner H616 is an ARM SoC with excellent price-to-performance ratio:
| Parameter | Specification |
|---|---|
| CPU | Quad-core ARM Cortex-A53 @ 1.5GHz |
| GPU | Mali G31 MP2 |
| Memory | Supports DDR3/DDR4, up to 4GB |
| Video | Hardware decode H.265/H.264, supports 4K@60fps |
| Interfaces | HDMI 2.0a, USB 3.0, Gigabit Ethernet, WiFi/BT (on some boards) |
| Storage | eMMC, SD card boot |
Key advantages:
- Affordable: Development boards cost only 100-200 RMB
- Good community support: Mainline Linux kernel already supports H6/H616
- Sufficient performance: Quad-core A53 is more than enough for Linux, plus lightweight multimedia processing
- Great for learning: More “raw” than Raspberry Pi, requiring you to build the system yourself, you’ll learn more
Why Choose Buildroot?
There are three main approaches to building embedded Linux systems:
| Approach | Characteristics | Suitable Scenarios |
|---|---|---|
| Buildroot | Simple, fast, straightforward configuration | Product firmware, dedicated devices |
| Yocto/OpenEmbedded | Powerful, flexible but complex | Large commercial products |
| Debian/Ubuntu | Complete package management, easy to start | Prototype development, general-purpose devices |
Buildroot’s core philosophy: Use the simplest approach to generate an embedded Linux system that’s just good enough.
Its advantages include:
- Simple configuration:
make menuconfighandles all configuration in one interface - Fast builds: First full compilation takes 20-40 minutes, incremental builds take seconds
- Compact output: Generated rootfs can be as small as 30MB
- Reproducible: One configuration generates the exact same system, suitable for mass production
Hardware Checklist
Before starting, you’ll need to prepare these items:
| Item | Description | Reference Price |
|---|---|---|
| Orange Pi 3 LTS or H616 board | Search “Orange Pi 3 LTS” on Taobao | ¥120-180 |
| MicroSD card (16GB+) | SanDisk Class 10 recommended | ¥25 |
| 5V/3A power supply | Type-C or DC, depends on the board | ¥15 |
| USB-TTL serial cable | CH340 or CP2102 chip | ¥8 |
| HDMI cable + monitor | For debugging output (optional) | - |
| Ethernet cable | Gigabit Ethernet connection (optional) | - |
| SD card reader | For flashing on PC | ¥10 |
Serial port is essential! 90% of embedded Linux debugging relies on serial port—without it, you’re flying blind.
Setting Up the Build Environment
1. Install Dependencies
Ubuntu 22.04 or 24.04 is recommended (physical machine or VM). Install the required build dependencies:
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. Download Buildroot
# Download latest stable version (using 2026.05 as example)
wget https://buildroot.org/downloads/buildroot-2026.05.tar.gz
tar xf buildroot-2026.05.tar.gz
cd buildroot-2026.05
Or use Git to get the latest code:
git clone https://github.com/buildroot/buildroot.git
cd buildroot
3. Check Disk Space
Buildroot compilation requires at least 10GB disk space, 20GB+ is recommended:
df -h .
Configuring Buildroot
Method 1: Use Existing defconfig (Recommended for Beginners)
Buildroot comes with many default configurations for development boards. While there’s no direct orangepi_h616_defconfig, we can modify based on the generic aarch64 configuration:
# First check if there are related configurations
ls configs/ | grep -i "orange\|allwinner\|h6\|sun50i"
If there’s a similar configuration, you can use it directly:
make orangepi_3_defconfig # If available
Method 2: Configure from Scratch (Recommended for Learning)
make qemu_aarch64_virt_defconfig # Start with a base configuration
make menuconfig
In menuconfig, focus on configuring these key items:
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 (select 6.6 or newer LTS)
Kernel configuration: sunxi defconfig
(sun50i-h616) Device Tree Source file name
Note: The H616 Device Tree file name might be
sun50i-h616-orangepi-3-lts, check what’s available in the kernel source underarch/arm64/boot/dts/allwinner/.
Bootloader
Bootloaders --->
[*] U-Boot
U-Boot version: Custom version (select latest)
U-Boot configuration: orangepi_3_defconfig (or orangepi_3_lts_defconfig)
Filesystem
Filesystem images --->
[*] ext4 root filesystem
[*] tar the root filesystem
Quick Configuration Reference
A typical H616 Buildroot configuration (key items in .config):
# Target platform
BR2_aarch64=y
BR2_cortex_a53=y
# Toolchain
BR2_TOOLCHAIN_BUILDROOT_GLIBC=y
# Kernel
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"
# Filesystem
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_4=y
Starting the Build
After configuration, start compilation with one command:
make -j$(nproc)
Tip: Buildroot has supported top-level parallel builds since version 2020, so the
-jparameter is safe to use.
The build process will complete in sequence:
- Download source packages (about 5-10 minutes, depends on network)
- Extract and apply patches
- Configure and compile cross-compilation toolchain
- Compile Linux kernel
- Compile U-Boot
- Generate rootfs
First build takes about 30-60 minutes (depends on CPU performance).
Build Artifacts
After compilation, the output/images/ directory will contain:
output/images/
├── bl31.bin # ARM Trusted Firmware
├── Image # Linux kernel image
├── sun50i-h616-orangepi-3-lts.dtb # Device tree
├── u-boot-sunxi-with-spl.bin # U-Boot (with SPL)
├── rootfs.ext4 # Root filesystem
└── sdcard.img # Complete SD card image (if configured)
Flashing to SD Card
Method 1: Using sdcard.img (Simplest)
If Buildroot is configured to generate sdcard.img, just flash it directly:
# Check SD card device name (be careful not to get this wrong!)
lsblk
# Flash (assuming SD card is /dev/sdb)
sudo dd if=output/images/sdcard.img of=/dev/sdb bs=4M status=progress
sync
Method 2: Manual Partition and Flash
If there’s no sdcard.img, you’ll need to do it manually:
# 1. Partition (assuming SD card is /dev/sdb)
sudo fdisk /dev/sdb
# Create a Linux partition (/dev/sdb1)
# 2. Format
sudo mkfs.ext4 /dev/sdb1
# 3. Mount and write
sudo mount /dev/sdb1 /mnt
sudo cp output/images/rootfs.ext4 /mnt/
# Or extract tar:
# sudo tar xf output/images/rootfs.tar -C /mnt/
# 4. Copy kernel and DTB
sudo mkdir -p /mnt/boot
sudo cp output/images/Image /mnt/boot/
sudo cp output/images/*.dtb /mnt/boot/
# 5. Write U-Boot (SPL at 8KB offset)
sudo dd if=output/images/u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8
# 6. Unmount
sudo umount /mnt
sync
First Boot
1. Connect Serial Port
# Wiring: TX→RX, RX→TX, GND→GND
# Baud rate: 115200
# Linux/Mac:
screen /dev/ttyUSB0 115200
# Windows use PuTTY or MobaXterm
The serial port pins on H616 boards are usually on the header at the edge of the board, check the board’s schematic. Orange Pi 3 LTS UART0 pins:
| Pin | Function |
|---|---|
| Pin 6 (TX) | Serial transmit |
| Pin 8 (RX) | Serial receive |
| Pin 10 (GND) | Ground |
2. Insert SD Card, Power On
You should see U-Boot boot messages on the serial port:
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
...
Then Linux kernel boot logs, finally reaching the login prompt:
Welcome to Buildroot
buildroot login: root
#
Congratulations! Your embedded Linux system is running!
3. Basic Verification
# Check system information
uname -a
# Linux buildroot 6.6.32 #1 SMP ... aarch64 GNU/Linux
# Check CPU information
cat /proc/cpuinfo
# Check memory
free -h
# Check disk
df -h
# Network (if board has ethernet port)
ifconfig eth0 up
udhcpc -i eth0
ping -c 3 8.8.8.8
Adding Custom Applications
Buildroot’s most powerful feature is the ability to easily add the software packages you need.
Method 1: Add via menuconfig
make menuconfig
# Navigate to select required packages:
# Target packages --->
# [*] Networking applications --->
# [*] openssh
# [*] Text editors and viewers --->
# [*] vim
# [*] Interpreter languages and scripting --->
# [*] python3
Then recompile:
make
Method 2: Add Custom Program
Create a simple C program:
mkdir -p package/hello-world
Create package/hello-world/Config.in:
config BR2_PACKAGE_HELLO_WORLD
bool "hello-world"
help
A simple hello world program
Create 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))
Create source code hello.c in the package/hello-world/ directory:
#include <stdio.h>
int main(void) {
printf("Hello from Allwinner H616!\n");
printf("Running embedded Linux with Buildroot.\n");
return 0;
}
And Makefile:
CC ?= gcc
CFLAGS ?= -Wall -O2
all: hello
hello: hello.c
$(CC) $(CFLAGS) -o $@ $<
clean:
rm -f hello
Reconfigure and compile:
make menuconfig
# Target packages --->
# Miscellaneous --->
# [*] hello-world
make
Common Troubleshooting
Problem 1: No Serial Output
Troubleshooting steps:
- Check if TX/RX are reversed (cross connection)
- Confirm baud rate is 115200
- Check if the board’s UART pin definition is correct
- Use a multimeter to check if the TX pin has voltage changes
Problem 2: U-Boot Can’t Find Kernel After Boot
=>
Stuck at U-Boot command line means kernel loading failed.
Solution:
# Manually specify boot parameters at U-Boot command line
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
Problem 3: Kernel Panic - not syncing: VFS: Unable to mount root fs
Cause: rootfs partition not found or wrong format.
Solution:
- Check if the
root=parameter inbootargsmatches the actual partition - Confirm SD card partition format is correct (ext4)
- Check U-Boot’s
boot.cmd/boot.scrconfiguration
Problem 4: Compilation Error “No rule to make target”
Usually .config has errors. Solution:
# Clean and reconfigure
make clean
make menuconfig
make
Problem 5: Network Not Working
# Check if network card is recognized
ip link show
# Manually configure IP
ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up
route add default gw 192.168.1.1
# Or use DHCP
udhcpc -i eth0
If ip link doesn’t show eth0, the kernel might not have compiled the network card driver. Go back to menuconfig and check:
Kernel --->
[*] Linux Kernel
Kernel configuration: sunxi defconfig
sunxi defconfig should include the H616 GMAC driver, but if you used a custom kernel configuration, you need to confirm:
CONFIG_STMMAC_ETH=y
CONFIG_DWMAC_SUNXI=y
Buildroot Advanced Tips
1. Using Overlay Directory
Overlay lets you add custom files to the generated rootfs without modifying Buildroot source code:
# Set in menuconfig
# System configuration --->
# (/path/to/overlay) Root filesystem overlay directories
# Then create directory structure in overlay matching rootfs
overlay/
├── etc/
│ └── hostname
├── root/
│ └── .bashrc
└── usr/
└── bin/
└── my-script.sh
2. Using post-build Script
Automatically execute scripts after build completion:
# 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
# Add custom configurations, etc.
3. Using br2-external
If you have multiple products sharing the same Buildroot version, use the br2-external mechanism to separate board-level configurations:
# Create external configuration directory
mkdir -p br2-external-h616/{configs,board/h616,package}
# Create desc file
cat > br2-external-h616/external.desc <<EOF
name: H616
desc: Allwinner H616 board support
EOF
# When using
make BR2_EXTERNAL=/path/to/br2-external-h616 menuconfig
4. Speeding Up Compilation
# Use ccache to cache compilation results
# Toolchain --->
# [*] Enable compiler cache (ccache)
# Or set DL_DIR to share download directory
# In .config:
BR2_DL_DIR="/home/user/buildroot-dl"
From Buildroot to Product
Systems built with Buildroot are suitable for dedicated devices, such as:
- Smart gateway: Run MQTT client + protocol conversion
- Digital signage: HDMI output + lightweight web browser
- Industrial controller: Modbus communication + local HMI
- Edge AI box: Camera interface + inference engine
Productization considerations:
- Security hardening: Disable root login, enable SSH key authentication
- Watchdog: Configure hardware watchdog to prevent hangs
- OTA updates: Use A/B partition scheme for remote upgrades
- Log management: Use tmpfs for logs to protect SD card lifespan
- Power management: Configure cpufreq to reduce power consumption
Summary
Today we completed a zero-to-hero embedded Linux journey:
- ✅ Learned the basics of Allwinner H616 and Buildroot
- ✅ Set up cross-compilation environment
- ✅ Configured and compiled a complete Linux system
- ✅ Flashed to SD card and successfully booted
- ✅ Learned to add custom applications and troubleshoot common issues
Next steps:
- Try adding Python support to the system and write some IoT applications
- Study Device Tree to understand how hardware is described
- Learn U-Boot environment variables and boot process
- Try using Buildroot’s legal-info feature to generate software license reports
The world of embedded Linux is vast, and Buildroot is your best entry tool. It’s simple enough to get you started quickly, yet flexible enough to take you to product level.
Feel free to leave comments with any questions, see you in the next article!