Cortex®-M4 development

Coprocessor Firmware Development

STM provides the STM32MP1 Developer Package to develop on Arm® Cortex®-M4 side.

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

Warning

The following contents does only work with our latest Gatesgarth release. Older mainline based BSPs like Zeus will fail as the RPMsg framework is not fully implemented in these kernel sources. M4 development does also work with the OpenSTLinux BSP.

OpenStLinuxSetup for Ka-Ro SOMs

How to setup the OpenSTLinux framework for our board is desribed in the document:

Coprocessor Management Overview

  • The STM32 MPU multiprocessor system allows to run independent firmwares on each CPU core.
  • Basicly, on the Cortex®-A7 core a Linux OS is running.
  • In Production boot mode, the Linux OS is loading the firmware on the Cortex®-M4 core and controls it (start/stop). Therefore, the Linux OS integrates the RemoteProc framework.
  • In Engineering boot mode, the firmware on the Cortex®-M4 core is already loaded and started by the bootloader.
  • Inter-processor communication of the two cores is based on RPMsg framework and Mailbox mechanisms.
  • For communication between the LinuxOs and the Cortex®-M4 software, virtual UARTs are implemented by the RPMsg framework.

How to boot the Cortex® Coprocessor

The STM32MP1 can be run in 2 differents boot modes:

1) Production boot mode (default mode):

  • Firmware is loaded into the coprocessor by the Cortex®-A7 processor
  • System ressources (clocks, regulators, and so on) are managed directly by Linux
  • the Cortex®-M4 firmware is provided/downloaded in the Linux file system
  • the pre-built firmware is launched on the coprocessor through the Linux Remote Proc framework
  • the firmware on the Cortex®-M4 is started/stopped by the Linux running on the Cortex®-A7.
  • the Cortex®-M4 software can also be loaded by the u-boot.

2) Engineering boot mode:

  • this mode is used specifically for firmware testing directly on the coprocessor
  • all ressources are managed directly in the example source code (clocks, regulators, and so on)
  • the firmware can be loaded directly from your favorite IDE (JTAG debugger is needed)

important

Engineering bootmode cannot be setup by jumpering on our modules. The module provides only 1 bootmode pin that can select between boot from USB or boot from emmc. The STM32MP1 processor provides 3 bootmode pins to distinguish between different bootmodes. Two of these bootmode pins are fixed by resistors. To setup engineering boot mode for our modules one of the resistors must be changed by soldering. Please ask our support for more information.

for more informations on using the different boot modes, please read: STM32CubeMP1 development guidelines.

How to configure system resources

  • the GPIO and EXTI configurations are protected from concurrent accesses by hardware semaphores from HSEM.
  • the Cortex®-M4 cannot configure clock and regulator system resources
  • the resource manager (Linux) configures the clocks and the regulators before the Cortex®-M4 starts.
  • at runtime, the Cortex®-M4 STM32Cube application can ask the resource manager to update the clock and regulator configurations
  • in addition to the peripheral configuration, the Cortex®-M4 still has to enable/disable the pheripheral clock.

for further informations, please read the document: How to configure system resources.

Resource manager for coprocessing

The configuration of the system resources for the Cortex®-M is done in the m4_system_resources node of the Linux kernel device tree.

The rproc_srm driver parses this node to configure these resources.

Inside that node, the resources of each device controlled by the coprocessor must be described in a sub-node with the following template:

m4_system_resources {
        compatible = "rproc-srm-core";
        status = "okay";

        /* System resources for peripheral A */
        <m4_aliasA>: <deviceA>@<addressA> {
                compatible = "rproc-srm-dev";
                reg = <...>;
                clocks = <...>;
                clock-names = "...";
                x-supply = <...>;
                status = "okay";
        };

        /* System resources for peripheral B */
        <m4_aliasB>: <deviceB>@<addressB> {
                compatible = "rproc-srm-dev";
                reg = <...>;
                clocks = <...>;
                clock-names = "...";
                x-supply = <...>;
                status = "okay";
        };

};

Please note, that most part of the m4_system_resources node and sub-nodes is already defined (with a ‘disabled’ status) in the ST delivered device tree.

You will find these system resources defined in the file stm32mp15-m4-srm.dtsi.

To declare a resource for the Cortex®-M4, enable the appropriate device in m4_system_resources and disable the device for the Linux use.

example:

Using the QSMP Evalkit, that is utilising the QSMP-1570 module, we want to use the USART2 device by the Cortex®-M4.

As Device Tree is a (Tree) structure, where the leafs set the values, you can overwrite definitions - included by lower dts/dtsi-files - in your local projects’s dts-file.

first, to be sure that the resource manager is enabled:

&m4_rproc {
        m4_system_resources {
                status = "okay";
        };
};

The USART2 device is enabled in the Linux device tree inside the file stm32mp157-qsmp-1570.dts.

so we can disable it with:

&usart2 {
        status = "disable"
};

The m4_usart2 resource is already defined inside the file stm32mp15-m4-srm.dtsi, with status disabled.

So we enable the resource with the following definitions:

&m4_usart2{
        pinctrl-names = "default";
        pinctrl-0 = <&m4_usart2_pins_mx>;
        status = "okay";
};

&pinctrl {
        m4_usart2_pins_mx: m4_usart2_mx-0 {
                pins {
                        pinmux =  <STM32_PINMUX('D', 5, RSVD)>, /* USART2_TX */
                                  <STM32_PINMUX('D', 6, RSVD)>; /* USART2_RX */
                };
        };
};

for further informations, please read the document: Resource manager for coprocessing.

Kernel Configurations needed

To use the RemoteProc and the RPMsg frameworks, be sure that they are enabled in your Linux kernel configuration using the Linux Menuconfig tool:

Device drivers  --->
    -*- Mailbox Hardware Support  --->
    <*> STM32 IPCC Mailbox
Device Drivers  --->
    Remoteproc drivers  --->
        <*> Support for Remote Processor subsystem
            -*-   Remoteproc System Resource Manager core
            -*-     Remoteproc System Resource Manager device
            <*>   STM32 remoteproc support
Device Drivers  --->
    Rpmsg drivers  --->
        <*> Virtio RPMSG driver
        <*> RPMSG tty driver

Device Tree Modifications needed

Some features must be configured in the Linux device tree:

  • reserved memory buffers, used by the RemoteProc framework
  • the Cortex®-M4
  • the mailbox registers
reserved-memory {
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;

        mcuram2:mcuram2@10000000{
                compatible = "shared-dma-pool";
                reg = <0x10000000 0x40000>;
                no-map;
        };

        vdev0vring0:vdev0vring0@10040000{
                compatible = "shared-dma-pool";
                reg = <0x10040000 0x1000>;
                no-map;
        };

        vdev0vring1:vdev0vring1@10041000{
                compatible = "shared-dma-pool";
                reg = <0x10041000 0x1000>;
                no-map;
        };

        vdev0buffer:vdev0buffer@10042000{
                compatible = "shared-dma-pool";
                reg = <0x10042000 0x4000>;
                no-map;
        };

        mcuram:mcuram@30000000{
                compatible = "shared-dma-pool";
                reg = <0x30000000 0x40000>;
                no-map;
        };

        retram:retram@38000000{
                compatible = "shared-dma-pool";
                reg = <0x38000000 0x10000>;
                no-map;
        };

        gpu_reserved: gpu@d4000000 {
                reg = <0xd4000000 0x4000000>;
                no-map;
        };
};
&m4_rproc {
        memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>,
                <&vdev0vring1>, <&vdev0buffer>;
        mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>;
        mbox-names = "vq0", "vq1", "shutdown";
        interrupt-parent = <&exti>;
        interrupts = <68 1>;
        interrupt-names = "wdg";
        wakeup-source;
        recovery;
        status = "okay";
};
&ipcc {
        status = "okay";
};

How to Control the Coprocessor from Linux

Basicly the Linux framework expects the firmware for the Cortex®-M4 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

How to start the Coprocessor from the bootloader

The Cortex®-M4 firmware can already be loaded and started by the u-boot, before the Linux OS is started. Therefore, the u-boot provides the rproc command to init and start the coprocessors. To list all coprocessors available do the following from the u-boot prompt:

     rproc init
     rproc list
0 - Name:'m4@10000000' type:'internal memory mapped' supports: load start stop reset is_running

Please note, attention must be payed to the implementation of the Arm Cortex®-M4 firmware if the RPMsg is used to communicate with Linux afterwards. In this case a synchronization is required. The Arm Cortex®-M4 core has to wait until Linux is booted to start RPMsg communications.

for detailed information, please read: How to start the coprocessor from the bootloader.