1. Article purpose[edit source]
This article aims to specify how to use LTDC 3rd Layer, controlled by Arm®-Cortex® M33 while displaying standard HMI on OpenSTLinux running on Arm®-Cortex® A35, using STM32Cube MPU firmware example.
This article also explains how to configure LTDC 3rd layer (Resolution, Window sizing, Opacity etc.) and how to make changes in OP-TEE RIF settings from External device tree so that LTDC 3rd Layer can be controlled via Arm®-Cortex® M33.
2. Prerequisites[edit source]
To run the STM32Cube Example to demonstrate the LTDC 3rd layer controlled by CM33 while displaying Standard HMI on OpenSTLinux running on Arm®-Cortex® A35, required hardware and software stacks are listed below:
- The STM32MP257x-EV1 Evaluation board
(including the default LVDS display Panel)
- Refer to the Installing the STM32CubeMP2 Package to obtain and install the source code
- Refer to the new recommended IDE: STM32CubeIDE
3. LTDC 3rd Layer example description[edit source]
The goal of this example is to demonstrate Arm®-Cortex® M33 controlled 3rd Layer non-protected while displaying standard HMI on OpenSTLinux running on Arm®-Cortex® A35.
This example displays a splash screen logo and a message during 20 seconds. It can be adapted for various use cases like displaying parameters of a running process controlled by the Arm®-Cortex® M33: motor speed, camera status, detected events, visual watch dog...
![]() |
You can browse this example source code in <CubePackage>/Projects/STM32MP257F-EV1/Examples/LTDC |
3.1. Steps to configure the 3rd Layer of LTDC[edit source]
- Read back LTDC "common registers" to determine Panel information (height and width). Note that the display panel and the LTDC internal peripheral have already been initialized by OpenSTLinux running on Arm®-Cortex® A35
- Configure the LTDC 3rd Layer with "no Reload trigger"
- Window Sizing: Full Screen and Partial Screen Mode, controlled by "FULLSCREEN" Preprocessor
- Opacity: controlled by "constA", set in such a way OpenSTLinux HMI will be visible
- Input Pixel Format: RGB565 in this example
- Set Immediate reload type when LTDC updates are required
![]() |
Refer to the LTDC internal peripheral article for more details. |
3.2. LTDC 3rd layer display content[edit source]
- Splash screen will be displayed with content (Example description, and ST logo)
- Splash screen will disappear after 20 second timeout (SUCCESS)
3.3. Operating mode[edit source]
After the LCD initialization, the LCD layer 3 is configured as following:
- FULLSCREEN Mode (with "FULLSCREEN" Preprocessor): layer 3 is configured to display a framebuffer content read from the DDR memory with direct color (RGB565) as pixel format and 1024x600 as resolution (same resolution as the panel).
- Partial Screen Mode (with no "FULLSCREEN" Preprocessor): Layer 3 is configured to display a framebuffer content read from the DDR memory with direct color (RGB565) as pixel format and 720x480 as resolution (smaller resolution than the panel.
3.4. Display composition[edit source]
The LTDC internal peripheral supports 3 layers of display composition, where blending order and blending factor of each layer with other can be configured. The LTDC common registers, Layer 1 and Layer 2 configuration is being controlled by CA35 whereas to demonstrate the LTDC 3rd Layer, Layer 3 resource is allocated to Arm®-Cortex® M33.
4. How to configure RIF to use LTDC 3rd layer in a non-secure context from Arm-Cortex M33[edit source]
The "ltdc_m33_layer" region of 4M bytes size has been used for the framebuffer (fb_address: 0x81300000 of 4MB).
To be able to write via Arm®-Cortex® M33 and read via LTDC AXI DMA engine in NSEC state to this framebuffer region, CID2 and CID4 are listed into read and write list of RISAF region 12.
The LTDC_L2_ID resource under RIFSC has been statically allocated to the Arm-Cortex M33 (CID2) and set to non-secure access (NSEC).
- Refer below changes in the OP-TEE External device tree (Note that these changes are maybe already present in your external device tree files):
<EXTERNAL DT>/optee/stm32mp257f-ev1-ca35tdcid-ostl-m33-examples-rif.dtsi
&rifsc {
st,protreg = <
.
.
.
RIFPROT(STM32MP25_RIFSC_LTDC_L0L1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
- RIFPROT(STM32MP25_RIFSC_LTDC_L2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+ RIFPROT(STM32MP25_RIFSC_LTDC_L2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
RIFPROT(STM32MP25_RIFSC_LTDC_ROT_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
.
.
.
>;
};
&rifsc {
st,rimu = <
.
.
RIMUPROT(RIMU_ID(9), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
RIMUPROT(RIMU_ID(10), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
RIMUPROT(RIMU_ID(11), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M)
- RIMUPROT(RIMU_ID(12), RIF_CID4, RIF_SEC, RIF_PRIV, RIF_CIDSEL_M)
+ RIMUPROT(RIMU_ID(12), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M)
RIMUPROT(RIMU_ID(13), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M)
RIMUPROT(RIMU_ID(14), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
RIMUPROT(RIMU_ID(15), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
.
.
>;
};
<dc_m33_layer {
st,protreg = <RISAFPROT(RISAF_REG_ID(12), RIF_CID2_BF|RIF_CID4_BF, RIF_CID2_BF|RIF_CID4_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
};
&risaf4 {
- memory-region= <&tfm_code>, <&cm33_cube_fw>, <&tfm_data>, <&cm33_cube_data>, <&ipc_shmem>, <&spare1>, <&bl31_context>, <&op_tee>, <&linuxkernel1>, <&gpu_reserved>, <<dc_sec_layer>, <<dc_sec_rotation>, <&linuxkernel2>;
+ memory-region= <&tfm_code>, <&cm33_cube_fw>, <&tfm_data>, <&cm33_cube_data>, <&ipc_shmem>, <&spare1>, <&bl31_context>, <&op_tee>, <&linuxkernel1>, <&gpu_reserved>, <<dc_m33_layer>, <<dc_sec_layer>, <<dc_sec_rotation>, <&linuxkernel2>;
};
<EXTERNAL DT>/optee/stm32mp257f-ev1-ca35tdcid-ostl-m33-examples-resmem.dtsi
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
.
.
- spare1: spare1@81300000 {
- reg = <0x0 0x81300000 0x0 0xcc0000>;
- no-map;
- };
+ spare1: spare1@81700000 {
+ reg = <0x0 0x81700000 0x0 0x8c0000>;
+ no-map;
+ };
.
.
+ ltdc_m33_layer: ltdc-m33-layer@81300000 {
+ reg = <0x0 0x81300000 0x0 0x400000>;
+ no-map;
+ };
.
.
}
- Update the OP-TEE external dt refer: How to configure OP-TEE
- Compile OP-TEE Image using How to configure OP-TEE
- Copy existing FIP binary to <OPTEE>/out/arm-plat-stm32mp2/core (for example: optee_os/out/stm32mp257f-ev1-ca35tdcid-ostl-m33-examples/core
- Run following commands:
cd <OPTEE>/out/arm-plat-stm32mp2/core
- Run Command for micro SD card:
fiptool update fip-stm32mp257f-ev1-ca35tdcid-ostl-m33-examples-optee-sdcard.bin --tos-fw tee-header_v2.bin --tos-fw-extra1 tee-pager_v2.bin --tos-fw-extra2 tee-pageable_v2.bin
- Run Command for eMMC
fiptool update fip-stm32mp257f-ev1-ca35tdcid-ostl-m33-examples-optee-emmc.bin --tos-fw tee-header_v2.bin --tos-fw-extra1 tee-pager_v2.bin --tos-fw-extra2 tee-pageable_v2.bin
- Copy FIP binary into the target device inside the folder /home/root/
- Run command for micro SD card (where mmcblk0p5 - mmcblk<MMC_INSTANCE>p<FIP_IMAGE_PARTITION_NUM>):
dd if=fip-stm32mp257f-ev1-ca35tdcid-ostl-m33-examples-optee-sdcard.bin of=/dev/mmcblk0p5 conv=fdatasync
- Run command for eMMC (where mmcblk1p3 - mmcblk<MMC_INSTANCE>p<FIP_IMAGE_PARTITION_NUM>):
dd if=fip-stm32mp257f-ev1-ca35tdcid-ostl-m33-examples-optee-emmc.bin of=/dev/mmcblk1p3 conv=fdatasync
- Reboot the target device
- Run the example
5. How to run STM32Cube MPU example[edit source]
To run the example on STM32MP257x-EV1 Evaluation board , perform following steps:
- Open the project folder containing the example at following path <CubePackage>/Projects/STM32MP257F-EV1/Examples/LTDC and double-click on file .project to open the Eclipse STM32CubeIDE
![]() |
You can browse this example source code in <CubePackage>/Projects/STM32MP257F-EV1/Examples/LTDC |
.
- Build with the configuration CA35TDCID_m33_ns_sign
- Create the example firmware directory on the target and copy the example signed firmware and its related script with the commands:
ssh root@192.168.7.1 'mkdir -p /home/root/LTDC_Display_3rdLayer/lib/firmware' scp LTDC_Display_3rdLayer_CM33_NonSecure_sign.bin root@192.168.7.1:/home/root/LTDC_Display_3rdLayer/lib/firmware
- Go to CubePackage folder and run following command:
scp Utilities/scripts/fw_cortex_m33.sh root@192.168.7.1:/home/root/LTDC_Display_3rdLayer/
- To run the example on the target shell, run following commands:
cd /home/root/LTDC_Display_3rdLayer
./fw_cortex_m33.sh start