Search by Tags

Communicating between cores with RPMsg

 

Your progress

 

Overview

In this section, you will learn how to transfer information between the heterogeneous cores. To accomplish this, Linux has the Remote Processor Messaging framework, known as RPMsg. It is based on virtio, which is an I/O virtualization framework.

RPMsg allows kernel drivers to communicate with remote processors, so one can develop userspace applications where these drivers are used to achieve send and receive data from a remote processor to further process it.

In this module, you will:

  • Create and configure an Eclipse RPMsg project for the Cortex-M4 core
  • Build the application and run it on your module, evaluating on both cores

Materials required

  • Serial-to-USB converter

Step 1

You will create an Eclipse project similar to the one in the previous section. Now, however, you will use the str_echo_bm example that comes with the Toradex FreeRTOS repository.

This demo achieves communication by writing and reading to a virtual serial port created by the imx_rpmsg_tty linux driver, which is bundled into Linux as a module.

Set up a new Eclipse project just like you did in step 2 in the previous lesson.

Step 2

Set up your project structure. Again, go to your project folder and create a subdirectory named sources.

$ cd <your_project_diretory>
$ mkdir sources
$ cd sources

From the FreeRTOS directory, copy the folders platform, middleware and to your sources directory.

$ cp -r ~/freertos-toradex/platform ./
$ cp -r ~/freertos-toradex/middleware ./

Enter the middleware/multicore/open-amp/porting/env folder and delete the freertos folder. These are environment definitions for using RPMsg with FreeRTOS applications. Since we're going with a bare-metal implementation in this example, we can delete the FreeRTOS definitions and keep the bm folder.

$ rm -r middleware/multicore/open-amp/porting/env/freertos

From examples/imx7_colibri_m4, copy the files board.c, board.h, clock_freq.c, clock_freq.h, gpio_pins.c, gpio_pins.h, pin_mux.c and pin_mux.h to a folder examples/imx7_colibri_m4 inside your sources directory.

$ mkdir examples
$ cd examples
$ mkdir imx7_colibri_m4
$ cd ../..
$ cp examples/imx7_colibri_m4/{board*,clock_freq*,gpio_pins*,pin_mux*} examples/imx7_colibri_m4

From examples/imx7_colibri_m4/demo_apps/rpmsg/str_echo_bm, copy str_echo_bm.c and hardware_init.c to your sources directory.

$ cp examples/imx7_colibri_m4/demo_apps/rpmsg/str_echo_bm/{str_echo_bm.c,hardware_init.c} ./

Your project directory should look like this:


  • Eclipse RPMsg file tree

    Eclipse RPMsg file tree

Also, make sure your includes in Project Properties -> C/C++ Build -> Settings -> ARM Cross GCC Compiler -> General are correct:


  • Eclipse RPMsg Includes

    Eclipse RPMsg Includes

All other configurations are identical to those on the previous lesson.

Step 3

Hit the build button (or press Ctrl+B).

Just like before, copy the generated elf file to your SD card and flash it into the M4 core:

$ cp <your_project_directory>/Debug/rpmsg_demo.elf /media/toradex/SDCARD

Step 4

Since the processor cores on the Colibri iMX7 have access to the same peripherals, we must disable some of them to avoid conflicts.

By default, the device tree on the Toradex-provided Linux image uses UART_B, which is the UART port used for debug on the M4 core, so we must disable it on Linux to avoid a kernel panic.

It can be done either by modifying the status property for the peripheral on the device tree to disabled (see Device Tree Customization) or, as a temporary solution, using the fdt_fixup command on U-Boot:

Colibri iMX7 # setenv fdt_fixup 'fdt addr ${fdt_addr_r} && fdt rm /soc/aips-bus@30800000/spba-bus@30800000/serial@30890000'
Colibri iMX7 # saveenv

Step 4

Once you're all set, resume the Linux booting process. The M4 core will keep running:

Colibri iMX7 # boot

Step 5

Once you're logged in, execute the following command on your board:

# modprobe imx_rpmsg_tty
[   61.598675] imx_rpmsg_tty rpmsg0: new channel: 0x400 -> 0x1!
[   61.606640] Install rpmsg tty driver!
...

Note: If you wish to load the imx_rpmsg_tty module automatically on every boot, create a config file in the modules-load.d directory by using the following command:

# echo imx_rpmsg_tty > /etc/modules-load.d/rpmsg_tty.conf

This creates a new TTY device located at /dev/ttyRPMSG which works like a virtual serial port.

You should already see a "hello world!" message on the M4 debug console, which was sent once the imx_rpmsg_tty module was loaded:

...
Name service handshake is done, M4 has setup a rpmsg channel [1 ---> 1024]
Get Message From A7 : "hello world!" [len : 12] from slot 0

Now you can open the TTY device and run write and read operations like you would do with an UART port. The following code opens the device, assigns it a file descriptor, writes and reads to int, then closes it:

# stty -F /dev/ttyRPMSG -echo
# exec 3<> /dev/ttyRPMSG 
# echo Test >&3 
# cat <&3
Test
^C
# exec 3>&- 

  • RPMsg demo

    RPMsg demo

FAQ

Is it possible to increase the RPMsg buffer size
Is it possible to store the M4 firmware on flash and automatically run it on boot