|
Getting Started with Embedded Linux: Running Buildroot on Allwinner H616

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:

ParameterSpecification
CPUQuad-core ARM Cortex-A53 @ 1.5GHz
GPUMali G31 MP2
MemorySupports DDR3/DDR4, up to 4GB
VideoHardware decode H.265/H.264, supports 4K@60fps
InterfacesHDMI 2.0a, USB 3.0, Gigabit Ethernet, WiFi/BT (on some boards)
StorageeMMC, 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:

ApproachCharacteristicsSuitable Scenarios
BuildrootSimple, fast, straightforward configurationProduct firmware, dedicated devices
Yocto/OpenEmbeddedPowerful, flexible but complexLarge commercial products
Debian/UbuntuComplete package management, easy to startPrototype 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:

  1. Simple configuration: make menuconfig handles all configuration in one interface
  2. Fast builds: First full compilation takes 20-40 minutes, incremental builds take seconds
  3. Compact output: Generated rootfs can be as small as 30MB
  4. Reproducible: One configuration generates the exact same system, suitable for mass production

Hardware Checklist

Before starting, you’ll need to prepare these items:

ItemDescriptionReference Price
Orange Pi 3 LTS or H616 boardSearch “Orange Pi 3 LTS” on Taobao¥120-180
MicroSD card (16GB+)SanDisk Class 10 recommended¥25
5V/3A power supplyType-C or DC, depends on the board¥15
USB-TTL serial cableCH340 or CP2102 chip¥8
HDMI cable + monitorFor debugging output (optional)-
Ethernet cableGigabit Ethernet connection (optional)-
SD card readerFor 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

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
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 under arch/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 -j parameter is safe to use.

The build process will complete in sequence:

  1. Download source packages (about 5-10 minutes, depends on network)
  2. Extract and apply patches
  3. Configure and compile cross-compilation toolchain
  4. Compile Linux kernel
  5. Compile U-Boot
  6. 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:

PinFunction
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:

  1. Check if TX/RX are reversed (cross connection)
  2. Confirm baud rate is 115200
  3. Check if the board’s UART pin definition is correct
  4. 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 in bootargs matches the actual partition
  • Confirm SD card partition format is correct (ext4)
  • Check U-Boot’s boot.cmd / boot.scr configuration

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:

  1. Security hardening: Disable root login, enable SSH key authentication
  2. Watchdog: Configure hardware watchdog to prevent hangs
  3. OTA updates: Use A/B partition scheme for remote upgrades
  4. Log management: Use tmpfs for logs to protect SD card lifespan
  5. Power management: Configure cpufreq to reduce power consumption

Summary

Today we completed a zero-to-hero embedded Linux journey:

  1. ✅ Learned the basics of Allwinner H616 and Buildroot
  2. ✅ Set up cross-compilation environment
  3. ✅ Configured and compiled a complete Linux system
  4. ✅ Flashed to SD card and successfully booted
  5. ✅ 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!