Maxim Build Prerequisites (CMake)
This guide describes how to build a no-OS project for the Maxim platform using the CMake build system.
The CMake build is driven by board presets (defined in
board_configs/maxim/CMakePresets.json) and project defconfigs (Kconfig
fragments inside each project). A small helper script,
tools/scripts/no_os_build.py, discovers the valid project/variant/board
combinations and orchestrates the cmake configure and build steps for you.
Supported boards
The following Maxim boards (presets) are available out of the box. All presets use the vendor toolchain bundled with the Maxim SDK:
Preset / Board
Target chip
max78000fthrmax78000
max78000evkitmax78000
max32650fthrmax32650
max32655fthrmax32655
max32660fthrmax32660
max32666fthrmax32665
max32670evkitmax32670
ad-apard32690-slmax32690
max32690evkitmax32690
max32690fthrmax32690
ad-swiot1l-slmax32650
max32657evkitmax32657
Prerequisites
CMake 3.28 or newer (presets v7 are used).
Ninja (the presets use the Ninja generator).
Python 3. The build creates a private virtual environment under
.no_os_venvon first configure and installs the dependencies listed intools/scripts/requirements.txt(kconfiglib,pylink-squareand, on Windows,windows-curses).An ARM cross toolchain (
arm-none-eabi-gcc). All Maxim presets use the vendor toolchain bundled with the Maxim SDK, so no separate toolchain install is required.The Maxim SDK (see below), which also provides OpenOCD for flashing and debugging.
Install the Maxim SDK
The Maxim Microcontrollers SDK (MSDK) contains the register/startup files, linker scripts, vendor toolchain and OpenOCD needed to build and flash firmware for the MAX32xxx and MAX78xxx microcontrollers.
The build system locates the SDK in one of two ways (checked in this order):
CodeFusion Studio (CFS) — pass
-DCFS_PATH=/path/to/cfs, set theCFS_PATHenvironment variable, or place it at~/cfs. When found, the libraries, vendor toolchain and OpenOCD are taken from inside the CFS tree.MAXIM_LIBRARIES — set this environment variable to the
MaximSDK/Librariespath:# Linux (default install path) export MAXIM_LIBRARIES=~/MaximSDK/Libraries
# Windows (PowerShell), SDK installed to C:\MaximSDK $env:MAXIM_LIBRARIES = "C:\MaximSDK\Libraries"
If neither a CFS install nor MAXIM_LIBRARIES is found, configuration fails
with MAXIM_LIBRARIES is not set. Point it at the Maxim SDK Libraries
directory ....
(Optional) For visual debugging, install Visual Studio Code and the Cortex-Debug extension. IDE project files are generated automatically as part of the build, including a
no-os.code-workspacefile at the repository root.Important
To build, debug and run a project from VS Code you must open the generated
no-os.code-workspacefile, not just the no-OS folder. The debug launch configuration and include paths live in that workspace; opening the folder on its own will not pick them up. Open it with:$ code no-os.code-workspace
or from VS Code via
File > Open Workspace from File.... The build utility can also open it for you after a successful build by passing--opentono_os_build.py build.VS Code does not always prompt to open the workspace on its own (the notification is shown at most once per folder and is suppressed once dismissed), so open it explicitly as shown above.
Listing build combinations
From the no-OS repository root, list the valid combinations for the Maxim platform:
$ python tools/scripts/no_os_build.py list
You can filter by project, variant or board:
$ python tools/scripts/no_os_build.py list --project iio_demo $ python tools/scripts/no_os_build.py list --board max78000fthr
Each row is a PROJECT VARIANT BOARD PLATFORM tuple that can be fed back
to the build subcommand.
Building a project
Recommended: the build helper
The simplest way to configure and build is via no_os_build.py, which selects
the right preset, defconfig and board config for you:
$ python tools/scripts/no_os_build.py build \ --project iio_demo --variant iio --board max78000fthr
Useful options:
--clean— remove the build directory before configuring.
-j N/--jobs N— parallel compile jobs.
--parallel— build different boards in parallel.
--probe {openocd,jlink}— select the debug probe (needed for flashing).
--flash— flash after a successful build (requires--probe).
--dry-run— print thecmakecommands without running them.
Each combination is built into its own directory named
build/<project>-<variant>-<board> at the repo root (override the location
with --build-dir). The build artifacts (.elf, .hex, .bin) are placed
in <build-dir>/build.
Manual CMake invocation
You can also drive CMake directly. Configure with the board preset and select
the project/variant with PROJECT_DEFCONFIG:
$ cmake -B iio_demo --preset max78000fthr \ -DPROJECT_DEFCONFIG=iio_demo/iio.conf
Then build the project target (the target name is the project directory name):
$ cmake --build iio_demo --target iio_demo
Note
PROJECT_DEFCONFIG is a path relative to the projects/ directory of
the form <project>/<variant>.conf. When the project provides board
variants under projects/<project>/boards/<variant>/<board>.conf, the
matching board config is layered on top automatically based on the preset's
BOARD value.
Note
If no CMAKE_BUILD_TYPE is given, the build defaults to
RelWithDebInfo so the ELF contains debug info. Use
-DCMAKE_BUILD_TYPE=Debug for an unoptimized build, or MinSizeRel /
Release for size/speed.
MAX78000 core selection
MAXIM_CORE selects arm (the default) or riscv before compiler
selection. Keep PLATFORM=maxim and TARGET=max78000 for both cores. Use a
separate build directory and project defconfig for each image:
$ cmake --preset max78000fthr -B build/cpu1 \ -DMAXIM_CORE=riscv -DPROJECT_DEFCONFIG=<project>/<cpu1>.conf $ cmake --build build/cpu1 --target <project>
CPU1 uses riscv-none-elf-gcc, the RV32IMC instruction set with Zicsr and
Zifencei, and the ILP32 ABI. The toolchain locates the SDK's xPack compiler or a
compiler on PATH. CPU1 has its own generated Kconfig header; do not reuse
CPU0's build directory or configuration. RISC-V FreeRTOS support is not yet
provided by this platform.
The SDK RISC-V startup initializes CPU1's C runtime; the ARM host owns system
clock and board setup. CPU1's platform initialization starts an independent
elapsed-time timer. MAXIM_RISCV_TIME_TIMER selects timer 0 through 3
(default: 3). Reserve this timer in both applications: CPU1's no-OS timer and
PWM drivers reject attempts to use it. The timer runs from ISO/64 and extends
its count through a dedicated interrupt. Keep the timer interrupt enabled for
long-running firmware; if interrupts are masked, call no_os_get_time() at
least once per timer period (approximately 76 minutes). Do not gate or reset
this timer or its ISO clock while elapsed time is needed. SDK delay calls use
the CPU1 performance counter independently of elapsed time. Delays must not be
nested or used concurrently with other consumers that reset that counter.
MAXIM_RISCV_FLASH_ORIGIN and MAXIM_RISCV_FLASH_LENGTH select CPU1's
flash region. Defaults cover the whole flash for a standalone image. A combined
ARM/RISC-V build must supply a disjoint CPU1 flash region and reserve CPU1 SRAM
in the ARM linker layout. MAXIM_RISCV_SRAM2_RESERVE excludes a multiple of
16 bytes from the beginning of SRAM2 for debug or IPC storage. CPU1 refreshes
its SDK system/peripheral clock variable from hardware registers; it does not
rely on CPU0 placing that variable at the same address. Repeated CPU1
initialization preserves the elapsed-time epoch. Bare-metal syscall stubs come
from libnosys; firmware can provide a UART output implementation if needed.
IRQ entry points use the selected core's calling convention. RISC-V IRQ
priorities are fixed; attempts to set a programmable priority return
-ENOTSUP. CAPI mailbox transport can run on either core when allocation is
enabled; coprocessor lifecycle control is available only to the ARM host.
Firmware needing only SEMA register access can include maxim_ipc_raw.h
without the CAPI dispatcher. Reserve any IPC table at the same address in both
linker layouts and use the publication/acquisition helpers before reading its
slots. Serialize peripheral ownership and shared system-register updates with
a cross-core lock. CONFIG_SYS_MAXIM adds the reset wrapper and its linker
option, but the wrapper itself does not provide mutual exclusion.
Embedding a RISC-V image
A MAX78000 ARM project can build a separate CPU1 project and embed its binary:
include(maxim_coprocessor) maxim_add_riscv_coprocessor(my_application DEFCONFIG "${CMAKE_CURRENT_SOURCE_DIR}/riscv.conf" SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/riscv/main.c" INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/src" SRAM2_RESERVE 0x1000)
Call the helper after configuring the ARM target's sources and link libraries.
DEFCONFIG is required and enables CPU1's API/device/platform drivers through
Kconfig. List application sources in SOURCES; the platform supplies startup,
SDK, and no-OS driver sources. CPU1's configuration is copied into its own build
project and does not inherit CPU0's feature selections. INCLUDES and
DEFINES apply to the CPU1 application and its platform sources. A camera
application can enable CONFIG_CAMERA_OV7692_MAXIM and provide a board header
through INCLUDES. TIME_TIMER selects the reserved elapsed-time timer.
The helper links an ARM premap to determine CPU1's flash address, configures the
CPU1 CMake project with that address and remaining flash size, builds CPU1, and
embeds its binary in the final ARM ELF. Header changes are tracked by the normal
compiler dependency files. Moving the ARM code or changing the SRAM reservation
reconfigures CPU1 and relinks it. The final build checks that CPU1's vector table
is located exactly where ARM embeds it. The CPU1 ELF and map remain available
under coprocessor/build for debugging, along with its separate
no-os-core/build/no_os_config.h.
Flashing and Debugging
Flashing requires a debug probe to be selected at configure time via
-DPROBE=.... Two probes are supported:
openocd(default) — uses the OpenOCD that ships with the Maxim SDK.
jlink— uses a SEGGER J-Link via thepylink-squarePython package.
Configure with the desired probe, build, then run the flash target:
$ cmake -B iio_demo --preset max78000fthr \ -DPROJECT_DEFCONFIG=iio_demo/iio.conf -DPROBE=openocd $ cmake --build iio_demo --target iio_demo $ cmake --build iio_demo --target flash
Or, with the helper script in one step:
$ python tools/scripts/no_os_build.py build \ --project iio_demo --variant iio --board max78000fthr \ --probe openocd --flash
When the OpenOCD probe is selected, the following additional targets are available:
flash— program the.elfto the target and reset.
erase— erase the device flash.
debug— start OpenOCD and attach GDB (Linux/macOS).
debug_server— start OpenOCD and wait for a GDB connection. On Windows, rundebug_serverin one terminal anddebug_gdbin another.$ cmake --build iio_demo --target debug
To debug graphically from VS Code, open the generated no-os.code-workspace
(see the install step above) and launch the debug configuration from there;
opening the no-OS folder without the workspace will not load the debug setup.
Windows
The CMake flow works natively on Windows (PowerShell). Install the Maxim SDK to
a path without spaces (e.g. C:\MaximSDK) and set MAXIM_LIBRARIES as shown
above. Make sure cmake, ninja and python are available on PATH,
then follow the same configure/build/flash steps as on Linux.