Cortex®-M4 development

Coprocessor Firmware Development

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

For using this software, read the STM documentation provided here.

Warning

The following contents were only tested with Yocto Thud, Zeus is not tested yet.

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)
  • Engineering boot mode is setup by boot mode jumpering

for more informations on using the different boot modes, please look here.

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 here.

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 stm32mp157c-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 stm32mp157c-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 here.

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;

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

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

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

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

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

        vdev0buffer: vdev0buffer@10044000 {
                compatible = "shared-dma-pool";
                reg = <0x10044000 0x4000>;
                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. 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 here.