| This article is only applicable to M33-TD flavor |
1. Introduction[edit | edit source]
The Cortex-M33-TD software ecosystem for STM32MP2 series platforms is designed to provide a secure, flexible, and robust foundation for embedded system bring-up.
In this architecture, the Cortex-M33 processor is responsible for early system initialization and management, working in tandem with the Cortex-A35 processor. The software stack includes:
- MCUboot for secure boot and firmware updates,
- Trusted Firmware-M (TF-M)' [1] for secure services,
- STM32CubeMPU firmware as the nonsecure application manager built on FreeRTOS.
Within this ecosystem, the STM3CubeMPU firmware —referred below as the StarterApp_M33TD— serves as the main nonsecure application manager which is essential for system operation: it schedules user and system tasks, manages remote processor control (such as starting and resetting the Cortex-A35), and interacts with secure services. While the full-featured StarterApp_M33TD demonstrates these capabilities on STM32 MPU boards, porting to a custom board is best approached with a focus on the essentials.
This article helps you port the StarterApp_M33TD to your custom hardware as a STM32CubeIDE project, focusing on a bare minimum application.
By concentrating on board-dependent features — UART logging, remote processor management, and a simple LED heartbeat — you can quickly validate your hardware and establish a solid foundation for further development. SoC-level startup and system files remain unchanged, allowing you to focus exclusively on the board support package (BSP) and minimal application logic.
2. Prerequisites[edit | edit source]
STM32CubeIDE must be installed.
3. StarterApp_M33TD overview[edit | edit source]
StarterApp_M33TD is a demonstration example delivered in the STM32CubeMP2 Package, acting as a nonsecure application manager.
It is designed to:
- Integrate with FreeRTOS as middleware.
- Manage system integration and scheduling.
- Provide a minimal set of tasks for system bring-up for M33-TD flavor
.
3.1. Minimal task setup for porting StarterApp_M33TD[edit | edit source]
Only the following FreeRTOS tasks are required for a functional StarterApp_M33TD:
- remoteproc_task: Handles lifecycle management of the high-performance Cortex-A35 coprocessor (SoC-dependent, board-agnostic for MP25xx).
- userapp_task: Simple heartbeat logic (LED toggle, board-dependent).
Other tasks (if present) can be commented out in app_freertos.c for the initial port.
4. StarterApp_M33TD flow overview[edit | edit source]
Below is the high-level flow from main.c to the FreeRTOS scheduler kickoff, with board-specific steps clearly marked and the minimal FreeRTOS tasks shown as branches from the scheduler.
main.c entry | v System/Clock Init | v [Board-Specific] LED Init | v [Board-Specific] UART Init | v Print System Info | v osKernelInitialize() | v MX_FREERTOS_Init() (Task creation) | v osKernelStart() | v FreeRTOS Scheduler | +---------------------+ | | v v remoteproc_task userapp_task
5. Step-by-step porting guide[edit | edit source]
5.1. 1. Prepare your custom board BSP[edit | edit source]
- Ensure your custom board has a BSP (Board Support Package) with:
- LED initialization and control (for
userapp_task) - UART initialization (required for system-level
printfoutput and for any application task that needs to print to the terminal)
- LED initialization and control (for
5.2. 2. Copy StarterApp_M33TD project[edit | edit source]
- Copy the StarterApp_M33TD project for the reference board (e.g., STM32MP257F-EV1) into the target path.
- Import it into your STM32CubeIDE workspace as a new project new project for your custom board.
|
For more information on how to import StarterApp_M33TD project for custom board, Refer following article: How_to_import,_build_and_debug_STM32CubeMP2_StarterAppM33TD_demonstration_in_STM32CubeIDE |
5.3. 3. Update board-specific initialization[edit | edit source]
- In
main.c, update:BSP_LED_Init(LED3);andBSP_LED_Toggle(LED3);to use your board's LED.- Replace the default STM32 MPU board UART initialization logic with the appropriate UART initialization for your custom board.
- This may involve:
- Requesting a different UART resource (e.g.,
RESMGR_RIFSC_UARTx_IDfor your chosen UART instance), - Calling your custom board’s BSP UART initialization API,
- Or directly configuring the UART using HAL functions in
main.c.
- Requesting a different UART resource (e.g.,
- In
stm32mp2xx_hal_msp.c, update:- GPIO and peripheral clock enables to match your board's pinout and hardware resources.
- Any resource manager requests for GPIOs, clocks, or peripherals.
5.4. 4. Minimal task configuration in app_freertos.c[edit | edit source]
- In
MX_FREERTOS_Init(), keep only the following tasks:
RemoteProcTask_Init(); UserAppTask_Init(); // Comment out other tasks for a bare minimum port
- Comment out or remove other task initializations.
5.5. 5. Porting each task[edit | edit source]
- remoteproc_task
- Purpose: Manages lifecycle (start/stop/crash) of the Cortex-A35 processor.
- Porting:
- The task logic is board-agnostic and does not require changes for custom boards based on STM32MP25x lines
. - EXTI, GPIO, and NVIC initialization for remote processor management is SoC-dependent and already correct for all STM32MP25x lines
-based boards. - No changes are needed in
remoteproc_task.cfor custom board porting.
- The task logic is board-agnostic and does not require changes for custom boards based on STM32MP25x lines
- userapp_task
- Purpose: Simple heartbeat (LED toggle).
- Porting:
- Update
BSP_LED_Toggle(LED3);to use your board's LED. - If your board uses a different LED or GPIO, update the macro or function accordingly.
- Update
5.6. 6. Build and test[edit | edit source]
- Build the project in STM32CubeIDE for your custom board.
- Flash the firmware and observe:
- UART logs (system-level messages and any output from application tasks)
- LED heartbeat (from
userapp_task) - Remote processor management (from
remoteproc_task)
|
For more information on how to build and debug StarterApp_M33TD[2] project, Refer following article: How_to_import,_build_and_debug_STM32CubeMP2_StarterAppM33TD_demonstration_in_STM32CubeIDE |
6. Minimal project structure (after porting)[edit | edit source]
Below is the recommended minimal project structure for a clean custom board port of the StarterApp_M33TD Demo application in STM32CubeIDE:
StarterApp_M33TD_CM33_NonSecure ├── Application │ ├── Startup │ │ └── startup_stm32mp257ccx_m33.s <-- Startup file (unchanged for MP25xx SoC) │ └── User │ ├── Core │ │ └── Src │ │ ├── main.c │ │ ├── stm32mp2xx_hal_msp.c │ │ ├── stm32mp2xx_hal_timebase_tim.c │ │ └── stm32mp2xx_it.c │ └── FREERTOS │ └── App │ ├── app_freertos.c │ ├── remoteproc_task.c │ └── userapp_task.c ├── 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 ├── Drivers │ ├── BSP │ │ └── (Custom board BSP files only) │ └── CMSIS │ ├── system_stm32mp2xx_m33_ns.c <-- System file (unchanged for MP25xx SoC) │ └── STM32MP2xx_HAL_Driver ├── Middlewares │ └── FreeRTOS ├── Utilities └── (Trusted Firmware-M as submodule or reference)
Note:
- The startup file (
startup_stm32mp257ccx_m33.s) and system file (system_stm32mp2xx_m33_ns.c) are SoC-dependent and should remain unchanged for all custom boards based on the STM32MP25x lines
. - Only the BSP (Board Support Package) and application logic need to be adapted for your custom hardware.
7. Project cleanup[edit | edit source]
After porting, perform the following cleanup steps in your STM32CubeIDE project to ensure a minimal and maintainable project:
- Remove unnecessary task files:
Delete source/header files for tasks not required in the minimal application.
- Clean up
app_freertos.c:
Remove or comment out initialization calls for unused tasks.
- Clean up
app_tasks_config.h:
This header defines stack sizes, priorities, and configuration macros for all tasks. - Remove or comment out configuration macros for tasks that are not part of the minimal application. - Ensure only the macros forremoteproc_task, anduserapp_taskremain. - Example (after cleanup):
#define REMOTEPROC_TASK_STACK_SIZE 1024 #define REMOTEPROC_TASK_PRIORITY osPriorityNormal #define USERAPP_TASK_STACK_SIZE 512 #define USERAPP_TASK_PRIORITY osPriorityBelowNormal
- Remove evaluation board BSP files:
If you are not using the STM32MP257x-EV1 Evaluation boardBSP, delete its files and add your custom board’s BSP.
- Update build/project files:
Remove references to deleted files from Makefiles, CMakeLists.txt, or project configuration files.
- Check includes and dependencies:
Ensure only the necessary includes and dependencies remain for the minimal application.
- Review application logic:
Remove any code, function calls, or references to tasks and features that are not part of the minimal port, ensuring a clean and maintainable codebase.
8. Code Section References[edit | edit source]
Below are code snippets and sections you may need to adapt:
8.1. main.c: Board UART initialization example[edit | edit source]
Default (Evaluation board) Example:
if(ResMgr_Request(RESMGR_RESOURCE_RIFSC, RESMGR_RIFSC_UART5_ID) == RESMGR_STATUS_ACCESS_OK) { COM_Init.BaudRate = 115200; COM_Init.WordLength = UART_WORDLENGTH_8B; COM_Init.StopBits = UART_STOPBITS_1; COM_Init.Parity = UART_PARITY_NONE; COM_Init.HwFlowCtl = UART_HWCONTROL_NONE; /* Initialize and select COM1 which is the COM port associated with current Core */ BSP_COM_Init(COM_VCP_CM33, &COM_Init); BSP_COM_SelectLogPort(COM_VCP_CM33); }
For a custom board:
Replace the above initialization logic with the appropriate UART initialization for your hardware.
This may involve:
- Requesting a different UART resource (e.g.,
RESMGR_RIFSC_UARTx_IDfor your chosen UART instance), - Calling your custom board’s BSP UART initialization API,
- Or directly configuring the UART using HAL functions in
main.c.
Examples:
// Using a different UART instance if(ResMgr_Request(RESMGR_RESOURCE_RIFSC, RESMGR_RIFSC_UART3_ID) == RESMGR_STATUS_ACCESS_OK) { // Or using a custom BSP API CustomBoard_UART_Init(&COM_Init); CustomBoard_SelectLogPort(); // Or direct HAL initialization MX_USARTx_UART_Init(); // Your own initialization function }
8.2. App_freertos.c: minimal task initialization[edit | edit source]
void MX_FREERTOS_Init(void) {
RemoteProcTask_Init();
UserAppTask_Init();
// Comment out other tasks for bare minimum port
}
8.3. Userapp_task.c: heartbeat task[edit | edit source]
static void UserAppTask(void *argument)
{
for (;;) {
BSP_LED_Toggle(LED3); // Update LED3 as per your board
osDelay(1000);
}
}
9. Troubleshooting[edit | edit source]
- UART not working: Check pin mapping and initialization in both BSP and
main.c. - LED not toggling: Verify correct GPIO and LED macros for your board.
- remote processor not managed: Ensure EXTI and GPIO resources are correctly configured (for STM32MP25x lines
, the reference implementation is already correct).
10. Extending the application[edit | edit source]
Once the minimal port is functional, you can incrementally enable and port additional tasks as needed for your application.
11. References[edit | edit source]
- ↑ Refer trusted-firmware-m
- ↑ For STM32MP257F-EV1 refer StarterApp_M33TD