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.
Information |
The Cortex®-M0+ demonstration application is only applicable for STM32MP257x-EV1 Evaluation board as it use the LPUART1 which is not available for STM32MP257x-DK Discovery kit . |
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)
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)
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.
Information |
On ecosystem release v6.0.0 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; };
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 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.
- Once IPCC2 interrupt is received, then the firmware:
- 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 .
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.
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).
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