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

max78000fthr

max78000

max78000evkit

max78000

max32650fthr

max32650

max32655fthr

max32655

max32660fthr

max32660

max32666fthr

max32665

max32670evkit

max32670

ad-apard32690-sl

max32690

max32690evkit

max32690

max32690fthr

max32690

ad-swiot1l-sl

max32650

max32657evkit

max32657

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_venv on first configure and installs the dependencies listed in tools/scripts/requirements.txt (kconfiglib, pylink-square and, 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):

  1. CodeFusion Studio (CFS) — pass -DCFS_PATH=/path/to/cfs, set the CFS_PATH environment variable, or place it at ~/cfs. When found, the libraries, vendor toolchain and OpenOCD are taken from inside the CFS tree.

  2. MAXIM_LIBRARIES — set this environment variable to the MaximSDK/Libraries path:

    # 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-workspace file at the repository root.

    Important

    To build, debug and run a project from VS Code you must open the generated no-os.code-workspace file, 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 --open to no_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

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.

Configuring options (menuconfig)

Kconfig options can be browsed and changed interactively after configuring:

$ cmake --build iio_demo --target menuconfig

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 the pylink-square Python 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 .elf to 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, run debug_server in one terminal and debug_gdb in 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.