Last edited one month ago

How to migrate STM32CubeMPU examples from A35-TD flavor to M33-TD flavor

Applicable for STM32MP21x lines, STM32MP25x lines

Trusted domain applicability
This article is only applicable to M33-TD flavor of STM32MP2 series

1. Overview[edit | edit source]

This article explains how to migrate STM32CubeMPU Cortex®-M33 nonsecure (NS) examples and applications, originally developed for A35-TD flavor , so that they run correctly for M33-TD flavor .

For M33-TD flavor , the boot and integration model is different:

  • The Cortex®-A35 begins execution from ROM, loads FSBL‑M (first‑stage bootloader on M33) and then starts the Cortex®-M33.
  • The Cortex®-M33 becomes the TDCID of the platform. Trusted Firmware-M (TF‑M) runs in the secure state and manages secure operations and resource allocation.
  • Nonsecure firmware on Cortex®-M33 is implemented as FreeRTOS‑based applications as a NS Application Manager that uses the common stack Utilities/M33TD_NSAppCore.
  • The Cortex®-A35 then operates as a high‑performance remote processor (running OpenSTLinux) started and supervised by the M33 nonsecure application via TF‑M/SCMI and RemoteProc services.

The STM32CubeMPU package provides several reference projects for M33-TD flavor :

  • StarterApp_M33TD: Default nonsecure FreeRTOS application and NS Application Manager demonstration for system integration.[1][2]
  • Template_StarterApp_M33TD: Bare‑minimum NS Application Manager profile built on top of Utilities/M33TD_NSAppCore, intended as the baseline for custom applications and for migrating existing examples to M33-TD flavor .[3]
  • TestApp_M33TD: Demonstration application built on the NS Application Manager, showing how to add additional application logic (a test sequence) on top of the common stack and how to control its behavior via build‑time options.[4]

These projects demonstrate how the Cortex®‑M33 NS application participates in the full platform boot for M33-TD flavor , and how user code can be added as FreeRTOS tasks on top of a shared NS Application Manager.

Information
The Cortex®-M33 nonsecure demonstration applications such as StarterApp_M33TD, Template_StarterApp_M33TD and TestApp_M33TD are available for both STM32MP215F-DK and STM32MP257F-EV1 in the STM32CubeMP2 package.

2. Architectural changes from A35-TD flavor to M33-TD flavor [edit | edit source]

2.1. Boot chain and firmware placement[edit | edit source]

For A35-TD flavor :

  • the Cortex®‑A35 is typically the TDCID: it boots first (BL2/TF‑A/OP‑TEE), and the Cortex®‑M firmware is often loaded and controlled later through the Cortex‑M RemoteProc mechanism.

For M33-TD flavor :

  • The boot chain starts on Cortex®‑A35 ROM, but boot responsibility is delegated to the Cortex®‑M33 through FSBL‑M:
    • A35 ROMFSBL‑M (MCUboot) → TF‑M (CM33‑S) → NS Application Manager (CM33‑NS).
  • Once the CM33‑NS NS Application Manager is running, it brings up the Cortex®‑A35 as a high‑performance remote processor (Linux or bare metal) via TF‑M SCMI and remote processor services.

For a detailed view of the boot chain, refer to STM32MP2 M33‑TD flavor boot chain.

2.2. Role of TF‑M and NS Application Manager[edit | edit source]

For M33-TD flavor :

  • Trusted Firmware-M (TF‑M) runs in the secure state of Cortex®‑M33 and:
    • Manages secure operations, secure services and resource access control.
    • Owns the secure state; STM32CubeMPU firmware is always nonsecure.
  • STM32CubeMPU firmware runs in the nonsecure state of Cortex®‑M33 and must:
    • Access secure features (for example secure storage, remote processor management, clocks, power services) via TF‑M APIs (SCMI, platform IOCTLs, etc.).
    • Execute as a FreeRTOS‑based application managed by a NS Application Manager built on top of the common stack Utilities/M33TD_NSAppCore.

The NS Application Manager provides a set of core tasks, such as:

  • Logger task (centralized logging to UART console).
  • SCMI manager task (SCMI notifications and events).
  • Remote processor task (Cortex®‑A35 start/stop/monitor and crash recovery).
  • Watchdog monitor task.
  • Optional user application task (for example LED activity).

Template_StarterApp_M33TD integrates this stack and enables a bare‑minimum NS Application Manager profile that is suitable as a base project for migrating STM32CubeMPU Cortex®‑M33 NS examples and applications to M33-TD flavor .

3. Platform constraints for M33-TD nonsecure applications[edit | edit source]

3.1. Linker file and memory map constraints[edit | edit source]

The CM33‑NS linker script must be aligned with the reserved memory layout defined in the external device tree (external‑DT). Under M33-TD flavor , specific DDR regions are reserved for CM33‑NS firmware code and data, for example (excerpt):

cm33_cube_fw: cm33-cube-fw@80080000 {
			compatible = "reserved-memory";
			reg = <0x0 0x80080000 0x0 0x80000>;
			#memory-region-cells = <0>;
		};
		
cm33_cube_data: cm33-cube-data@80200000 {
			compatible = "reserved-memory";
			reg = <0x0 0x80200000 0x0 0x800000>;
			#memory-region-cells = <0>;
		};

The linker script used by the CM33‑NS application (for example stm32mp2xx_DDR_m33_ns.ld in StarterApp_M33TD) must:

  • Place code and read‑only data into the region defined by cm33_cube_fw.
  • Place read/write data and BSS into the region defined by cm33_cube_data.
  • Respect alignment and size constraints for the reserved memory areas.

If a migrated example or custom application requires **more CM33 code space** than the default:

  • Adjust the external‑DT reserved memory:
    • Increase the size of cm33_cube_fw (code region).
    • Decrease the size of cm33_cube_data if necessary, while keeping the total reserved size within platform limits and aligned as required.
  • Update the CM33‑NS linker script accordingly:
    • Align the memory region used for .text, .rodata, .data and .bss with the new addresses and sizes.
    • Ensure that the linker script and external‑DT define identical base addresses and lengths for the CM33‑NS regions.

If the external‑DT and linker script diverge (for example code or data extending beyond the reserved region), runtime faults or unpredictable behavior may occur. Always keep the external‑DT reserved memory description and the CM33‑NS linker script aligned.

Information

For Cube examples, the linker file provided in the delivered M33‑TD demonstration projects (for example, StarterApp_M33TD[5][6]) can be used as a template when adapting custom applications for M33-TD flavor .

3.2. System resource allocation[edit | edit source]


Resource allocation strategy when STM32CubeMP2 cube non-secure firmware runs along with other OSTL components differs significantly between M33-TD flavor and A35-TD flavor .
For M33-TD flavor , the Cortex‑M33 secure firmware (TF‑M) manages system resources and exposes only a defined subset of peripherals to the nonsecure CM33 context.

This is a key point for migration: when moving an example or application from A35-TD flavor to M33-TD flavor , the CM33 nonsecure application is not running alone. TF‑M is running on the same core and owns some peripherals and memory regions. Only peripherals explicitly assigned to CM33‑NS in the RIF configuration can be used directly by nonsecure examples and applications.

3.2.1. System resource allocation for M33-TD flavor [edit | edit source]


In this setup, resource allocation is primarily managed by the Trusted Firmware-M (TF-M) secure stack running on the Cortex‑M33 as TDCID. This centralizes security and resource provisioning within the Cortex‑M33 environment, ensuring that only authorized nonsecure firmware can access specific hardware resources.

The following peripherals are available for use by Cortex‑M33 nonsecure examples and applications by default (depending on the STM32MP2 device line):

STM32MP25 lines

  • TIM6, IWDG4, UART5, ICACHE/DCACHE, LTDC_L3, USART6, TIM3/8, LPTIM4, SPI1/3/8, I2C1/8, ADC3, WWDG1, I3C4
(and associated GPIO pins, RCC kernel clocks, RCC GPIO clocks and HPDMA4 channels for these peripherals)


STM32MP21 lines

  • TIM6, IWDG4, UART4, ICACHE/DCACHE, LTDC_L3, TIM3/8, LPTIM4, SPI1, WWDG1, I3C2
(and associated GPIO pins, RCC kernel clocks and RCC GPIO clocks for these peripherals)


This allocation ensures that nonsecure applications have access to essential peripherals while maintaining a robust security boundary enforced by TF‑M.[7]

Information
Click on "Expand", visible on the right side of the page, to view additional information for Assigning a peripheral to CM33 Non‑Secure (MP21/MP25).

Purpose
Quick guidance to reassign a peripheral to the CM33 Non‑Secure context using the external‑DT delivered in STM32CubeMP2 Package, using RIF configuration files in: Firmware/Utilities/dt-stm32mp/stm32mp2/m33-td/tfm/. Use the -rif*.dtsi file matching your TF‑M build mode.

How to Modify

  1. Open the RIF file matching your TF‑M build mode:
  Firmware/Utilities/dt-stm32mp/stm32mp2/m33-td/tfm/<board>-...-rif*.dtsi
  1. Under &rifsc, locate the peripheral and switch ownership to CM33‑NS by setting its CID and secure/privilege RIF configuration to the Arm®-Cortex®-M33 Non‑Secure context.
  2. For GPIO, adjust the specific RIF_IOPORT_PIN(n) rule under the corresponding &gpioX node.
  3. If the device uses DMA or shared buffers, ensure related RISAF/RISAB memory regions allow the same CM33‑NS domain.
  4. Rebuild and redeploy so the new DT takes effect; verify on target.

Refer to How to import, build and debug STM32CubeMP2 StarterAppM33TD demonstration in STM32CubeIDE for build, import and debug steps.

Example A — Reassign TIM1 to CM33‑NS
Locate TIM1 peripheral under &rifsc and switch the CID from CID1 (Arm®-Cortex®-A35) to CID2 (Arm®-Cortex®-M33).

Original:

&rifsc {
  st,protreg = <
    RIFPROT(STM32MP25_RIFSC_TIM1_ID, RIF_UNUSED, RIF_UNLOCK,
            RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
    ...
  >;
};

Modified (assign to ArmCortex‑M33 Non‑Secure context):

&rifsc {
  st,protreg = <
    RIFPROT(STM32MP25_RIFSC_TIM1_ID, RIF_UNUSED, RIF_UNLOCK,
            RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
    ...
  >;
};

Optional (unprivileged CM33‑NS):

RIFPROT(STM32MP25_RIFSC_TIM1_ID, RIF_UNUSED, RIF_UNLOCK,
        RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)

Verification tips:

  • From CM33‑NS, enable the TIM1 clock and write its registers; confirm behavior.
  • On Linux (ArmCortex‑A35), disable or remove the TIM1 node/driver to avoid conflicts.
  • If TIM1 uses DMA, ensure the DMA controller channels and target buffers are permitted for RIF_CID2/RIF_NSEC.

Example B — Assign a GPIO pin to CM33‑NS
Edit the appropriate GPIO port node (example PF7):

Example existing port policy:

&gpiof {
  st,protreg = <
    RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK,
            RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
    ...
  >;
};

Add or adjust the specific pin (PF7) for CM33‑NS ownership:

&gpiof {
  st,protreg = <
    RIFPROT(RIF_IOPORT_PIN(7),  RIF_UNUSED, RIF_UNLOCK,
            RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
    ...
  >;
};

Notes:

  • Use the correct pin index with RIF_IOPORT_PIN(n).
  • Remove/disable conflicting pinctrl/consumers for that pin in the Linux (ArmCortex‑A35) Device Tree.

Memory blocks (when relevant)
If the peripheral DMA‑accesses buffers or uses shared memory, align RISAF/RISAB regions with the CM33‑NS domain to avoid access faults.

Minimal shared memory example (allow both ArmCortex‑A35 and CM33):

&ipc_shmem {
  st,protreg = <
    RISAFPROT(RISAF_REG_ID(5),
              RIF_CID1_BF|RIF_CID2_BF,  /* readers  */
              RIF_CID1_BF|RIF_CID2_BF,  /* writers  */
              RIF_UNUSED,               /* exec     */
              RIF_NSEC,                 /* security */
              RIF_ENC_DIS,              /* encrypt  */
              RIF_BREN_EN)              /* Base Region   */
  >;
};

Build, flash, verify (quick)

  • Rebuild with the TF‑M dev mode matching the edited -rif*.dtsi (see the referenced page above).
  • Flash updated binaries to the board.
  • Verify on target:
- CM33‑NS: initialize clocks and access the reassigned peripheral.
- Linux (Arm<sup>®</sup>-Cortex<sup>®</sup>-A35): confirm the device is not bound/used after reassignment.
- DMA/memory: validate data paths and firewall regions match the chosen domain.

Common issues and checks

  • Linux (Arm®-Cortex®-A35) still owns the device (disable/unbind in the Linux Device Tree).
  • SEC/NSEC mismatch between device and memory regions.
  • IRQ routing not permitted to CM33 (check &extiX st,proccid).

Reverting a change
Restore RIF_CID2 back to RIF_CID1 (and any other attributes if modified), rebuild, and redeploy. Keep Linux and TF‑M RIF DTs synchronized to reflect the intended ownership.

Information
Required GPIO pins, RCC kernel clock and RCC GPIO clock resources are also assigned to Cortex®-M33 for the above peripherals under both STM32MP25/STM32MP21 lines. For the exact security configuration, refer to the external‑DT delivered in the STM32CubeMP2 package.

3.2.2. Summary of differences[edit | edit source]

  • For M33-TD flavor
    • Resource allocation is managed by the TF‑M stack running on Cortex‑M33.
    • Nonsecure applications have access to a defined set of peripherals, as listed above (plus any peripherals explicitly reassigned via RIF configuration).
    • Security boundaries are enforced at the firmware level within the Cortex‑M33 trusted secure domain.
  • For A35-TD flavor
    • Resource allocation is managed by the OP‑TEE stack running on Cortex‑A35.
    • All resource access is mediated by the OP‑TEE stack, providing a unified security model for the A35-TD flavor environment.

This distinction is crucial for developers targeting STM32MP2 platforms, as it impacts how applications are designed, which peripherals can be used directly from CM33‑NS, and how the overall security model of the system behaves.

3.3. NS Application Manager tasks and timing constraints[edit | edit source]

The NS Application Manager provided by Utilities/M33TD_NSAppCore runs several system tasks in the CM33‑NS domain, including:

  • Logger task (centralized logging).
  • SCMI manager task (SCMI notifications/events).
  • Remote processor task (Cortex‑A35 start/stop/monitor, crash recovery).
  • Watchdog monitor task.

These tasks are part of the platform behavior for M33-TD flavor : they handle TF‑M notifications and SCMI messages that are required for:

  • The Cortex‑A35/Linux boot sequences.
  • Ongoing power‑management and system control flows.

For correct behavior (especially when Linux is booted on the Cortex‑A35 remote processor), these NSAppCore tasks must remain responsive. Custom tasks added on top of the NS Application Manager must therefore be designed so that SCMI manager, RemoteProc and other system tasks can still be scheduled and respond to TF‑M notifications in a timely manner.

4. Firmware placement and boot process[edit | edit source]

A significant change for M33-TD flavor is the placement of Cortex‑M33 firmware on the boot device prior to platform boot‑up. This contrasts with A35-TD flavor , where Cortex‑M33 firmware is often executed at runtime using the RemoteProc utility.

For M33-TD flavor :

  • The combined TF‑M (secure) + CM33‑NS application image is prepared during the build process (assembled and signed together).
  • MCUBoot and TF‑M handle the secure boot chain and then start the CM33‑NS NS Application Manager.
  • The Cortex‑A35 is then brought up as a high‑performance remote processor by the nonsecure M33 application (via RemoteProc and SCMI services).
Information

To generate and flash binaries for Cortex®-M33 NS applications (such as StarterApp_M33TD, Template_StarterApp_M33TD and TestApp_M33TD), follow the README files of the demonstration projects in the STM32CubeMP2 package. These READMEs describe the TF‑M build, postbuild (assemble/sign) steps, and integration into the OpenSTLinux image tree.[8][9]

5. Migrating examples and applications to the M33-TD flavor[edit | edit source]

Once the architectural differences, memory mapping and resource allocation constraints are understood, existing Cortex‑M33 nonsecure examples and applications (originally developed for A35-TD flavor ) can be migrated to M33-TD flavor by running them as additional FreeRTOS tasks on top of the NS Application Manager.

The recommended migration workflow is:

  1. Use Template_StarterApp_M33TD as the base NS Application Manager project for the target board.
  2. Integrate your example/application logic as one or more CM33‑NS FreeRTOS tasks inside this project.
  3. Ensure that the example:
    • Uses only peripherals and memory regions available to CM33‑NS, or updates the RIF configuration and external‑DT if additional peripherals are needed.
    • Respects the timing constraints of the NS Application Manager system tasks (SCMI manager, RemoteProc, WdgMonitor, etc.), especially if the full M33‑TD ecosystem boot (including Cortex‑A35/Linux as high‑performance remote processor) is required.

5.1. Using Template_StarterApp_M33TD as a base project[edit | edit source]

Template_StarterApp_M33TD is delivered as a bare‑minimum NS Application Manager profile built on top of the common stack Utilities/M33TD_NSAppCore and is intended as the starting point for custom applications and for migrating existing examples to M33-TD flavor .

Key characteristics:

  • Uses the NS Application Manager bootstrap NSCoreApp_Init() provided by the utility stack.
  • Enables the minimal set of core NSAppCore tasks:
    • Logger task.
    • SCMI manager task.
    • Remote processor task.
    • Watchdog monitor task.
    • A simple user application task (LED activity) used as a liveness indicator.
  • Relies on board‑specific driver interfaces implemented under the application project (AppDriver layer) to bind the generic tasks to the actual hardware.

When Template_StarterApp_M33TD is used as migration base for M33-TD flavor :

  • Import Template_StarterApp_M33TD into STM32CubeIDE for your board (for example STM32MP215F-DK or STM32MP257F-EV1).
  • Ensure that the common stack Utilities/M33TD_NSAppCore is included and configured as in the template.
  • Keep the minimal NS Application Manager tasks enabled (logger, SCMI, RemoteProc, WdgMonitor, user app), unless your use case explicitly requires a different profile.
  • Adapt the AppDriver implementations for your board (for example UART instance and pins for logging, LEDs for the user app task, button GPIOs if button features are enabled).

5.1.1. Reusing baseline UART and USER button configuration[edit | edit source]

The NS Application Manager baseline (Template_StarterApp_M33TD and related profiles) already configures several key peripherals via the utility stack:

  • The Logger task uses the logger output driver to configure the UART console on CM33 (for example by calling logger_output_init(), which sets up the COM port and selects it as the log output). This provides a standard CM33 logging path.
  • When enabled, the Button Monitor task configures the USER button (for example USER2) and its EXTI line to classify button events (short press, long press, etc.) and notify interested components.

For migrated examples and custom applications:

  • Reuse the existing logging path provided by the Logger task instead of reconfiguring the UART or changing the COM port. Use the NSAppCore logging APIs or the logger driver so that all logs appear on the existing CM33 UART console.
  • If button events are needed, reuse the existing USER button and EXTI configuration by registering for button events from the Button Monitor task (where available) instead of reinitializing EXTI for that pin.
Information
The UART console and USER button resources are already owned and configured by the NS Application Manager baseline through the utility stack. Migrated examples should reuse these facilities (logging and button monitoring) rather than reconfiguring UART/EXTI, to avoid conflicts with the existing configuration.

5.2. Adding a custom FreeRTOS task on top of the NS Application Manager[edit | edit source]

When migrating an existing example or creating a new CM33‑NS application, the recommended approach is to add a dedicated FreeRTOS task on top of Template_StarterApp_M33TD, while keeping the NS Application Manager stack (M33TD_NSAppCore) unchanged.

A typical pattern is:

  1. Create a task header (for example custom_task.h) under the FreeRTOS application folder:
    • Define stack size and priority macros for the task, for example:
    #define CUSTOM_TASK_STACK_SIZE (1024U)
    #define CUSTOM_TASK_PRIORITY osPriorityNormal
    • Declare the task control APIs:
    void CustomTask_Init(void);
    void CustomTask_DeInit(void); (optional).
  2. Implement the task in custom_task.c:
    • Include CMSIS‑RTOS2 / FreeRTOS headers and your project headers.
    • Implement the task thread function, for example:
static void CustomTask_Thread(void *argument)
{
  for (;;)
  {
    /* Example / application logic */
    osDelay(100);  /* or wait on events/queues */
  }
}
    • In CustomTask_Init(), fill an osThreadAttr_t structure (name, stack size, priority) and create the thread using osThreadNew(), for example:
void CustomTask_Init(void)
{
  static const osThreadAttr_t customTask_attr =
  {
    .name       = "CustomTask",
    .stack_size = CUSTOM_TASK_STACK_SIZE,
    .priority   = CUSTOM_TASK_PRIORITY,
  };

  (void)osThreadNew(CustomTask_Thread, NULL, &customTask_attr);
}
  1. Integrate the task in main.c:
    • Keep the Template_StarterApp_M33TD bootstrap sequence. A common pattern is:
int main(void)
{
  /* HAL and system initialization */
  HAL_Init();
  SystemClock_Config();

  /* Optional: board-level initialization for custom application logic */
  Board_Init();

  /* Initialize the RTOS kernel */
  osKernelInitialize();

  /* Initialize the NS Application Manager stack (M33TD_NSAppCore) */
  NSCoreApp_Init();

  /* Initialize the custom example/application task */
  CustomTask_Init();

  /* Start the RTOS scheduler */
  osKernelStart();

  /* The program should not reach here */
  for (;;)
  {
  }
}
  1. Add the source file to the build:
    • Add custom_task.c to your CMake target sources or to the STM32CubeIDE CM33‑NS application project (for example under Application/User/FREERTOS/App).
    • No changes are required inside Utilities/M33TD_NSAppCore.
  2. Keep NS Application Manager configuration centralized:
    • NSAppCore tasks remain controlled by the configuration headers (for example app_tasks_config.h and nsappcore_config.h) and by project preprocessor settings.
    • Your custom task is initialized explicitly from main.c and uses its own stack/priority macros defined in custom_task.h.

A simplified view of the project organization when adding a custom task on top of Template_StarterApp_M33TD is:

Template_StarterApp_M33TD_CM33_NonSecure
├── Includes
├── Application
│   ├── Startup
│   │   └── startup_stm32mp21xx_m33_ns.S      <!-- Startup file (unchanged for a given SoC) -->
│   └── User
│       ├── Core
│       │   └── Src
│       │       ├── main.c                    <!-- Calls NSCoreApp_Init + CustomTask_Init + osKernelStart -->
│       │       ├── stm32mp2xx_hal_msp.c
│       │       ├── stm32mp2xx_hal_timebase_tim.c
│       │       ├── stm32mp2xx_it.c
│       │       └── syscalls.c
│       └── FREERTOS
│           ├── App                           <!-- Custom CM33‑NS FreeRTOS application code -->
│           │   ├── custom_task.h             <!-- Stack/priority macros, Init/DeInit prototypes -->
│           │   ├── custom_task.c             <!-- CMSIS‑RTOS2 thread, example/application logic -->
│           │   └── (other user-level FreeRTOS sources)
│           └── M33TD_NSAppCore
│               └── AppDriver                 <!-- Board-specific drivers used by NSAppCore and your task -->
├── TFM
│   └── App
│       ├── tfm_ioctl_cpu_api.c
│       ├── tfm_ns_interface.c
│       ├── tfm_platform_api.c
│       ├── tfm_scmi_api.c
│       └── tfm_tz_psa_ns_api.c
├── Doc
├── Drivers
├── Middlewares
│   └── FreeRTOS
├── Utilities
│   └── M33TD_NSAppCore
│       ├── App
│       │   └── Src                           <!-- NSAppCore task implementations (logger, SCMI, RemoteProc, etc.) -->
│       └── Common
│           └── FaultMgr                      <!-- Optional fault manager helpers -->
├── ResourcesManager
└── Template_StarterApp_M33TD_CM33_trusted-firmware-m
    <!-- Secure TF‑M CMake project (builds TF‑M binaries used by this NS application) -->

A migrated example typically moves its core logic (previously running in a standalone CM33 project or as a remoteproc firmware in the A35-TD flavor context) into the body of CustomTask_Thread() and any helper functions, adapted to:

  • Use only peripherals and memory regions available to CM33‑NS (or peripherals reassigned to CM33‑NS via RIF configuration).
  • Access secure functionality through TF‑M services instead of any direct secure‑state access used previously.

5.2.1. Priority and behavior guidelines for custom tasks[edit | edit source]

Custom tasks added on top of the NS Application Manager can use higher, equal or lower priority than NSAppCore tasks, depending on the application requirements. However, when the goal is to achieve the full M33-TD flavor ecosystem boot (CM33 + TF‑M + Cortex‑A35 with Linux as high‑performance remote processor), NSAppCore tasks must remain responsive.

Warning

In particular, the SCMI manager task and the remote processor task must be able to handle TF‑M notifications and SCMI messages during the Cortex‑A35/Linux boot sequence and at run time. A custom task, even if placed at a higher priority, must not run in a way that starves these system tasks (for example, tight busy loops without blocking or yielding).

When choosing the task attributes (such as CUSTOM_TASK_PRIORITY) and designing the task loop:

  • It is acceptable to use higher, equal or lower priority than NSAppCore tasks if required by your use case.
  • The custom task must regularly block or yield (for example, by waiting on events, queues or using osDelay()), so that SCMI and other system tasks can be scheduled when needed.

5.2.2. Optional: running CM33-only (REMOTE_PROC_AUTO_START=0)[edit | edit source]

In some scenarios, the intention is to run the CM33 nonsecure application without bringing up the Cortex‑A35/Linux side (for example, for standalone CM33 testing in the M33-TD flavor environment).

Information

If you do not want to start the Cortex‑A35/Linux side, you can prevent the A35 from starting automatically by setting the REMOTE_PROC_AUTO_START option to 0 (for example, via a CMake option or a project preprocessor define). In that case, SCMI timing constraints related to Linux boot are relaxed, but NSAppCore tasks (watchdog monitor, logger, etc.) should still be kept responsive for correct system behavior.

6. References[edit | edit source]

  1. For STM32MP215F-DK refer StarterApp_M33TD
  2. For STM32MP257F-EV1 refer StarterApp_M33TD
  3. For STM32MP215F-DK Refer Template_StarterApp_M33TD
  4. For STM32MP215F-DK refer TestApp_M33TD
  5. For STM32MP215F-DK refer StarterApp_M33TD/stm32mp2xx_DDR_m33_ns.ld
  6. For STM32MP257F-EV1 refer StarterApp_M33TD/stm32mp2xx_DDR_m33_ns.ld
  7. Refer Trusted Firmware-M documentation
  8. For STM32MP215F-DK refer StarterApp_M33TD/README.md
  9. For STM32MP257F-EV1 refer StarterApp_M33TD/README.md