Last edited 2 days ago

How to use the Cortex-M0+

Applicable for STM32MP25x lines


1. Article purpose[edit | edit source]

This article describes the configuration of the Cortex®-M0+ and its related resources, and how to run a Cortex®-M0+ firmware through a low power demonstration application. Purpose of this application is to demonstrate a low power use case and a communication use case between the Cortex®-M0+ and Cortex®-A35.

Info white.png Information
The Cortex®-M0+ demonstration application is only applicable for STM32MP257x-EV1 Evaluation board More info green.png as it use the LPUART1 which is not available for STM32MP257x-DK Discovery kit More info green.png.

2. Introduction[edit | edit source]

The Cortex®-M0+ is used as a coprocessor with access to limited resources, peripherals and memories. The Cortex®-M0+ processor is dedicated to executing small tasks that require few resources. It runs in a separate SmartRun domain, allowing other domains to be turned off to achieve low levels of power consumption.

3. Resources access from Cortex®-M0+[edit | edit source]

3.1. Memories[edit | edit source]

The Cortex®-M0+ can only use the LPSRAM memories for a total of 32KB, with following memory mapping:

  • LPSRAM1 : 0x200C0000 - 0x200C1FFF (8KB)
  • LPSRAM2 : 0x200C2000 - 0x200C3FFF (8KB)
  • LPSRAM3 : 0x200C4000 - 0x200C7FFF (16KB)
Info white.png Information
In the STM32MPU Embedded Software distribution, the memory mapping of the LPSRAM must necessarily be defined between 0x200C0000 and 0x200C7FFF.

3.2. Peripherals[edit | edit source]

The Cortex®-M0+ can only access to a set of limited peripherals:

  • LPTIM3, LPTIM4, LPTIM5
  • SPI8
  • LPUART1
  • I2C8
  • ADF1C
  • GPIOZ
  • LPDMA
  • RTC
  • I3C4
  • IPCC2
  • EXTI2
  • HSEM

3.3. Other resources[edit | edit source]

The Cortex®-M0+ can also access to others resources as:

  • PWR
  • CoreSight Debug through 2 ports :
    • The SWD (Serial Wire Debug)
    • The SWJ-DP (Serial Wire JTAG-Debug Port)
Info white.png Information
The Cortex®-M0+ has no access to RCC resources (for clock configuration for example). It implies that the clock gating has to be managed by the Cortex®-A35 (Linux kernel or OP-TEE).

3.4. Security[edit | edit source]

All memories, peripherals and resources access rights are managed by the Resource Isolation Framework (RIF) in the Cortex®-A35.

3.4.1. Memories RIF configuration example[edit | edit source]

The RIF configuration of the LPSRAM memories have to allow the load of the M0+ firmware image by the Cortex®-A35 Linux kernel remoteproc framework and the execution of the firmware on the Cortex®-M0+.

In the following example, the LPSRAM 1/2/3 (respectively RISAL_ID 1/2/3) are configured as a shared memory (subregion A and subregion B) between the Cortex®-A35 (RID_CID1) and Cortex®-M0+ (RIF_CID3):

	st,risal = <
		RISALPROT(RISAL_ID(1), RIFSC_RISAL_BLOCK_A, RIF_CID1, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIFSC_RISAL_SREN)
		RISALPROT(RISAL_ID(2), RIFSC_RISAL_BLOCK_A, RIF_CID1, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIFSC_RISAL_SREN)
		RISALPROT(RISAL_ID(3), RIFSC_RISAL_BLOCK_A, RIF_CID1, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIFSC_RISAL_SREN)
		RISALPROT(RISAL_ID(1), RIFSC_RISAL_BLOCK_B, RIF_CID3, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIFSC_RISAL_SREN)
		RISALPROT(RISAL_ID(2), RIFSC_RISAL_BLOCK_B, RIF_CID3, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIFSC_RISAL_SREN)
		RISALPROT(RISAL_ID(3), RIFSC_RISAL_BLOCK_B, RIF_CID3, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIFSC_RISAL_SREN)
	>;

3.4.2. Peripherals RIF configuration example[edit | edit source]

The RIF access right are applied to the peripherals and their associated RCC registers. If the Cortex®-M0+ controls the peripheral, the Cortex®-A35 has to configure the associated RCC registers before starting the Cortex®-M0+. For this reason, the peripherals' RIF access rights have to be allowed for both the Cortex®-A35 and the Cortex®-M0+.

In the following example, the LPUART1 is configured without any filtering to allow access of the LPUART1 by the Cortex®-A35 and the Cortex®-M0+:

&rifsc {
	st,protreg = <
       ....
		RIFPROT(STM32MP25_RIFSC_LPUART1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
       ....
	>;
	st,glocked = <RIFSC_RIMU_GLOCK>;
};


3.5. Low power constraints[edit | edit source]

The Cortex®-M0+ can be used during low power modes, while Cortex®-A35 and Cortex®-M33 are stopped. A dedicated autonomous mode is available for each peripheral that can be allocated to Cortex®-M0+ in order to avoid from stopping peripherals clocks during Cortex®-A35 low power.

Info white.png Information
On ecosystem release v6.0.0 More info.png The Cortex®-M0+ can only run during LP-Stop2 low power mode.

4. Linux Kernel configuration[edit | edit source]

  • To manage the Cortex®-M0+, activate the Cortex®-M0+ remoteproc driver by enabling the STM32_M0_RPROC build configuration,
  • To communicate with the Cortex®-M0+, activate the mailbox char device client by enabling the MAILBOX_CDEV build configuration.

5. Linux Kernel device tree configuration[edit | edit source]

The Cortex®-M0 live cycle in managed by the Linux kernel remoteproc framework.To configure the Cortex®-M0+, we mainly need:

  • to define the memory mapping
  • to define the m0_rproc node in device tree
  • to define the mailbox char device client node configuration.

5.1. Memory configuration[edit | edit source]

In the STM32MPU Embedded Software distribution, the default memory configuration is splited in 3 memory regions that can be customized:

  • Code  : 16KB (LPSRAM1 & LPSRAM2)
  • Data  : 8KB (LPSRAM3)
  • Shared Memory : 8KB (LPSRAM3)

The shared memory is used to shared data between Cortex®-M0+ and Cortex®-A35 through interprocessor communication and mailbox mechanisms.

		cm0_cube_fw: cm0-cube-fw@200C0000 {
			compatible = "shared-dma-pool";
			reg = <0x0 0x200C0000 0x0 0x4000>;
			no-map;
		};

		cm0_cube_data: cm0-cube-data@200C4000 {
			compatible = "shared-dma-pool";
			reg = <0x0 0x200C4000 0x0 0x2000>;
			no-map;
		};

		ipc_shmem_2: ipc-shmem-2@200C6000{
			compatible = "shared-dma-pool";
			reg = <0x0 0x200C6000 0x0 0x2000>;
			no-map;
		};
Info white.png Information
This memory mapping need to be aligned with the Cortex®-M0+ Cube Firmware memory mapping (Linkerscript).

5.2. Remoteproc configuration[edit | edit source]

  • The memory-region property should list the memories used for the firmware execution and for the interprocessor communication
  • The clocks property should list the peripheral clocks used by the Cortex®-M0+
&m0_rproc {
	mboxes = <&ipcc2 0>, <&ipcc2 1>, <&ipcc2 2>; 
	mbox-names = "rx", "tx", "shutdown";
	memory-region = <&cm0_cube_fw>, <&cm0_cube_data>;
	clocks = <&rcc CK_CPU3>,              <- Enable CPU3 clock
		 <&rcc CK_CPU3_AM>,               <- Enable CPU3 autonomous Mode
		 <&rcc CK_LPUART1_C3>,            <- Allocate LPUART1 to CPU3
		 <&rcc CK_KER_LPUART1>,           <- Enable LPUART1 clock 
		 <&rcc CK_LPUART1_AM>,            <- Enable LPUART1 autonomous Mode 
		 <&scmi_clk CK_SCMI_IPCC2>,       <- Enable IPCC2 clock
		 <&scmi_clk CK_SCMI_IPCC2_AM>;    <- Enable IPCC2 autonomous Mode
	status = "okay";
};

5.3. Mailbox client configuration[edit | edit source]

  • The memory-region property should list the memory used for the interprocessor communication (shared memory)
	mbox_client: mailbox-client@1 {
		compatible = "mbox-cdev";
		reg = <1 0>;
		memory-region =  <&ipc_shmem_2>;
		mboxes = <&ipcc2 0>;
		mbox-names = "rx-tx";
		status = "okay";
	};

6. Cortex®-M0+ demonstration (applicable on STM32MP257x-EV1 Evaluation board More info green.png only)[edit | edit source]

The Cortex®-M0+ demonstration aims to show the Cortex®-A35 wakeup from low power mode (LP-Stop2) from Cortex®-M0+.

The demonstration application consists in:

  • Starting the Cortex®-M0+ firmware through remoteproc driver.
  • Configuring a wakeup delay in Cortex®-CM0+ firmware from Linux userland (Cortex®-A35) by using IPCC communication, shared memory and Mailbox mechanism.
  • Setting the LP-Stop2 low power mode.
  • Waking up the Cortex®-A35 from Cortex®-M0+ firmware through interrupt after the programmed delay is expired.

6.1. STM32Cube Firmware application[edit | edit source]

The Cortex®-M0+ STM32Cube Firmware application is available as an example in STM32CubeMP2 Firmware Package. It allows to wake up the Cortex®-A35 from low power mode after a programmed delay.

This application uses the following features:

  • LPUART1 : to print messages on console
  • IPCC2 : to send / receive notification between Cortex®-M0+ and Cortex®-A35 through interprocessor communication mechanism (interrupt)
  • Shared Memory: to share data between the Cortex®-M0+ and Cortex®-A35

Purpose of this application is to:

  • Initialize LPUART1 for printing messages on the console.
  • Initialize IPCC2 for communication between Cortex®-M0+ and Cortex®-A35.
  • Print a message on LPUART1 every 2 seconds.
  • Wait from an IPCC2 interrupt which corresponds to a message received in shared memory from Cortex®-A35.
    • Once IPCC2 interrupt is received, then the firmware:
      • Reads the first 4 bytes from the shared memory, which represent the delay before sending a notification to the Cortex®-A35.
      • Starts a delay with the value read from shared memory.
      • Once delay has elapsed, send a notification through the IPCC2 to wake up the Cortex®-A35.
  • Continue printing default message in LPUART1 and waiting for new message from Cortex®-A35.

6.2. Board and connectors[edit | edit source]

Main access to Cortex®-M0+ is done through the MikroBUS connector available on STM32MP257x-EV1 Evaluation board More info green.png.

Microbus.png

6.3. How to connect LPUART1[edit | edit source]

To use the LPUART1, you need to :

  • Connect the 3 wired USB-to-TTL Serial UART debug cable to MikroBUS connector through pins RX/TX/GND.

6.4. How to debug Cortex®-M0+[edit | edit source]

The debug of the Cortex®-M0+ can done by 2 ways according to the state of the Cortex®-A35 as the following :

  • When the Cortex®-A35 is running, the debug of Cortex®-M0+ can be done through STLINK connector.
  • When the Cortex®-A35 is in low power mode, the debug of Cortex®-M0+ can be done through the SWD port.
Warning white.png Warning
the hardware allows to use the STLINK while the low power mode is set. But in such case, the hardware maintains some regulators and clocks. To debug the Cortex®-M0+ in LP-Stop2 low power mode it is recommended to use the dedicated SWD port

To use the SWD interface, you need to :

  • Connect the debugger to MikroBUS connector through pins MISO/MOSI/3.3V/GND.
  • Enable the SWD debug interface for the Cortex®-M0+ (clear the bit DBG_SWD_SEL_N of the register DBGMCU_CR).

Dbgmcu cr.png

6.5. How to run the Cortex®-M0+ demonstration application[edit | edit source]

The Cortex®-M0+ firmware image has to be copied in folder /lib/firmware in the Linux rootfs. By default the Cortex®-M0+ firmware is named CM0PLUS_Demo_NonSecure.elf.

  • Start from following path and check that the Cortex®-M0+ firmware is available
 cd /lib/firmware
  • Stop the M33 firmware
 echo stop > /sys/class/remoteproc/remoteproc0/state
  • Configure the M0+ firmware
 echo CM0PLUS_Demo_NonSecure.elf > /sys/class/remoteproc/remoteproc1/firmware
  • Start the M0+ firmware
 echo start > /sys/class/remoteproc/remoteproc1/state
[ 1245.086086] remoteproc remoteproc1: powering up m0
[ 1245.120304] remoteproc remoteproc1: Booting fw image CM0PLUS_Demo_NonSecure.elf, size 1017852
[ 1245.123454] remoteproc remoteproc1: remote processor m0 is now up
  • Enabling IPCC2 wakeup source for A35 wakeup
 echo enabled > /sys/devices/platform/soc@0/46250000.mailbox/power/wakeup
  • Configure delay to Cortex®-M0+ before waking-up Cortex®-A35 (ex : 7s)
 echo 7 > /dev/mailbox0

Cortex®-M0+ logs from LPUART1:

**** CM0PLUS Example application ****
(1) Hello from CM0+
(2) Hello from CM0+
(3) Hello from CM0+
(4) Hello from CM0+
(5) Hello from CM0+
(5) A35 wakeup request in 7s
  • Set Cortex®-A35 to low power (during 30 seconds)
rtcwake --date +30sec -m mem

Cortex®-A35 logs from Linux console:

rtcwake: assuming RTC uses UTC ...
rtcwake: wakeup from "mem" using /dev/rtc0 at Tue Oct  8 16:44:29 2024
[  414.922335] PM: suspend entry (deep)
[  414.922538] Filesystems sync: 0.000 seconds
[  414.960147] Freezing user space processes
[  414.962082] Freezing user space processes completed (elapsed 0.001 seconds)
[  414.965543] OOM killer disabled.
[  414.968675] Freezing remaining freezable tasks
[  414.974403] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[  414.985780] stm32-dwmac 482d0000.eth2 end0: FPE workqueue stop
[  414.986671] stm32-dwmac 482c0000.eth1 end1: FPE workqueue stop
[  415.070706] Disabling non-boot CPUs ...
[  415.072458] psci: CPU1 killed (polled 0 ms)
INFO:    Entering LP_Stop2 low power mode
  • Cortex®-A35 wakeup

Cortex®-M0+ logs from LPUART1:

(5) A35 wakeup request done !
(6) Hello from CM0+

Cortex®-A35 logs from Linux console:

[  415.073956] Enabling non-boot CPUs ...
I/TC: Secondary CPU 1 initializing
I/TC: Secondary CPU 1 switching to normal world boot
[  415.085464] Detected VIPT I-cache on CPU1
[  415.085540] CPU1: Booted secondary processor 0x0000000001 [0x411fd040]
[  415.086106] CPU1 is up
[  415.095505] i2c 0-001a: Unbalanced pm_runtime_enable!
[  415.137097] dwmac4: Master AXI performs any burst length
[  415.137154] stm32-dwmac 482c0000.eth1 end1: No Safety Features support found
[  415.345753] stm32-dwmac 482c0000.eth1 end1: IEEE 1588-2008 Advanced Timestamp supported
[  415.348476] stm32-dwmac 482c0000.eth1 end1: FPE workqueue start
[  415.354080] stm32-dwmac 482c0000.eth1 end1: configuring for phy/rgmii-id link mode
[  415.577092] dwmac4: Master AXI performs any burst length
[  415.577134] stm32-dwmac 482d0000.eth2 end0: No Safety Features support found
[  415.583804] stm32-dwmac 482d0000.eth2 end0: IEEE 1588-2008 Advanced Timestamp supported
[  415.591954] stm32-dwmac 482d0000.eth2 end0: FPE workqueue start
[  415.597751] stm32-dwmac 482d0000.eth2 end0: configuring for phy/rgmii-id link mode
[  416.086930] onboard-usb-hub 1-1: reset high-speed USB device number 2 using ehci-platform
[  416.352327] OOM killer enabled.
[  416.352360] Restarting tasks ... done.
[  416.359329] random: crng reseeded on system resumption
[  416.366896] PM: suspend exit

7. Code source[edit | edit source]

7.1. Linux kernel[edit | edit source]

drivers/remoteproc/stm32_m0_rproc.c 
drivers/mailbox/mailbox-client_cdev.c 
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts 

7.2. STM32Cube application[edit | edit source]

Projects/STM32MP257F-EV1/Demonstrationss/CM0PLUS_DEMO