Android IoT, Automotive, & Smart TV Customizations

From Zero to Boot: A Deep Dive into Porting Android Things to an ARM Cortex-A SoC

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction: The World of Android Things on Custom Hardware

Android Things, Google’s embedded operating system derived from Android, was designed to bring the power of Android’s ecosystem to the Internet of Things (IoT). While often associated with specific reference boards, the real power and flexibility lie in its ability to be ported to custom ARM Cortex-A System-on-Chips (SoCs). This article provides an expert-level, step-by-step guide for developers and engineers aiming to port Android Things to their bespoke ARM Cortex-A hardware, detailing the critical phases from bootloader bring-up to the Android framework integration.

Porting Android Things to a custom SoC offers numerous advantages, including cost optimization, tailored peripheral integration (e.g., specialized sensors, industrial interfaces), unique form factors, and optimized power consumption for specific applications. However, it’s a complex endeavor requiring deep knowledge of bootloaders, Linux kernel internals, device drivers, and the Android Open Source Project (AOSP) build system.

Phase 1: Prerequisites and Development Environment Setup

Before embarking on the porting journey, ensure you have the necessary hardware and software in place. A dedicated Linux build host (Ubuntu 18.04 LTS or newer recommended) with ample disk space (250GB+) and RAM (16GB+) is crucial.

Hardware Requirements:

  • Target ARM Cortex-A SoC development board with access to boot pins, JTAG/SWD, and a serial console (UART).
  • USB-to-Serial adapter for console access.
  • JTAG/SWD debugger (e.g., Segger J-Link, OpenOCD-compatible).
  • Reliable power supply.

Software and Toolchain Setup:

First, set up your AOSP build environment by installing essential packages:

sudo apt-get update && sudo apt-get install -y git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev libgl1-mesa-dev libxml2-utils xsltproc rsync wget bc python cpio android-sdk-platform-tools-core

Next, initialize the AOSP source tree, including Android Things:

mkdir android-things-src && cd android-things-src repo init -u https://android.googlesource.com/platform/manifest -b android-things-1.0.2_r1 --depth=1 repo sync -j$(nproc)

Ensure you have the correct ARM cross-compilation toolchain. For AOSP builds, the prebuilt toolchains usually suffice. For bootloader and kernel, you might need a specific `gcc-arm-linux-gnueabihf` (for 32-bit ARM) or `aarch64-linux-gnu` (for 64-bit ARM) toolchain if not provided by the vendor.

Phase 2: Bootloader Adaptation (U-Boot)

The bootloader is the first piece of software to run on your SoC, responsible for initializing basic hardware (DDR, clocks, GPIOs) and loading the kernel. U-Boot is the de-facto standard for ARM embedded systems.

1. Obtain U-Boot Source:

Start with a U-Boot branch that has support for a similar SoC or your specific vendor’s reference board. If unavailable, you’ll need to port a generic U-Boot or adapt a vendor-provided SDK’s bootloader.

git clone git://git.denx.de/u-boot.git cd u-boot

2. Create/Adapt Board Configuration:

Define your board’s specific configurations in `configs/`. This involves setting up DDR, clock trees, GPIO multiplexing, and boot device parameters.

# Example: Basic defconfig for a custom board CONFIG_ARM=y CONFIG_ARCH_ROCKCHIP=y # Or your specific SoC family CONFIG_ROCKCHIP_RK3399=y # Or your specific SoC CONFIG_SYS_TEXT_BASE=0x00080000 CONFIG_SYS_MALLOC_LEN=0x400000 CONFIG_DDR_SETTINGS_IN_CFG_H=y CONFIG_CMD_FASTBOOT=y CONFIG_SPL=y # If using SPL for multi-stage boot

You’ll also need to create a board-specific header file (e.g., `include/configs/.h`) to detail memory map, peripheral addresses, and pinmux settings.

3. Build and Flash U-Boot:

Compile U-Boot for your target:

export ARCH=arm64 # or arm export CROSS_COMPILE=/path/to/your/toolchain/bin/aarch64-linux-gnu- make  make -j$(nproc)

This will generate `u-boot.bin` (or `u-boot.img`, `u-boot-spl.bin` depending on configuration). The flashing method varies by SoC. Common methods include SD card, eMMC, or using a manufacturer’s flashing tool via USB or JTAG.

# Example: Flashing U-Boot to SD card dd if=u-boot-spl.bin of=/dev/sdX bs=512 seek=8 # For SPL+U-Boot dd if=u-boot.itb of=/dev/sdX bs=512 seek=16384 # For full U-Boot, sector values vary

Verify bootloader execution via the serial console.

Phase 3: Linux Kernel Porting

The Linux kernel forms the core of Android Things, managing hardware resources and providing the necessary services for the Android framework. Your goal is to achieve a stable kernel boot with essential drivers.

1. Obtain Kernel Source:

Start with a mainline Linux kernel (e.g., 4.9.x for Android Things 1.0.2_r1) or a vendor-provided kernel compatible with your SoC.

git clone https://github.com/torvalds/linux.git -b v4.9 cd linux

2. Device Tree Source (DTS) Modifications:

The Device Tree (DT) describes your board’s hardware to the kernel. You’ll need to create or modify `arch/arm64/boot/dts//.dts` and its dependencies.

  • CPU & Memory: Define core CPU properties, clock frequencies, and DDR memory regions.
  • Peripherals: Add nodes for crucial peripherals: UART (for console), I2C, SPI, USB, SD/eMMC, networking (Ethernet/WiFi), display interfaces (HDMI, MIPI DSI), touchscreens, and GPIOs.
  • Android Specifics: Ensure nodes for `ashmem`, `binder`, `logger`, and other Android kernel modules are correctly configured.
// Example DTS snippet for an I2C bus &i2c1 { status =

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner