주요 콘텐츠

Create Polyspace Test Target Registration Package for TRACE32 Debugging on Physical Hardware

R2026b

TRACE32 is a hardware and software toolset from Lauterbach that lets you load programs onto target hardware, run them, and inspect what they are doing. It works through a hardware debug probe that plugs into your target on one end and your computer on the other.

The TRACE32 toolset supports various ways of communicating with the target hardware. One of the supported ways is the Fast Data Exchange or FDX protocol. In this protocol, the test code reads and writes designated memory locations on the target, and the debug probe continuously moves that data between the target and your computer. No extra software licenses are needed beyond TRACE32 itself.

This topic shows how to create a Polyspace® Test™ target registration package for FDX communication with a physical target through the TRACE32 debug probe. The example uses a NXP S32K344 board (Cortex-M7) with a Lauterbach CombiProbe connected via USB.

Prerequisites

Before you begin, you need:

  • TRACE32 PowerView installed on your machine. Download from the Lauterbach Portal. This example uses <T32Install> as the TRACE32 software installation folder. For instance:

    • FDX source files from your TRACE32 installation, t32fdx.c and t32fdx.h, are located under <T32Install>\demo\arm\fdx\.

    • To open the PowerView software, you can double-click the appropriate executable in <T32Install>\bin.

  • NXP S32 Design Studio installed on your machine. It provides both the cross-compiler (GCC for ARM) and the SDK files (Real-Time Drivers, startup code, and peripheral headers) used in this example.

  • A Lauterbach debug probe (such as CombiProbe or PowerDebug) connected to your target board via USB.

Package Overview

Your target registration package for FDX communication contains the following files:

NXP_S32K3X4EVB_Q257_Package/
├── pstestPreferences.json
├── NXP_S32K3X4EVB_Q257_Preferences.m
├── NXP_S32K3X4EVB_Q257_PackageRegister.m
├── NXP_S32K3X4EVB_Q257_PackageUnregister.m
├── NXP_S32K3X4EVB_Q257_DebugIOTool.m
├── NXP_S32K3X4EVB_Q257_BoardDefinition.m
├── NXP_S32K3X4EVB_Q257_ToolchainDefinition.m
├── S32K344_Trace32_config.t32
├── s32k344evb-q257.cmm
├── src/
│   ├── rtiostream_fdx.c
│   ├── rtiostream_fdx.h
│   ├── NXP_S32K3X4EVB_Q257_board.c
│   ├── NXP_S32K3X4EVB_Q257_board.h
│   └── ...  (SDK/driver files for your board)
Of these, the .t32 file and the .cmm file control how TRACE32 connects to the target and sets up FDX communication. Sample versions of these files are provided with a TRACE32 installation but the key parts of the files are highlighted below. This example also walks through authoring the remainder of the files.

Create TRACE32 Files

The .t32 file and the .cmm files control how TRACE32 connects to the specific hardware board. The key parts of the files are outlined below. For more information on the syntaxes, see TRACE32 documentation.

Create TRACE32 Config File

Create a .t32 configuration file for your debug probe. The key settings for physical hardware with FDX are:

; USB debugger with auto-reconnect
PBI=USB
CONNECTIONMODE=AUTOCONNECT

; System paths
OS=
ID=TRACE32

; Remote API (used internally by the framework)
IC=NETASSIST
PORT=20000
PACKLEN=1024

The file has three sections:

  • Probe connection — The PBI= block specifies how TRACE32 connects to the debug hardware. USB selects a USB-attached probe. CONNECTIONMODE=AUTOCONNECT forces the connection even if a previous session did not release the probe cleanly — without it, subsequent runs fail with "TRACE32 device already used by other GUI."

  • System paths — OS= and ID=TRACE32 identify the TRACE32 instance. Set SYS= to your TRACE32 installation directory if it is not in the default location.

  • Remote API — The IC=NETASSIST block opens a UDP port (here 20000) that the framework uses to send control commands to TRACE32.

Create Startup Script

Create a PRACTICE script (.cmm) that configures the CPU, programs the flash, sets up FDX channels, and starts execution. The script receives four arguments from the framework: the ELF file path, pipe names for input and output, and a debug flag.

ENTRY &ELF_FILE &pipeIn &pipeOut &isDebug

IF (!OS.FILE(&ELF_FILE))
(
    PRINT %ERROR "The target binary location must be passed to the script."
    ENDDO
)

; CPU and debug port configuration (adapt to your target)
SYStem.CPU S32K344-M7
SYStem.CONFIG.DEBUGPORTTYPE SWD
IF COMBIPROBE()||UTRACE()
(
    SYStem.CONFIG.CONNECTOR MIPI20T
)
SYStem.Option DUALPORT ON
SYStem.MemAccess DAP
SYStem.JtagClock 10MHz
Trace.DISable
SYStem.Up

; Flash programming (adapt to your target)
DO ~~/demo/arm/flash/s32k3.cmm PREPAREONLY
FLASH.ReProgram ALL
Data.LOAD.Elf "&ELF_FILE"
FLASH.ReProgram OFF

; FDX configuration
FDX.RESet
SYStem.MemAccess DAP
FDX.METHOD BUFFERE

FDX.OutChannel FdxSendBuffer
FDX.InChannel FdxReceiveBuffer

FDX.PipeWRITE FdxSendBuffer "&pipeOut"
FDX.PipeREAD FdxReceiveBuffer "&pipeIn"
FDX.ENableChannel

; Optional: breakpoint for debug mode
if "&isDebug"=="1"
(
    Break.Set pst_run_test_case_function
)

Break.Set rtIOStreamClose /OnChip

Go

ENDDO

The script proceeds in four phases:

  • CPU and debug port setup — Selects the CPU type, configures the debug interface (SWD, JTAG clock speed), and brings the debug session up with SYStem.Up.

  • Flash programming — Erases and programs the target flash with the compiled test binary. The FLASH.ReProgram commands handle sector-level erase-before-write automatically.

  • FDX channel configuration — FDX.METHOD BUFFERE selects the ring buffer transfer method. FDX.OutChannel and FDX.InChannel bind FDX channels to symbols in target memory (FdxSendBuffer and FdxReceiveBuffer, defined in rtiostream_fdx.c). FDX.PipeWRITE and FDX.PipeREAD expose those channels as Windows named pipes whose names are provided by the framework.

  • Execution — Break.Set rtIOStreamClose /OnChip places a hardware breakpoint that halts the CPU when the test completes. Go starts execution and the script exits with ENDDO. From this point, the framework exchanges test data through the named pipes while the target runs.

Create Preferences Files

You can abstract away details specific to your target board and TRACE32 installation in a JSON file.

Create Preferences JSON

Create a pstestPreferences.json file with paths to your cross-compiler, TRACE32 files, and FDX source files:

{
    "GnuARMPath": "C:/path/to/your/gcc-arm-compiler",
    "SDK_Base_Path": "C:/path/to/your/sdk/base",
    "SDK_Platform_Path": "C:/path/to/your/sdk/platform",

    "T32Config": "C:/path/to/your/S32K344_Trace32_config.t32",
    "T32StartupScript": "C:/path/to/your/s32k344evb-q257.cmm",
    "T32Executable": "C:/T32/bin/windows64/t32marm.exe",

    "T32FdxFiles" : ["C:/T32/demo/arm/fdx/t32fdx.c",
                     "C:/T32/demo/arm/fdx/t32fdx.h"]
}

The JSON contains two groups of settings:

  • TRACE32 and FDX (required for all FDX setups) — T32Config and T32StartupScript point to the .t32 and .cmm files described in the previous sections. T32Executable is the path to the TRACE32 PowerView executable for your target architecture (for example, t32marm.exe for ARM). T32FdxFiles lists the t32fdx.c and t32fdx.h files from the TRACE32 installation. The framework compiles these into the target binary alongside your rtiostream_fdx.c.

  • Board-specific paths (vary by target) — GnuARMPath points to the cross-compiler. SDK_Base_Path and SDK_Platform_Path are specific to the NXP S32K3 RTD package and provide the headers and drivers for this board. Other boards would have different keys here depending on their SDK structure.

    For instance, the following are example paths from an NXP Design Studio installation:

        "GnuARMPath": "C:/NXP/S32DS.3.6.8/S32DS/build_tools/gcc_v11.4/gcc-11.4-arm32-eabi",
        "SDK_Base_Path": "C:/NXP/SW32K3_RTD_4.4_R21-11_3.0.0/eclipse/plugins/BaseNXP_TS_T40D34M30I0R0",
        "SDK_Platform_Path": "C:/NXP/SW32K3_RTD_4.4_R21-11_3.0.0/eclipse/plugins/Platform_TS_T40D34M30I0R0"

Create Preferences Class to Read JSON

Create a preferences class NXP_S32K3X4EVB_Q257_Preferences that inherits from pstest.target.Trace32.TargetPreferences:

classdef NXP_S32K3X4EVB_Q257_Preferences < pstest.target.Trace32.TargetPreferences
    properties(Constant)
        ToolChainName = "GCC ARM Cortex M | NXP_S32K3X4EVB-Q257"
        BoardName = "NXP_S32K3X4EVB_Q257 TRACE32"
    end
    methods(Access=public)
        function this = NXP_S32K3X4EVB_Q257_Preferences(jsonName)
            arguments
                jsonName (1,1) string = "pstestPreferences.json"
            end
            jsonFullPath = fullfile(fileparts(which(mfilename)), jsonName);
            this@pstest.target.Trace32.TargetPreferences(jsonFullPath);
        end
    end
end
This class reads the JSON file, adds additional properties (ToolchainName and BoardName), and implicitly adds some properties to enable a gateway for communication between Polyspace Test and the target hardware.

Instantiate Preferences Class From Package Registration File

In your packageRegister.m, instantiate the NXP_S32K3X4EVB_Q257_Preferences class you just created.

addpath(fileparts(mfilename('fullpath')));
prefs = NXP_S32K3X4EVB_Q257_Preferences();

if savepath
    warning('Error while saving path!');
end
rehash toolboxcache;
You can now use the variable prefs as a MATLAB® structure whose fields are the properties in the JSON file.

Implement Target-Side Data Transfer

Create a file rtiostream_fdx.c that implements the rtIOStream API using FDX. This file runs on the target and is responsible for exchanging data with the host through memory locations that the debug probe monitors.

The FDX API is provided by t32fdx.c and t32fdx.h from your TRACE32 installation (listed in T32FdxFiles in the JSON preferences).

#include <stddef.h>
#include "t32fdx.h"
#include "rtiostream_fdx.h"

#define RTIOSTREAM_NO_ERROR  (0)
#define RTIOSTREAM_ERROR    (-1)

/* FDX channel buffers (4096 bytes each) */
T32_Fdx_DefineChannel(FdxSendBuffer, 4096);     /* target -> host */
T32_Fdx_DefineChannel(FdxReceiveBuffer, 4096);   /* host -> target */

void initFDX(void) {
    T32_Fdx_InitChannel(FdxSendBuffer);
    T32_Fdx_InitChannel(FdxReceiveBuffer);
    T32_Fdx_EnableChannel(FdxSendBuffer);
    T32_Fdx_EnableChannel(FdxReceiveBuffer);
}

int rtIOStreamOpen(int argc, void *argv[])
{
    (void)argc;
    (void)argv;
    initFDX();
    return RTIOSTREAM_NO_ERROR;
}

int rtIOStreamClose(int streamID)
{
    (void)streamID;
    T32_Fdx_DisableChannel(FdxSendBuffer);
    T32_Fdx_DisableChannel(FdxReceiveBuffer);
    return RTIOSTREAM_NO_ERROR;
}

int rtIOStreamSend(int streamID, const void *src, size_t size, size_t *sizeSent)
{
    (void)streamID;
    int sent = T32_Fdx_Send(&FdxSendBuffer, (void *)src, (int)size);
    if (sent > 0) {
        *sizeSent = (size_t)sent;
        return RTIOSTREAM_NO_ERROR;
    }
    *sizeSent = 0;
    return RTIOSTREAM_ERROR;
}

int rtIOStreamRecv(int streamID, void *dst, size_t size, size_t *sizeRecvd)
{
    (void)streamID;
    int recvd = T32_Fdx_Receive(&FdxReceiveBuffer, dst, (int)size);
    *sizeRecvd = (size_t)(recvd > 0 ? recvd : 0);
    return RTIOSTREAM_NO_ERROR;
}

The implementation has three layers:

  • Channel declaration — T32_Fdx_DefineChannel reserves a block of target memory (here 4096 bytes) as a data buffer. The symbol names (FdxSendBuffer, FdxReceiveBuffer) must match the names used in the .cmm script so TRACE32 knows where to read and write.

  • Initialization — rtIOStreamOpen calls initFDX(), which initializes and enables both channels. This runs once at the start of the test.

  • Data transfer — rtIOStreamSend writes test data into the send buffer; rtIOStreamRecv reads incoming data from the receive buffer. The debug probe continuously moves data between these memory regions and the host. rtIOStreamClose disables both channels when the test finishes.

Create Execution Tool

Create a class NXP_S32K3X4EVB_Q257_DebugIOTool that inherits from pstest.target.Trace32.DebugIOTool:

classdef NXP_S32K3X4EVB_Q257_DebugIOTool < pstest.target.Trace32.DebugIOTool
    methods
        function this = NXP_S32K3X4EVB_Q257_DebugIOTool
            this@pstest.target.Trace32.DebugIOTool(NXP_S32K3X4EVB_Q257_Preferences());
        end
    end
end

This class is a thin wrapper. The parent class pstest.target.Trace32.DebugIOTool handles the full lifecycle: launching TRACE32, running the startup script, managing the gateway process, and shutting everything down after the test. All it needs from you is the preferences object so it knows which executable, config file, and script to use.

Register Board and Communication

Create a board definition file NXP_S32K3X4EVB_Q257_BoardDefinition.m that registers the board, its processor, source files, execution service, and communication settings. The file has five sections:

  • Board and processor — Creates the board and processor objects with the appropriate language implementation:

    prefs = NXP_S32K3X4EVB_Q257_Preferences();
    
    board = target.create("Board", "Name", prefs.BoardName);
    processor = target.create("Processor", "Name", "NXP_S32K3X4EVB_Q257", ...
        "Manufacturer", "NXP");
    langImpl = target.create("LanguageImplementation", ...
        "Name", "ARM Cortex-M Compatible", "Copy", "GNU GCC ARM 32-bit");
    processor.LanguageImplementations = langImpl;
    board.Processors = processor;

  • Source files and includes — Lists the board support files (startup code, drivers, SDK files) and the rtiostream_fdx.c implementation. The FDX files from the JSON preferences are also added here:

    baseSoftDir = [strrep(fileparts(mfilename('fullpath')), '\','/') '/src'];
    
    mainFunction = target.create("MainFunction", "Name", prefs.BoardName + " - Test Main");
    mainFunction.IncludeFiles = {'NXP_S32K3X4EVB_Q257_board.h'};
    mainFunction.InitializationCode = sprintf('init_NXP_S32K3X4EVB_Q257();\n');
    board.MainFunctions = mainFunction;
    
    mainFunction.BuildDependencies.SourceFiles = { ...
        [baseSoftDir, '/NXP_S32K3X4EVB_Q257_board.c'] ...
        [baseSoftDir, '/rtiostream_fdx.c'] ...
        ... % NXP SDK driver files (Clock_Ip, startup, nvic, etc.)
    };
    
    mainFunction.BuildDependencies.IncludePaths = { ...
        baseSoftDir, ...
        [baseSoftDir, '/NXP'], ...
        [prefs.SDK_Base_Path, '/include'], ...
        [prefs.SDK_Base_Path, '/header'], ...
        [prefs.SDK_Platform_Path, '/startup/include'] ...
    };
    
    % Add FDX files from TRACE32 installation
    for ii = 1:numel(prefs.T32FdxFiles)
        [folder, ~, ext] = fileparts(prefs.T32FdxFiles{ii});
        if strcmp(ext, '.h')
            mainFunction.BuildDependencies.IncludePaths{end+1} = folder;
        else
            mainFunction.BuildDependencies.SourceFiles{end+1} = prefs.T32FdxFiles{ii};
        end
    end

  • Execution service — Registers the DebugIOTool class as the execution tool for this board:

    className = 'NXP_S32K3X4EVB_Q257_DebugIOTool';
    customExecutionService = target.create("APIImplementation", ...
        "Name", prefs.BoardName + " - Execution Service implementation", ...
        "API", target.get("API", "ExecutionTool"), ...
        "BuildDependencies", target.create("MATLABDependencies", "Classes", className));
    
    executionTool = target.create("ExecutionService", ...
        "Name", prefs.BoardName + " - Target process execution", ...
        "APIImplementation", customExecutionService);
    board.Tools.ExecutionTools = executionTool;

  • Communication — Sets up the protocol stack and TCP connection to the gateway process. The gateway translates between TCP and the FDX named pipes:

    % Internal protocol (polls for breakpoint hits)
    pilProtocol = target.internal.create("PILDebugIOProtocol", ...
        "Name", prefs.BoardName + " - PIL DebugIOProtocol");
    pilProtocol.BreakpointPollingWaitTime = 10000;
    board.Inner.CommunicationProtocolStacks = pilProtocol;
    
    % External protocol (timeouts for receive and open)
    pilProtocolExt = target.create("PILProtocol", ...
        "Name", prefs.BoardName + " - PIL Protocol");
    pilProtocolExt.ReceiveTimeout = 10000;
    pilProtocolExt.OpenTimeout = 30000;
    board.CommunicationProtocolStacks = pilProtocolExt;
    
    % TCP connection to gateway
    connection = target.create("TargetConnection", "Name", prefs.BoardName);
    connection.CommunicationChannel = target.create("TCPChannel", ...
        "Name", prefs.BoardName + " - TCPChannel");
    connection.CommunicationChannel.IPAddress = "localhost";
    gatewayArgs = prefs.getGatewayArgs();
    connection.CommunicationChannel.Port = num2str(gatewayArgs.Port);
    connection.Target = board;
    
    target.add(connection, "UserInstall", true, "SuppressOutput", false);

Define Toolchain

Create a toolchain definition file NXP_S32K3X4EVB_Q257_ToolchainDefinition.m that registers the cross-compiler, linker, assembler, and archiver with the appropriate flags for your target processor.

The toolchain definition is not specific to TRACE32 or FDX — it defines how to compile, link, and produce an ELF binary for your target architecture. For a detailed walkthrough of creating a toolchain definition, see the toolchain section in Create Target Registration Packages for C/C++ Test Execution on Targets.

Bring It All Together in Package Registration

The package registration file NXP_S32K3X4EVB_Q257_PackageRegister.m is the entry point that ties all the pieces together. When you register the package, this file runs and calls the board definition and toolchain definition:

addpath(fileparts(mfilename('fullpath')));
if savepath
    warning('Error while saving path!');
end
rehash toolboxcache;
prefs = NXP_S32K3X4EVB_Q257_Preferences();
NXP_S32K3X4EVB_Q257_BoardDefinition();
NXP_S32K3X4EVB_Q257_ToolchainDefinition();

This file:

  • Adds the package folder to the MATLAB path so the framework can find your classes.

  • Saves the path and refreshes the toolbox cache so the registration persists across Polyspace Test sessions.

  • Calls NXP_S32K3X4EVB_Q257_BoardDefinition() to register the board, processor, source files, execution tool, and communication settings.

  • Calls NXP_S32K3X4EVB_Q257_ToolchainDefinition() to register the cross-compiler and build tools.

Register and Run

To register and use the target:

  1. Open a project configuration in the Polyspace Platform user interface. Select Manage Boards and register your package using the packageRegister.m file.

  2. On the Build tab, select your board name for the option Target board name (Testing).

  3. Build and run your tests. TRACE32 PowerView opens automatically, programs the flash, configures FDX channels, and starts execution. Test results are transferred through FDX pipes and displayed in the user interface.

Troubleshooting

SymptomLikely Cause
"FATAL ERROR from PBI-driver. TRACE32 device already used by other GUI."Add CONNECTIONMODE=AUTOCONNECT to the .t32 config file after the USB line. This forces the connection to the probe even if a previous session did not release it cleanly.
No data transfer or test hangsVerify that initFDX() is called in rtIOStreamOpen. Open the FDX channel window in TRACE32 PowerView and check that channels show "EnableChannel" selected and pipes are connected.
Flash programming errorPower-cycle both the debug probe and the target board to reset the hardware state.

Comparison with Instruction Set Simulator Workflow

TRACE32 also supports a software-only mode called the Instruction Set Simulator (ISS), which simulates CPU execution without physical hardware. For the ISS workflow, see Adapt Polyspace Test Target Package for TRACE32 Instruction Set Simulator.

The key differences between the two workflows are:

AspectFDX (this topic)ISS
HardwarePhysical board and debug probe requiredNo hardware required (software simulation)
T32XIL ToolboxNot requiredRequired
Data transferFDX named pipes (debug probe reads target memory)TCP port via RCL=NETTCP
Target-side codeCustom rtiostream_fdx.c using FDX APIProvided by T32XIL Toolbox (t32xil_rtiostream.c)
Startup scriptConfigures FDX channels, programs flash, issues GoLoads ELF only (T32XIL Toolbox manages execution)
Execution controlScript starts the CPU; breakpoint halts it at test endT32XIL Toolbox starts and stops the CPU

Choose the FDX workflow when you need to run tests on real hardware — for example, to verify timing behavior, peripheral interaction, or flash-resident code. Choose the ISS workflow for fast iteration without hardware dependencies.

See Also

Topics