Skip to main content

Cortex-M Shared Memory Guide

danger

The example in this article lacks the data safety of RPMsg and RemoteProc. Therefore, Toradex doesn't recommend using this method in production without substantial code improvements and safeguards.

Introduction

This article describes how to exchange data between two cores using the MCUXpresso SDK.

The method described in this article doesn't use drivers or RPMsg protocols. To exchange data between cores using RPMsg and RemoteProc, refer to the following articles:

This article complies with the Typographic Conventions for Toradex Documentation.

Prerequisites

The MCUXpresso SDK and all required tools must be configured before proceeding. Refer to the Setting Up the MCUXpresso SDK and Toolchain for HMP Development article for more information about the installation process.

Exchanging Data Through Shared Memory

The following procedure describes how to exchange data between the alternative core and Linux environment using shared memory.

  1. Modify the hello_world example to write and read data from a shared memory address in the DDR:

    warning

    The shared memory address used in the following example is 0x8FF00000, but it may need to be adjusted based on the module's memory map. Make sure to choose an address that is not used by any other component and is properly reserved in the device tree overlay. After choosing the shared memory address, make sure to update it in the main file and the device tree overlay accordingly.

    To check the memory map of the module, run the following command in the Linux environment:

    # cat /proc/iomem
    hello_world.c
    #include "fsl_device_registers.h"
    #include "fsl_debug_console.h"
    #include "board.h"
    #include "app.h"

    /*******************************************************************************
    * Definitions
    ******************************************************************************/
    #define SHARED_MEM_ADDRESS 0x8FF00000

    /*!
    * @brief Main function
    */
    int main(void)
    {
    /* Initialize standard SDK demo application pins */
    BOARD_InitHardware();

    volatile uint32_t *ddr_shared_mem = (uint32_t*) SHARED_MEM_ADDRESS;

    /* Print the initial banner */
    PRINTF("\r\nShared Memory Demo!\r\n\n");
    PRINTF("Shared address: 0x%X\r\n", SHARED_MEM_ADDRESS);
    PRINTF("READ: $devmem2 0x%X\r\n", SHARED_MEM_ADDRESS);
    PRINTF("--------------------\r\n");

    /* Write 0xBB in the shared memory address */
    *ddr_shared_mem = 0xBB;

    uint8_t index = 1;

    while(1)
    {
    PRINTF("\r\n0x%X: 0x%X\r\n", SHARED_MEM_ADDRESS, *ddr_shared_mem);

    PRINTF("Index: %d\r\n", index);
    if (index == 25)
    index = 1;
    else
    index++;

    for (uint32_t i = 0; i < 10000000; i++);
    }
    }
  2. Create a device tree overlay with a reserved-memory node that matches the main device tree file:

info

For Torizon OS, device tree overlays can be enabled with TorizonCore Builder. For Linux BSP images, refer to the Device Tree Overlays documentation.

custom-imx95-shared-memory-overlay.dts
/dts-v1/;
/plugin/;

/ {
compatible = "toradex,verdin-imx95";

fragment@0 {
target-path = "/reserved-memory";

__overlay__ {
#address-cells = <2>;
#size-cells = <2>;

m7_shm: m7-shm@8ff00000 {
reg = <0x0 0x8ff00000 0x0 0x100000>;
no-map;
};
};
};
};
  1. Compile a firmware for the alternative core. Refer to How To Compile Firmware for Alternative Cores (NXP) for instructions.

  2. Load and run the compiled firmware, following the instructions available on How To Load and Run Firmware on Alternative Cores (NXP).

  3. Boot the module and check the alternative core UART output to confirm that the shared memory is working as expected:

    Shared Memory Demo!

    Shared address: 0x8FF00000
    READ: $devmem2 0x8FF00000
    --------------------

    0x8FF00000: 0xBB
    Index: 1

    0x8FF00000: 0xBB
    Index: 2

    0x8FF00000: 0xBB
    Index: 3

    0x8FF00000: 0xBB
    Index: 4
  4. Run the following container to initialize a Debian environment with the required tools:

    # docker run --rm -it \
    --privileged \
    --device=/dev/mem \
    torizon/debian:4

    Install the busybox package inside the container to use the busybox devmem command:

    ## apt update && apt install busybox -y

    Finally, run the busybox devmem command to update the value in the shared memory address:

    ## busybox devmem 0x8FF00000 32 0xFF

    After updating the value, check the alternative core UART output again:

    0x8FF00000: 0xFF
    Index: 5

    0x8FF00000: 0xFF
    Index: 6

    0x8FF00000: 0xFF
    Index: 7

    0x8FF00000: 0xFF
    Index: 8
Send Feedback!