Cortex-M Shared Memory Guide
Introductionβ
The objective of this article is to demonstrate a method for data exchange between two cores within the Heterogeneous Multi-processing (HMP) configuration, without employing drivers or RPMsg protocols. The approach involves reserving a buffer in the RAM and accessing its data from the two cores.
If you are looking for information about other approaches for exchanging data between two cores with different architectures, refer to the following articles:
Prerequisitesβ
- Follow the steps at Setting Up MCUXpresso SDK and Toolchain for Cortex-M development.
- Understanding of how to load compiled binaries into Cortex-M.
- Understanding of how to debug Cortex-M using JTAG (Cortex-M JTAG Debugging).
Exchanging Data Through Shared Memoryβ
These steps illustrate a basic data exchange technique, but lacks the data safety of RPMsg and Remoteproc. Therefore, it shouldn't be used in production without substantial code improvements and safeguards.
Create the demo project. For that, simply go to the
demo_apps
folder and copy thehello-world
demo that comes from the SDK and edit the code.$ cd boards/evkmimx8mm/demo_apps/
$ cp -r hello_world shared_memoryDelete the
main.c
code and replace it with the following code:#include "FreeRTOS.h"
#include "task.h"
#include "board.h"
#include "debug_console_imx.h"
#define SHARED_MEM_ADDRESS 0x8FF00000
void SharedMemTask(void *pvParameters)
{
uint32_t *ddr_shared_mem = (uint32_t*) SHARED_MEM_ADDRESS;
// Print the initial banner
PRINTF("\\r\\nShared Memory Demo!\\n\\n\\r");
PRINTF("Shared address: 0x%X\\n\\r", SHARED_MEM_ADDRESS);
PRINTF("READ: $devmem2 0x%X\\n\\r", SHARED_MEM_ADDRESS);
PRINTF("-------------------------------------------------------------------------------\\n\\r");
// write 0xBB in the shared memory address
*ddr_shared_mem = 0xBB;
while(1)
{
PRINTF("\\r\\n0x%X: 0x%X\\n\\r", SHARED_MEM_ADDRESS, *ddr_shared_mem);
for (int i = 0; i < 10000000; i++);
}
}
int main(void)
{
hardware_init();
xTaskCreate(SharedMemTask, "Print Task", configMINIMAL_STACK_SIZE,
NULL, tskIDLE_PRIORITY+1, NULL);
vTaskStartScheduler();
// Should never reach this point.
while (true);
}This code will read the address 0x8FF00000 and keep printing its contents in a loop. The content is 4 bytes long.
Compile the code and send it to the module. For information on how to set up the SDK and compile your code, refer to Setting Up MCUXpresso SDK and Toolchain for Cortex-M development.
Create a device tree overlay that has a
reserved-memory
node that reserve 1MB in the address 0x8FF00000./dts-v1/;
/plugin/;
/ {
compatible = "toradex,verdin-imx8mm";
};
&{/} {
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
m4_shm: cm4@8FF00000 {
reg = <0x8FF00000 0x100000>;
no-map;
};
};
};Compile the overlay and deploy to the module. Then, edit the
overlays.txt
file to enable the overlay.Reboot the module. At this point, during boot, you should be able to see Cortex-M printing messages on UART:
Shared Memory Demo!
Shared address: 0x8FF00000
READ: $devmem2 0x8FF00000
-------------------------------------------------------------------------------
0x8FF00000: 0xBB
0x8FF00000: 0xBB
0x8FF00000: 0xBB
0x8FF00000: 0xBBIn this case, Cortex-M wrote 0xBB to 0x8FF00000 and itβs printing the content.
In runtime, change the value using
devmem2
:# devmem2 0x8FF00000 w 0xFF
/dev/mem opened.
Memory mapped at address 0xb6f0a000.
Read at address 0x8FF00000 (0xb6f0a000): 0x000000BB
Write at address 0x8FF00000 (0xb6f0a000): 0x000000FF, readback 0x000000FFYou will see that the value on Cortex-M changed:
0x8FF00000: 0xFF
0x8FF00000: 0xFF
0x8FF00000: 0xFF
0x8FF00000: 0xFFYou can also read it back on Linux:
# devmem2 0x8FF00000
/dev/mem opened.
Memory mapped at address 0xb6f99000.
Read at address 0x8FF00000 (0xb6f99000): 0x000000FFChange this value on the Cortex-M side. For this, edit the code from the step 1 by writing to the 0x8FF00000 address.
uint32_t value = 0;
PRINTF("\\r\\nWrite a value for this register (in HEX): \\n\\r");
SCANF("%X", &value);
PRINTF("\\r\\nValue: 0x%X \\n\\r",value);
*ddr_shared_mem = value;