Build and Flashing

Overview

This guide walks you through the following steps:

  • Set up a Zephyr command-line development environment on Ubuntu or Windows (this guide supports Ubuntu 24.04 LTS and later versions; for other Linux distributions, refer to Install Linux Host Dependencies)

  • Obtain the source code

  • Build, flash, and run a sample application

Select and Update the Operating System

Click the operating system you are using.

Linux (Ubuntu):

Update system packages:

sudo apt update
sudo apt upgrade

Install Dependencies

Next, use the package manager to install the host dependencies.

The minimum version requirements for the main dependencies are as follows:

Tool

Minimum Version

CMake

3.28.0

Python

3.12

Device Tree Compiler

1.4.6

Linux (Ubuntu):
  1. Install the required dependencies using apt:

    sudo apt install --no-install-recommends git cmake ninja-build gperf \
      ccache dfu-util device-tree-compiler wget python3-dev python3-venv python3-tk \
      xz-utils file make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1
    

    Note

    On AArch64 (ARM64) systems, gcc-multilib and g++-multilib may not be available and should be removed from the installation list.

  2. Verify the installed versions of the main dependencies:

    cmake --version
    python3 --version
    dtc --version
    

    Compare the output versions against the requirements in the table above. To manually update dependencies, refer to the Install Linux Host Dependencies page.

Get Zephyr and Install Python Dependencies

Next, download Zephyr and its modules into a new west workspace. You will also install Zephyr’s Python dependencies in a Python virtual environment so they stay separate from your system Python installation.

The commands below use ~/nuwa as an example workspace path. You can choose any name and location — just replace it with your own path.

  1. Create a new virtual environment:

    python3 -m venv ~/nuwa/.venv
    
  2. Activate the virtual environment:

    source ~/nuwa/.venv/bin/activate
    

    After activation, the shell prompt will display a (.venv) prefix. You can exit the virtual environment at any time by running deactivate.

    Note

    Remember to activate the virtual environment each time you start working.

  3. Install west:

    pip install west
    
  4. Get the nuwa Zephyr source code:

    cd ~/nuwa
    west init -m https://github.com/Ameba-AIoT/nuwa.git
    west update
    
  5. Export the Zephyr CMake package. This allows CMake to automatically load the boilerplate code needed to build Zephyr applications:

    west zephyr-export
    
  6. Create a shortcut to nuwa.py. This Python script wraps west commands. When using nuwa.py to build, it automatically installs the Python dependencies and the Toolchain:

    ln -sf tools/meta_tools/nuwa.py nuwa.py
    
  7. Install Python dependencies using west (automatically installed when using nuwa.py):

    west packages pip --install
    

Install Toolchain

The Zephyr toolchain contains the compilers, assemblers, linkers, and other programs required to build Zephyr applications for each architecture supported by Zephyr.

Currently, the Ameba platform supports only the gnuarmemb toolchain provided by Ameba; the official Zephyr SDK toolchain released by the Zephyr project is not supported.

Use the following command to install the toolchain provided by Ameba (automatically installed when using nuwa.py):

cd ~/nuwa
west realtek ameba install

Command options let you specify where the SDK is installed and which architecture toolchains to install; run west realtek ameba install -h for details.

When building with nuwa.py, the ZEPHYR_TOOLCHAIN_VARIANT and GNUARMEMB_TOOLCHAIN_PATH environment variables are automatically set to point to the Toolchain installed here, with no manual configuration needed. If you skip nuwa.py and use raw west or native zephyr commands instead, configure these two toolchain environment variables manually:

Linux (Ubuntu):
export ZEPHYR_TOOLCHAIN_VARIANT=gnuarmemb
export GNUARMEMB_TOOLCHAIN_PATH=~/rtk-toolchain/asdk-12.3.1-4600/linux/newlib

For more details, see the Zephyr official documentation on GNU Arm Embedded.

Creating an Application

SDK uses CMake as its build system. This build system is application-centric, combining application code with the Zephyr kernel source into a single unified binary. It primarily consists of two parts:

  • Zephyr base directory: contains Zephyr’s own source code, kernel configuration options, and build definitions.

  • Application directory: contains all files specific to the application, such as configuration options and source code.

A typical application directory structure is as follows:

<app>
├── CMakeLists.txt     Entry build script that integrates with the Zephyr build system
├── app.overlay        Device Tree overlay file (optional)
├── prj.conf           Application-specific Kconfig configuration file
├── VERSION            Version identifier file (optional)
└── src
    └── main.c         Main application source file

Building the Application

The Zephyr build system compiles and links all components of the application into a single firmware image, which can run on either simulated or real hardware.

As with any CMake-based system, the build process occurs in two phases:

  • Configuration Phase: The CMake command-line tool generates build files when a generator is specified. In Zephyr, this phase also includes:

    • Generating build/zephyr/zephyr.dts and build/zephyr/include/generated/devicetree_generated.h based on DTS content and YAML bindings.

    • Collecting all Kconfig files, loading default configurations, and combining them with DTS output to determine the final set of configuration options and dependencies, resulting in build/zephyr/.config and build/zephyr/include/generated/autoconf.h.

    • Generating build system files, including CMakeCache.txt and build.ninja.

  • Build Phase: The native build tool (e.g., Ninja) executes the actual compilation and linking to produce the firmware binary. For more information on these concepts, refer to the CMake documentation: Introduction to CMake.

Build Command

The following command is used to build an application:

./nuwa.py build -b <BOARD> [-d <BUILD_DIR>] [-i <IMAGE_DIR>] [-p] [--sysbuild] <SOURCE_DIR>

Parameter descriptions:

  • build: executes the build subcommand.

  • -b <BOARD>: [Required] specifies the target board name (e.g., rtl872xda_evb). The build toolchain automatically loads the board configuration files under zephyr/boards/realtek/rtl872xda_evb.

  • <SOURCE_DIR>: [Required] positional argument specifying the path to the application project (relative to the SDK root directory).

  • -d <BUILD_DIR>: [Optional] specifies the output directory for build artifacts. All intermediate and result files generated during the build are stored here; the directory name can be freely chosen. Defaults to the build directory if not specified.

  • -i <IMAGE_DIR>: [Optional] specifies the output directory for the ImageTool firmware images. Defaults to SDK/images if not specified.

  • -p: [Optional] pristine rebuild. Without this flag, the build defaults to incremental (only regenerating when the configuration changes); with it, the entire build directory is cleaned and regenerated before building, equivalent to running west build -t pristine and then building.

  • --sysbuild: [Optional] creates a multi-domain (sysbuild) build system for building multiple images together (e.g., the application and MCUboot). See the Zephyr Sysbuild documentation for details.

Example: Building the Hello World Sample

./nuwa.py build -b rtl872xda_evb zephyr/samples/hello_world

Note

For the build phase, it’s best to use ./nuwa.py build (a wrapper around west build), which is more convenient than using west build manually. For environment setup, see Install Toolchain.

Partial Clean

Removes files generated during the Build Phase (e.g., .obj, .elf, .hex), but retains configuration files from the Configuration Phase (e.g., .config):

west build -t clean

Full Clean (Pristine)

Removes all files generated in both the Build Phase and Configuration Phase:

west build -t pristine

Opening the Menuconfig Interface

Menuconfig is part of the build process and depends on intermediate files generated during the Configuration Phase. If the build directory is empty, menuconfig cannot be launched, as the build system has no knowledge of the specific application directory at that point:

west build -t menuconfig

Contents of the Build Directory

The build directory is used by CMake and Ninja, and contains the build system files, intermediate files, and the final images. Its main structure is as follows:

SDK/build/
├── amebaxxx_gcc_project/    Intermediate files needed to merge multiple MCU images
├── build.ninja              Ninja build file
├── CMakeCache.txt           CMake configuration cache
├── CMakeFiles/              CMake internal files
├── rules.ninja              Ninja build rules
└── zephyr/                  Zephyr's generated files and build artifacts

After configuration and build complete, the following files are typically generated:

  • .config: the final effective Kconfig configuration.

  • .o, .a: compiled object files and static libraries.

  • zephyr.elf: the final ELF image containing the application and the Zephyr kernel.

  • zephyr.bin, zephyr.hex: other image formats converted from the ELF.

Images Directory and Firmware Flashing

After the build completes, the firmware can be flashed to the development board in either of the following two ways:

  • west flash: flashes the firmware directly using the west command-line tool, with no additional tools required. See west flash Usage for details.

  • ImageTool: after building with ./nuwa.py, the firmware for ImageTool is placed in the SDK/images directory by default; the ImageTool utility is located under SDK/tools/ameba/ImageTool. Refer to the Image Tool user guide for flashing instructions.

West Build and Flash Methods

west build Usage

Before building, set the toolchain environment variables. These are configured automatically when using ./nuwa.py, so no manual action is needed; if you use raw west commands directly, see Install Toolchain to configure them manually.

Common commands:

# Build the application for a specific board
west build -b <BOARD> <SOURCE_DIR>

# Clean the default build directory
west build -t pristine

west flash Usage

Linux:

A Windows PC is connected to the development board via a serial cable, and the Linux server performs remote flashing.

  1. Download and launch AmebaRemoteService on the Windows PC;

  2. Connect the Windows PC to the development board using a serial cable, and press the button to enter download mode;

  3. Execute the following command on the Linux server, <PORT> is the serial port of the development board on the Windows PC, and <WINDOWS_IP> is the IP address of that PC.

    west flash --port <PORT> --remote-server <WINDOWS_IP>
    

Note

  • If the firmware currently running on the development board has CONFIG_SHELL enabled, running west flash causes the flashing tool to send a command over the serial port before flashing, automatically putting the board into download mode without needing to press the button.