Cortex®-M33 development

Coprocessor Firmware Development

STM provides the STM32MP2 Developer Package to develop on Arm® Cortex®-M33 side.

Starting up with development on Arm® Cortex®-M33 read the STM documentation: Develop on Arm® Cortex®-M33.

STM32MP2 boot flavor

The STM32MP2 Cortex-M33 boot mode is configured via BOOT pins. , allowing it to act as the primary boot processor (Trusted Domain) from sources like SD-Card/eMMC, or to be started later by the Cortex-A35 (e.g., via Linux/remoteproc), depending on the chosen boot flavor and pin settings.

Differences Between A35-TD Flavor and M33-TD Flavor Boot Chains

STM32MP2 supports two possible Trusted Domain (TD) configurations, defining which processor acts as the first trusted core after the ROM code. These configurations affect how the secure boot chain progresses and where trust anchors are placed.

important

The actual BSP supports only the A35-TD Flavor Boot Chain at the moment.

A35-TD Flavor Boot Chain

Cortex-A35 is booting first. Cortex-M33 is kept under reset by hardware until application request to start it. The Trusted Domain continues on the CA35. After the immutable ROM boot (in the Manufacturer Trusted Domain), the secure boot chain flows directly toward the Cortex-A35.

Boot Sequence:

  1. ROM Code

    • Authenticates and loads next stage, Trusted Firmware-A (TF-A) used as the FSBL

  2. Trusted early boot on CA35

    • In TF-A BL31 - CA35 enters secure mode (EL3)

    • Loads secure monitor, trusted firmware, security services

  3. CA35 launches non-secure OS (Linux)

Result:

  • CA35 is the anchor for the Owner Trusted Domain

  • Secure services executed by the A35 secure monitor (OP-TEE)

  • CM33 is brought up after CA35 and typically runs non-trusted firmware unless OEM places additional constraints.

M33-TD Flavor Boot Chain

The Trusted Domain continues on the CM33. This configuration gives the CM33 ownership of early secure boot and secure services.

Boot Sequence:

  1. ROM Code

    • Authenticates first CM33 firmware image

  2. CM33 secure boot execution

    • CM33 runs the trusted firmware stack

    • CM33 configures security boundaries (firewalls, SAU/IDAU, memory splits)

    • CM33 may host a TEE-like secure environment

  3. CM33 releases CA35

    • CA35 boots into Linux or other OS in non-secure domain

Result:

  • CM33 is the anchor of the Owner Trusted Domain

  • CM33 controls access to security-critical peripherals

  • CA35 is always subordinate to CM33’s security configuration

How to prepare your Linux image for Cortex®-M33 Coprocessor support

To support the Cortex®-M33 coprocessor, a number of kernel features must be installed that are not available in the standard image. This is accomplished in Yocto by using a special distro feature.

To add this Distro Feature, open your local.conf and add the following line:

DISTRO_FEATURES:append = " copro"

How to install the FDT overlay for Coprocessor support

Additional device tree features must be integrated via a special device tree overlay for the coprozessor. For more information about FDT overlays, please see FDT Overlays

To install the overlay, a baseboard variable must be set in the U-Boot environment, and the overlay name must be added to the appropriate overlays_${baseboard} variable, e.g.:

setenv baseboard <baseboard>
setenv overlays_<baseboard> ${overlays_<baseboard>} karo-copro
saveenv

Deploying the firmware to the target

To start the firmware, we have to deploy it first to the target’s memory. That could be basicly, the internal emmc device of the SOM or the SD-card of the base board. The following example shows, how to deploy the firmware to the internal emmc device.

After building the yocto Linux and programming it with the uuu-tool to the target, we can examine the programmed partitions inside U-Boot:

part list mmc 0
Partition Map for MMC device 0  --   Partition Type: EFI
Part    Start LBA       End LBA         Name
        Attributes
        Type GUID
        Partition GUID
  1     0x00000800      0x000017ff      "fip"
        attrs:  0x0000000000000000
        type:   19d5df83-11b0-457b-be2c-7559c13142a5
                (19d5df83-11b0-457b-be2c-7559c13142a5)
        guid:   aff42d55-134f-449c-b892-92bf1a6f7955
  2     0x00001800      0x000217ff      "boot"
        attrs:  0x0000000000000000
        type:   bc13c2ff-59e6-4262-a352-b275fd6f7172
                (bc13c2ff-59e6-4262-a352-b275fd6f7172)
        guid:   36d1f7ae-9e50-46ce-accf-57989189f556
  3     0x00021800      0x000617ff      "rootfs"
        attrs:  0x0000000000000000
        type:   b921b045-1df0-41c3-af44-4c6f280d3fae
                (b921b045-1df0-41c3-af44-4c6f280d3fae)
        guid:   a0b81ad7-47ec-4181-8b1f-733702fdd8c6
  4     0x00061800      0x00747bff      "userfs"
        attrs:  0x0000000000000000
        type:   b0e01050-ee5f-4390-949a-9101b17104e9
                (b0e01050-ee5f-4390-949a-9101b17104e9)
        guid:   cd07e31f-4090-499c-a02b-7966aa57b421

The “boot”-partition contains the Linux- image and device trees. To store the firmware binary into that partition we use the USB Mass Storage U-Boot function to mount that partition to our Linux host PC:

ums 0 mmc 0:2

Mount the mass storage device on your host machine and copy the firmware .elf-file to the mounted boot-partition.

Stop the ums-device with CTRL + C in U-Boot.

List the contents of the boot-partition from U-Boot to check it:

ls mmc 0:2
16289800 Image
    1302 stm32mp25-karo-copro.dtb
     432 stm32mp25-karo-gpu.dtb
     531 stm32mp25-karo-rtc.dtb
    1075 stm32mp25-txmp-fdcan1.dtb
    1075 stm32mp25-txmp-fdcan2.dtb
     911 stm32mp25-txmp-ft5x06.dtb
    1144 stm32mp25-txmp-keypad.dtb
    7138 stm32mp25-txmp-lcd-panel.dtb
     903 stm32mp25-txmp-mb7-wakeup-btn.dtb
    1244 stm32mp25-txmp-mb7.dtb
     432 stm32mp25-txmp-sdcard1-cd.dtb
     432 stm32mp25-txmp-sdcard2-cd.dtb
    4314 stm32mp25-txmp-sound.dtb
     625 stm32mp25-txmp-spidev.dtb
   97656 stm32mp257f-txmp-2550.dtb
 3412056 OpenAMP_TTY_echo_CM33_NonSecure.elf

Create a firmware folder named /lib/firmware inside your rootfs if it does not already exist.

Copy the firmware image OpenAMP_TTY_echo_CM33_NonSecure.elf into the firmware folder

mkdir /lib/firmware
cp /media/OpenAMP_TTY_echo_CM33_NonSecure.elf /lib/firmware/

How to Control the Coprocessor from Linux

Basicly the Linux framework expects the firmware for the Cortex®-M334 coprocessor stored in the file system, by default in the /lib/firmware/ folder. Optionally another location can be set. In this case the remoteproc framework parses this new path in priority.

Below the command for adding a new path for firmware parsing:

echo -n <firmware_path> > /sys/module/firmware_class/parameters/path

To load the firmware into the coprocessor by the remoteproc framework, use this command:

echo -n <firmware_name.elf> > /sys/class/remoteproc/remoteproc0/firmware

Start the firmware with this comand:

echo start >/sys/class/remoteproc/remoteproc0/state

This stops the remote processor:

echo stop >/sys/class/remoteproc/remoteproc0/state

For debugging the remote processor you can get debug messages via the remoteproc framework:

cat /sys/kernel/debug/remoteproc/remoteproc0/trace0

dynamic debugging

In case of problems, you can enable dynamic debugging to obtain valuable information.

echo -n 'file stm32-ipcc.c +p' > /sys/kernel/debug/dynamic_debug/control
echo -n 'file stm32_rproc.c +p' > /sys/kernel/debug/dynamic_debug/control
echo -n 'file remoteproc*.c +p' > /sys/kernel/debug/dynamic_debug/control
echo -n 'file virtio_rpmsg_bus.c +p' > /sys/kernel/debug/dynamic_debug/control
echo -n 'file virtio_ring.c +p' > /sys/kernel/debug/dynamic_debug/control