Architecture

An OpenSMA image is a layered C/C++/Ada firmware built per SoC core and linked into a single downloadable image. This chapter shows how the pieces fit; the Build System chapter shows how the build drives them.

Layer composition

flowchart TB
    subgraph proj[Project: mcxn547helloworld]
        C0[core0/main.cpp]
        C1[core1/main.cpp]
    end
    subgraph nv[nv:: firmware — src/nv/]
        FEAT[Feature subsystems:<br/>mctp, pldm, spdm, vrot,<br/>fancontrol, telemetry, ...]
        COMMON[common / logger / ipc]
    end
    subgraph mod[Shared C++ modules — corepdk/modules/]
        MCTP[mctp-cpp]
        PLDM[pldm-fd]
        SPDM[spdm]
    end
    subgraph bsp[BSP — src/sys/ + src/boards/]
        SYS[sys/mcxn556, sys/mcu]
        BOARD[boards/mcxn547helloworld]
    end
    SDK[(NXP MCUXpresso SDK<br/>libexec/sdk)]

    C0 --> FEAT
    C1 --> FEAT
    FEAT --> COMMON
    FEAT --> MCTP
    FEAT --> PLDM
    FEAT --> SPDM
    COMMON --> SYS
    SYS --> BOARD
    BOARD --> SDK

The nv:: firmware layer

All firmware code lives in the nv:: namespace under src/nv/. The umbrella header src/nv/nv.h pulls in the common utilities (src/nv/nv.h:20) and defines the error-propagation macros the codebase uses everywhere — NV_TRY (src/nv/nv.h:24) and the NV_ROE_* “return-on-error” family (src/nv/nv.h:27), which check a status enum against ::Ok and early-return. This expected/status style (rather than exceptions) is characteristic of the whole tree.

Subsystems are directories under src/nv/ — e.g. src/nv/mctp/, src/nv/pldm/, src/nv/vrot/. The heavier protocol subsystems are thin nv:: wrappers over shared modules: src/nv/mctp/composer.h:22 simply aliases pdk::mctp::app::Composer from corepdk/modules/mctp-cpp/.

Shared modules (corepdk/modules/)

Three reusable C++ modules are consumed by the nv:: subsystems:

Module Path Wrapped by
MCTP corepdk/modules/mctp-cpp/ src/nv/mctp/
PLDM FD corepdk/modules/pldm-fd/ src/nv/pldm/
SPDM corepdk/modules/spdm/ src/nv/spdm/

Keeping the protocol engines in corepdk lets them be reused across projects while src/nv/ supplies the platform wiring.

BSP and the bootloader

The board/SoC layer lives under src/sys/ (mcu, mcxn236, mcxn556, x86) and src/boards/. The firmware bootloader wraps the SoC bootloader: nv::bootloader::Driver (src/nv/bootloader.h:28) derives from sys::bootloader::Driver (src/nv/bootloader.h:21), layering the nv:: API over the BSP primitive. See Platform / BSP & Projects.

Dual-core composition (core0 + core1)

The MCXN556S is dual-core. Building PLATFORM=mcxn556-both (mcu_build.sh:99) produces two images and folds them into one:

sequenceDiagram
    participant B as mcu_build.sh
    participant U as ./ubs (make)
    participant O as objcopy
    B->>U: build core1 (run_build_flow mcxn556-core1)
    U-->>B: core1.elf
    B->>O: objcopy core1.elf -> core1.bin
    O-->>B: core1.bin
    B->>B: xxd -i core1.bin -> core0/core1_image.c
    Note over B: array tagged .core1_image section
    B->>U: build core0 (embeds core1 image)
    U-->>B: core0 image (both cores)

Concretely, mcu_build.sh derives the per-core platforms (mcu_build.sh:106), builds core1 first, runs objcopy to get a raw binary (mcu_build.sh:120), then xxd -i turns that binary into src/projects/<project>/core0/core1_image.c (mcu_build.sh:131), rewriting the array into a .core1_image linker section (mcu_build.sh:133). core0 is then built with that image linked in, so the single downloaded artifact carries both cores. Each core has its own entry point: src/projects/mcxn547helloworld/core0/main.cpp and .../core1/main.cpp.

Next


Built with Just the Docs. Source-traced against NVIDIA/OpenSMA at 9b183d3 (v02.0020.0000). Methodology under appendices/trace-methodology.

This site uses Just the Docs, a documentation theme for Jekyll.