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 Kirkstone release, or newer. In older mainline based BSPs, like Hardknott or Gatesgarth, the device tree files and kernel configurations do not support the Linux RPMsg framework.

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. For detailed information about using engineering boot mode, please see Engineering Boot Mode Details

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.

Please note

The following kernel features are enabled by default in the Kirkstone release, or newer. In older mainline based BSPs, like Hardknott or Gatesgarth, this has to be done by the cutomer.

using the Linux Menuconfig tool:

Device drivers  --->
   -*- Mailbox Hardware Support  --->
   <*> STM32 IPCC Mailbox
Device drivers  --->
   Remoteproc drivers  --->
      <*> Support for Remote Processor subsystem
      <*> STM32 remoteproc support
Device Drivers  --->
   Character devices  --->
      <*> RPMSG tty driver

Device Tree Modifications needed

Please note

With the Kirkstone release, or newer, the U-Boot provides an FDT Overlay (karo-copro) that installs the following device tree settings.

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 install the FDT overlay for copro support

From Yocto release 4.0 (kirkstone) onwards, the process of automatically changing the fdt_file variable according to the baseboard setting is being abandoned in favour of FDT overlays. To support the coprocessor features in the device tree, the U-Boot provides the fdt overlay karo-copro.

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 qsbase1
setenv overlays_qsbase1 'setenv overlays karo-copro qsmp-qsbase1 qsmp-ksz9031'
saveenv

How to use firmware sample projects of the STM32CubeMP1 package from ST

The STM32CubeMP1 package from ST provides various firmware sample projects for the Cortex®-M4 coprocessor. Most of these samples run without modifications on our eval-kits. From Yocto release 4.0 (kirkstone) onwards, we provide a Distro Features to build these samples and and move the binaries to the userfs.

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

DISTRO_FEATURES:append = " copro"

In Linux, mount the userfs:

mount /usr/local/

You will find the sample projects in: /usr/local/Cube-M4-examples/STM32MP157C-DK2/

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

If you want to evaluate one of the predefined samples provided under /usr/local/Cube-M4-examples/STM32MP157C-DK2/ by the Distro Feature copro, you can setup the firmware path in the following way for the OpenAMP_TTY_echo sample:

echo -n /usr/local/Cube-M4-examples/STM32MP157C-DK2/Applications/OpenAMP/OpenAMP_TTY_echo/lib/firmware/ > /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.