Project

General

Profile

AM62x M4 RPMsg echo to Arm/Linux

Objectives:

  • Build and run an M4 program which will echo any RPMsg message it receives back to the sender.
  • Build and run an ARM/Linux user program which will send a number of messages to the M4 and receive the messages echoed back.
  • Run both of these programs in debuggers.

Prerequisites

Step 1: Building the M4 program

Creating the project and getting the initial source

  • Import CCS projects. File->Import...->Code Composer Studio->CCS Projects-> Next
  • Select Search-directory: Browse to ~/ti/mcu_plus_sdk_am62x_08_06_00/examples/drivers/ipc/ipc_rpmsg_echo_linux
  • Select the ipc_rpmsg_echo_linux_am62x-sk_m4fss0-0_freertos_ti-arm-clang project (make sure Copy projects into workspace is checked.)
  • Finish

Modifying the source for a debugger wait loop

  • Open ipc_rpmsg_echo.c
  • In the function ipc_rpmsg_echo_main() near line 360, change the initial code to look like:

Initial Code

void ipc_rpmsg_echo_main(void *args)
{
    int32_t status;

    Drivers_open();
    Board_driversOpen();

    DebugP_log("[IPC RPMSG ECHO] Version: %s (%s %s):  \r\n", IPC_FW_VERSION, __DATE__, __TIME__);


Modified Code
void ipc_rpmsg_echo_main(void *args)
{
    int32_t status;
    int max_wait_time = 30;

    Drivers_open();
    Board_driversOpen();

    DebugP_log("[IPC RPMSG ECHO] Version: %s (%s %s):  \r\n", IPC_FW_VERSION, __DATE__, __TIME__);

    DebugP_log("Starting to wait for debugger attach. %d seconds\r\n", max_wait_time);
    for (int ii = 0; ii < max_wait_time; ++ii)
    {
        if ((ii % 5) == 0)
        {
            DebugP_log("%3d secs: Waiting for debugger attach\r\n", ii);
        }
        ClockP_sleep(1);
    }

    DebugP_log("Done waiting for debugger attach. Moving on...\r\n");

Building the project

Do one of the following:
  • Press ctrl-B to start the build of the project.
  • Project->Build Project
  • In the Project Explorer, point the mouse to the project name, rightmouse->Build Project

Putting the program on the target

  • Open a Terminal window, local terminal
    cd <your_workspace>/ipc_rpmsg_echo_linux_am62x-sk_m4fss0-0_freertos_ti-arm-clang/Debug
    ssh am62x mkdir mcu_rpmsg
    scp am62-mcu-m4f0_0-fw am62x:mcu_rpmsg
    ssh am62x ln -sf /home/root/mcu_rpmsg/am62-mcu-m4f0_0-fw /lib/firmware/am62-mcu-m4f0_0-fw
    

Using remoteproc to start the program on the target

For these commands, it is best to use the serial console of the target so you can see the system messages printed on the console. When stopping the remoteproc, if the remoteproc is already stopped, you will see an error message that can be ignored. When starting the remoteproc, there should be several messages indicating that the remoteproc is loaded and up and running.

It would also be useful to attach to the second uart of the usb uart connection. The second uart will be the uart connected to the M4. When the M4 is running, there will be messages printed on this second console.

Commands for the target console:

echo stop >/sys/class/remoteproc/remoteproc0/state
echo start >/sys/class/remoteproc/remoteproc0/state

These commands can also be given from the Local Terminal in Code Composer:

ssh am62x 'echo stop >/sys/class/remoteproc/remoteproc0/state'
ssh am62x 'echo start >/sys/class/remoteproc/remoteproc0/state'

Checking the output of the program

On the ARM UART, when you stop and start the M4 remoteproc, you should see output like:

root@mitysom-am62x:~# echo stop >/sys/class/remoteproc/remoteproc0/state
[85761.244261] remoteproc remoteproc0: stopped remote processor 5000000.m4fss
root@mitysom-am62x:~# echo start >/sys/class/remoteproc/remoteproc0/state
[85776.450011] remoteproc remoteproc0: powering up 5000000.m4fss
[85776.456996] remoteproc remoteproc0: Booting fw image am62-mcu-m4f0_0-fw, size 119820
[85776.466410]  remoteproc0#vdev0buffer: assigned reserved memory node m4f-dma-memory@9cb00000
[85776.475484] virtio_rpmsg_bus virtio0: rpmsg host is online
[85776.482169]  remoteproc0#vdev0buffer: registered virtio0 (type 7)
[85776.488394] remoteproc remoteproc0: remote processor 5000000.m4fss is now up
root@mitysom-am62x:~# [85806.479843] virtio_rpmsg_bus virtio0: creating channel ti.ipc4.ping-pong addr 0xd
[85806.487819] virtio_rpmsg_bus virtio0: creating channel rpmsg_chrdev addr 0xe

Note that the final 2 messages come out 30 seconds after the initial messages.

The extra 30 seconds is the time inserted to wait for the debugger connection. This is not really a long time and it will be made longer when we want to do debugging. For now, it is enough to be observable but not greatly annoying.

On the M4 UART, you should see output like:

[IPC RPMSG ECHO] Version: REL.MCUSDK.08.06.00.12 (May  5 2023 14:32:31):
Starting to wait for debugger attach. 30 seconds
  0 secs: Waiting for debugger attach
  5 secs: Waiting for debugger attach
 10 secs: Waiting for debugger attach
 15 secs: Waiting for debugger attach
 20 secs: Waiting for debugger attach
 25 secs: Waiting for debugger attach
Done waiting for debugger attach. Moving on...
[IPC RPMSG ECHO] Remote Core waiting for messages at end point 13 ... !!!
[IPC RPMSG ECHO] Remote Core waiting for messages at end point 14 ... !!!

At this point, the M4 program is running and waiting for the Arm/Linux to send it messages.

Comment on the program and the resource table

Using just a makefile to build the program.

If you want to build the program with a makefile without using Code Composer, you can just use the makefile that comes with the example. Try the following:

Create a script like the following to do the proper setup for using the makefile.

Contents of build.sh:

#!/bin/bash

export MCU_PLUS_SDK_PATH=/home/$USERNAME/ti/mcu_plus_sdk_am62x_08_06_00_18

cd ipc_rpmsg_echo_linux/am62x-sk/m4fss0-0_freertos/ti-arm-clang

make "$@" 

With this script, you can just copy the example at ~/ti/mcu_plus_sdk_arm62x_08_06_00_18/examples/drivers/ipc/ipc_rpmsg_echo_linux to a work directory and run build.sh.

mkdir work_dir
cd work_dir
cp -r ~/ti/mcu_plus_sdk_am62x_08_06_00_18/examples/drivers/ipc/ipc_rpmsg_echo_linux .
# create build.sh with above contents, make it executable
./build.sh

# Use ./build.sh clean to clean the generated files with:
./build.sh clean

This example program could be used as a starting point for your own application. Or you could pick a different example that might be closer to your application and use that as a starting point. If the example is close enough, then your modifications may just consist of adding more source files. This approach is usually much easier than trying to create a makefile from scratch.

Step 2: Building the Arm/Linux user program

Getting the source files

The source files are contained in a TI git repository.

mkdir rpmsg
cd rpmsg
git clone https://git.ti.com/cgit/rpmsg/ti-rpmsg-char

Adding the project

In the existing workspace with the M4 program, we can add a second project for the Arm/Linux program.

  • File->New->Project->C/C++->C Project->Next
  • C Project
    • Project name: linux_rpmsg_demo
    • Project type: Empty Project
    • Toolchains: Cross GCC
    • Next
  • Select Configurations
    • Next
  • Cross GCC Command
    • Browse to the C Compiler in the ti-processor-sdk.
    • Cross compiler path: ~/ti-processor-sdk-linux-am62xx-evm-08.06.00.42/linux-devkit/sysroots/x86_64-arago-linux/usr/bin
    • Cross compiler prefix: aarch64-none-linux-gnu-
    • Finish
  • Add the source files
    • File->Import...->General->File System->Next
    • From Directory: Browse to the rpmsg/ti-rpmsg-char path
    • In the examples directory, select *.c file
    • In the include directory, select all the *.h files
    • In the src directory, select all *.c and *.h files
    • Into folder: linux_rpmsg_demo
    • Finish

The linux_rpmsg_demo project should now have examples, include, and src folders.

Building the project

Build the linux_rpmsg_demo project by doing one of the following.

  • Select the project in the Project Explorer. right-mouse->Build Project
  • Enter ctrl-B. (this will build both project)
  • Project->Build Project

Putting the program on the target

In the Local Terminal of Code Composer

cd <your_workspace_path>/linux_rpmsg_demo/Debug
scp linux_rpmsg_demo am62x:mcu_rpmsg

Running the program

  • Wait for the M4 program to get past the debugger wait
  • Processor ids are listed in rproc_id.h. The id "9" represents M4F_MCU0_0.
  • From the Terminal window, here is the command and expected output.
ssh am62x ./mcu_rpmsg/linux_rpmsg_demo -r 9 -n 10
Created endpt device rpmsg-char-9-1638, fd = 3 port = 1024
Exchanging 10 messages with rpmsg device ti.ipc4.ping-pong on rproc id 9 ...

Sending message #0: hello there 0!
Receiving message #0: hello there 0!
Sending message #1: hello there 1!
Receiving message #1: hello there 1!
Sending message #2: hello there 2!
Receiving message #2: hello there 2!
Sending message #3: hello there 3!
Receiving message #3: hello there 3!
Sending message #4: hello there 4!
Receiving message #4: hello there 4!
Sending message #5: hello there 5!
Receiving message #5: hello there 5!
Sending message #6: hello there 6!
Receiving message #6: hello there 6!
Sending message #7: hello there 7!
Receiving message #7: hello there 7!
Sending message #8: hello there 8!
Receiving message #8: hello there 8!
Sending message #9: hello there 9!
Receiving message #9: hello there 9!

Communicated 10 messages successfully on rpmsg-char-9-1638

TEST STATUS: PASSED

Step 3: Run both programs in debuggers

Create a Target Configuration

  • Select the ipc_rpmsg_echo_linux_am62x-sk_m4fss0-0_freertos_ti-arm-clang project in the Project Explorer
  • Right-mouse->File->Target Configuration File
  • File name: am62x.ccxml
  • Finish
  • General Setup
    • Change Connection to the type of probe you are using.
    • Board or Device should be AM62
    • Advanced
      • Select CortexA53_0, Check the Bypass box.
      • Select CortexA53_1, Check the Bypass box.
      • Select CortexA53_2, Check the Bypass box.
      • Select CortexA53_3, Check the Bypass box.
      • Click the Save button

Bypassing the 4 ARM cpus is a safety measure so you don't accidentally connect to a Linux cpu with the JTAG connection. This doesn't usually turn out well.

Make the debugger wait loop longer (180 seconds)

  • In the ipc_rpmsg_echo.c file near line 364, change the value of "max_wait_time" from 30 to 180.
  • Build the program

Put rebuilt program on the target

In the Local Terminal view on Code Composer.

cd <your_workspace>/ipc_rpmsg_echo_linux_am62x-sk_m4fss0-0_freertos_ti-arm-clang/Debug
scp am62-mcu-m4f0_0-fw am62x:mcu_rpmsg

Use remoteproc to stop and start the program on the target

In the Local Terminal view on Code Composer.

ssh am62x 'echo stop >/sys/class/remoteproc/remoteproc0/state'
ssh am62x 'echo start >/sys/class/remoteproc/remoteproc0/state'

Connect the M4 debugger, set breakpoint

  • Launch the Target Configuration
    • Window->Show View->Target Configurations
    • In Target Configurations View-
      • Projects->ipc_rpmsg_echo_linux_am62x-sk_m4fss0-0_freertos_ti-arm-clang->am62x.ccxml
      • right-mouse->Launch Selected Configuration
  • Connect to the M4
    • In the Debug view, select BLAZAR_Cortex_M4F_1->right-mouse->Connect Target
  • Load the Symbols
    • Run->Load->Load Symbols
      • Browse the ipc_rpmsg_echo_linux_am62x-sk_m4fss0-0_freertos_ti-arm-clang project and select the ipc_rpmsg_echo_linux_am62x-sk_m4fss0-0_freertos_ti-arm-clang.out executable
      • note that the am62-mcu-m4f0_0-fw which is copied to the target does not contain symbols and is not helpful to the debugger
  • Set breakpoint in the delay loop.
    • around line 378 in ipc_rpmsg_echo.c, set a breakpoint at the ClockP_sleep(1);
    • Resume the target. Run->Resume
  • Move out of the loop
    • When stopped at the call to ClockP_sleep()
    • Select the first line outside the delay loop (line 381)
    • Right-mouse->Move Line
  • Set a breakpoint when a message is received.
    • In ipc_rpmsg_echo.c, near line 163
    • Set a breakpoint at the first line after the call to RPMessage_recv()
  • Run. Run->Resume

Start the Linux program in gdbserver, set breakpoint

  • ssh am62x gdbserver :10000 ./mcu_rpmsg/linux_rpmsg_demo -r 9 -n 10
  • In the Project Explorer, select the linux_rpmsg_demo project
  • Run->Debug Configurations
    • C/C++ Remote Application->right-mouse->New Configuration
    • Name: linux_rpmsg_demo Debug
    • At the bottom: Using GDB (DSF)... click on Select other...
      • Check the Use configuration specific settings
      • Select GDB Manual Remote Debugging Launcher
      • OK
    • Debugger Tab
      • Main Tab
        • GDB debugger: gdb-multiarch
      • Connection Tab
        • TCP, localhost, 10000 (or local port that am62x is using)
    • Debug
    • Set breakpoint when message is received
      • In rpmsg_char_simple.c, near line 137
      • Set a breakpoint at the first line after the call to recv_msg()

Run program and stop when messages are received.

Resume the linux program.
  • Should stop in the M4
  • Resume the M4
  • Should stop in the linux program
  • Resume the linux program
  • Should stop in the M4
  • ...

Summary

This page has demonstrated how to:

  • Build and run an M4 program which will echo any RPMsg message it receives back to the sender.
  • Build and run an ARM/Linux user program which will send a number of messages to the M4 and receive the messages echoed back.
  • Run both of these programs in debuggers at the same time.

Go to top
Add picture from clipboard (Maximum size: 1 GB)