RISCV_RPMSG USER GUIDE


REVISION HISTORY

Revision No.
Description
Date
1.0 Initial release 04/17/2025

1. RPMSG DESCRIPTION

1.1. Overview

RPMsg stands for Remote Processor Messaging, an open multi-core communication protocol. Linux Kernel has a built-in implementation of the RPMsg protocol.

1.2. Flowchart

SigmaStar RPMsg userspace driver connects to the Linux built-in RPMsg protocol implementation and provides an interface for creating RPMsg Endpoints. Linux userspace apps can use these endpoints to communicate with apps under FreeRTOS.

SigmaStar RPMsg userspace driver will generate a device node /dev/rpmsg_ctrl0. Linux userspace apps can create endpoint device nodes (e.g. /dev/rpmsg0) for communication through the ioctl interface provided by /dev/rpmsg_ctrl0. When creating a node, you need to specify the local address and the remote communication address. For example, when creating an endpoint on the Linux userspace app, you specify the src address Src1 and the dst address Dst1. Then, on FreeRTOS, you need to use Dst1 as the src address to create an endpoint, and use Src1 as the dst address when sending data. In this way, the endpoint created by the Linux userspace app can communicate with the endpoint created by FreeRTOS.

1.2.1 Architecture Diagram of Linux Side

1.2.2 Architecture Diagram of FreeRTOS Side

2. keyword description

  • Master The dominant side in rpmsg communication. The other side can only be ready after the master is ready. Currently, the Linux side acts as the master.

  • Remote : The subordinate side in rpmsg communication. The remote needs to be notified by the master to be ready (the protocol is self-completed). Currently, the RTOS side acts as the remote.

  • Endpoint : The object used for receiving and sending rpmsg messages, represented by a 32-bit address. The sending and receiving of rpmsg messages are based on endpoints. The address is locally assigned, meaning the endpoints of master and remote can use the same address. There is no limit to the number of endpoints, as long as the endpoint addresses and memory space are sufficient.

  • Channel : A communication group composed of an endpoint on the master and an endpoint on the remote.

3. Function description

To use RPMsg for communication, endpoints need to be created on both the master and remote sides. The receiving end needs to monitor the local endpoint, while the sending end needs to use the local endpoint to send data to the remote endpoint. Due to different encapsulations of RPMsg, the usage methods on Linux and FreeRTOS differ significantly.

3.1 Endpoint Address Allocation

We reserve the address space from 0x40000000 to 0x7FFFFFFF for user usage. Please use the address generation interface to generate user addresses.

3.2 Usage on Linux

On Linux, the channel is exposed to users as an endpoint device, which is a standard character device. The operations for opening, closing, reading, and writing are performed using the generic interfaces of the character device. Sending and receiving data operations are translated into writing to and reading from the endpoint device.

Creating an endpoint requires using the RPMsg control device /dev/rpmsg_ctrl0 . When creating an endpoint device, you need to specify both the local endpoint address and the remote endpoint address. Since the channel already contains the remote endpoint address, sending data only requires writing data to the endpoint device.

The flow for using RPMsg for communication on Linux is as follows:

Sending Information : Create the endpoint device, open the endpoint device, write data to this endpoint device, and then close the endpoint device. Receiving Information : Create the endpoint device, open the endpoint device, read data from this endpoint device, and then close the endpoint device.

3.3 Usage on FreeRTOS

On FreeRTOS, to use RPMsg for communication, you need to first obtain an RPMsg instance. Then, use the instance to create the reception queue and the endpoint itself. Reception uses the receive interface to fetch data from the reception queue, while sending uses the send interface to send data from the local endpoint to the specified remote endpoint.

4. RPMSG DEMO

This chapter introduces two demos: RPMsg demo and RPMsg speed demo. The RPMsg demo code requires the user to manually add it to the project for compilation, while the RPMsg speed demo code is already integrated into the project. For RPMsg speed demo The defconfig for the emmc type is pre-enabled by default, and other types require the user to compile them manually.

4.1. RPMsg Demo Introduction

RPMsg demo consists of two parts, one is Linux userspace app, the other is FreeRTOS app, and the two apps use RPMsg to communicate.

In this demo, Linux userspace app continuously sends numbered "hello, world" messages to FreeRTOS app, then reads the response from FreeRTOS app and prints it out. FreeRTOS app waits in a loop for Linux userspace app to send data, then sends the data back without modification.

4.1.1 Linux Userspace App

4.1.1.1 Code (app_demo.c)
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <sys/ioctl.h>
 7 #include <fcntl.h>
 8 #include <stdint.h>
 9
10 #include "sstar_rpmsg.h"
11
12 int main(void)
13 {
14     struct ss_rpmsg_endpoint_info info;
15     char buffer[512];
16     char data[512];
17     int ret;
18     char devPath[256];
19     int fd, eptFd;
20     unsigned int index = 0x0;
21
22     memset(&info, 0, sizeof(info));
23     info.src = EPT_ADDR_MACRO(EPT_TYPE_CUSTOMER, 1);
24     info.dst = EPT_ADDR_MACRO(EPT_TYPE_CUSTOMER, 2);
25     snprintf(info.name, sizeof(info.name), "demo");
26     info.mode = RPMSG_MODE_RISCV;
27     info.target_id = 0;
28
29     fd = open("/dev/rpmsg_ctrl0", O_RDWR);
30     if (fd < 0)
31     {
32         perror("open");
33         return 0;
34     }
35
36     if (ioctl(fd, SS_RPMSG_CREATE_EPT_IOCTL, &info) < 0)
37     {
38         perror("ioctl");
39         return 0;
40     }
41
42     sleep(2);
43
44     snprintf(devPath, sizeof(devPath),  "/dev/rpmsg%d", info.id);
45     eptFd = open(devPath, O_RDWR);
46
47     if (eptFd < 0)
48     {
49         fprintf(stderr, "Failed to open endpoint!\n");
50         return 0;
51     }
52
53     while (1)
54     {
55         snprintf(buffer, sizeof(buffer), "hello,world:0x%x\n", index++);
56         ret = write(eptFd, buffer, strlen(buffer) + 1);
57
58         memset(data, 0, sizeof(data));
59         ret = read(eptFd, data, sizeof(data));
60         if (ret > 0)
61             printf("read ept:%d, %s\n", ret, data);
62         else
63             printf("read ept error:%d\n", ret);
64     }
65     return 0;
66 }
4.1.1.2 Note

1) The sleep() function is called in line 42 to prevent mdev from not finishing creating the RPMsg Endpoint node and to delay for a short period of time actively. For details, see SS_RPMSG_CREATE_EPT_IOCTL.

4.1.1.3 Compilation

Configure the compilation toolchain and compile directly:

aarch64-linux-gnu-gcc -static -I ${KERNELPATH}/drivers/sstar/include/ -o app_demo app_demo.c

4.1.2. FreeRTOS App

4.1.2.1 Code
 1 #include "ms_platform.h"
 2 #include "cam_os_wrapper.h"
 3 #include "initcall.h"
 4 #include "rpmsg_dualos.h"
 5
 6 static struct rpmsg_lite_instance *rpmsg_instance;
 7 static CamOsThread rpmsg_test_thread;
 8
 9 static void* rpmsg_test(void *arg)
10 {
11     struct rpmsg_lite_endpoint *test_ept;
12     rpmsg_queue_handle test_ept_q;
13     int test_ept_addr;
14
15     int recved = 0;
16     int ret;
17     unsigned long src;
18     char buf[256];
19
20     CamOsPrintf("Running rpmsg_test_task ...\n");
21
22     while (1) {
23         rpmsg_instance = rpmsg_dualos_get_instance(EPT_SOC_DEFAULT, EPT_OS_LINUX);
24         if (rpmsg_instance)
25             break;
26         CamOsMsSleep(1);
27     }
28
29     test_ept_q = rpmsg_queue_create(rpmsg_instance);
30     if (test_ept_q == NULL) {
31         CamOsPrintf("rpmsg_test: failed to create queue\n");
32         return NULL;
33     }
34
35     test_ept_addr = EPT_ADDR_MACRO(EPT_TYPE_CUSTOMER, 2);
36     test_ept = rpmsg_lite_create_ept(rpmsg_instance, test_ept_addr, rpmsg_queue_rx_cb, test_ept_q);
37     if (test_ept == NULL) {
38         CamOsPrintf("rpmsg_test: failed to create ept\n");
39         rpmsg_queue_destroy(rpmsg_instance, test_ept_q);
40         return NULL;
41     }
42
43     while (1) {
44         recved = 0x0;
45         rpmsg_queue_recv(rpmsg_instance, test_ept_q, &src, (char *)&buf, 256, &recved, RL_BLOCK);
46
47         if (recved > 0) {
48             ret = rpmsg_lite_send(rpmsg_instance, test_ept, src, (char *)buf, recved, 5*1000);
49             if (ret != RL_SUCCESS) {
50                 CamOsPrintf("rpmsg_test: rpmsg_lite_send return %d\n", ret);
51             }
52         }
53     }
54     return NULL;
55 }
56
57 void RPMsgAppMainEntry(void)
58 {
59     CamOsThreadAttrb_t attr = {
60         .nStackSize = 2048
61     };
62
63     attr.szName = "rpmsg_test";
64     CamOsThreadCreate(&rpmsg_test_thread, &attr, rpmsg_test, NULL);
65 }
66
67 rtos_application_initcall(RPMsgAppMainEntry, 0);
4.1.2.2 Note

1) Lines 22-27 call rpmsg_dualos_get_instance() to get the rpmsg instance in a loop, waiting for the RPMsg driver in FreeRTOS to be ready.

2) Line 29 creates a queue. When the RPMsg driver receives data sent to the corresponding endpoint, it calls the callback function rpmsg_queue_rx_cb and puts the data into this queue.

3) Line 36 calls rpmsg_lite_create_ept() to create the RPMsg Endpoint, where the src address, callback function rpmsg_queue_rx_cb, and the queue created on line 29 are passed in.

4) Line 45 calls rpmsg_queue_recv() to receive data. After creating the RPMsg Endpoint, the RPMsg driver can receive data sent to the corresponding src address. The last parameter RL_BLOCK of rpmsg_queue_recv() means blocked, that is, if there is no data, it will block until there is data before returning. If data is received, the second parameter will return the address of the sender.

5) Line 48 calls rpmsg_lite_send() to send the data back to the sender.

4.1.2.3 Compilation

Copy the above code and replace it in sc/application/rpmsg_app/src/rpmsg_speed_demo.c in RISCV sdk (it make RPMsg speed demo unavailable!), and recompile RISCV rtos.

4.2 RPMsg speed demo

This demo is a speed test for RPMsg. For detailed test information, refer to the sdk\verify\sample_code\source\pcupid\rpmsg\speed_demo\Readme.md file.
It is divided into two parts: the RTOS section and the Linux section. The RTOS section is enabled by default, while the Linux section is only enabled by default in the emmc defconfig. Other defconfigs require manual compilation.
To run this demo, first execute the RTOS part, then run the Linux part.

4.2.1 RTOS Section

The RTOS code is located at riscv\kernel\rtk\proj\sc\application\rpmsg_app\src\rpmsg_speed_demo.c.
This section is enabled by default.
To run it, enter the following command in FreeRTOS:

RTOS # rpmsg_speed_test
rpmsg_channel1_thread: start rpmsg channel1 thread...
rpmsg_channel2_thread: start rpmsg channel1 thread...

4.2.2 Linux Section

This section is located at sdk\verify\sample_code\source\pcupid\rpmsg\speed_demo\rpmsg_speed_demo.cpp. It is enabled by default only in the emmc defconfig. For other defconfigs, manual compilation is required.

4.2.2.1 emmc Execution Method

The emmc configuration is enabled by default. To run it, simply enter the following command:

/ # /customer/sample_code/rpmsg_speed_demo/prog_rpmsg_speed_demo  
Create rpmsg channnel success !  
Please input the following key to enter the RPMsg demo test item:  
'1' : Single-channel simple send-receive test  
'2' : Dual-channel simple send-receive test  
'3' : Single-channel single-send speed test  
'4' : Dual-channel single-send speed test  
'5' : Single-channel send-receive speed test  
'6' : Dual-channel send-receive speed test  
'7' : Async single-channel send-receive speed test  
'8' : Async dual-channel send-receive speed test  
'q' : Quit test  
4.2.2.2 Non-emmc Execution Method

For non-emmc configurations (e.g., spinand), manual compilation is required:

cd sdk/verify/sample_code
make source/pcupid/rpmsg/speed_demo

The generated executable file is located at:

sample_code/out/arm(64)/app/prog_rpmsg_speed_demo

Upload the file to the board (e.g., the /customer/ directory), add executable permissions, and run it:

/ # cp mnt/prog_rpmsg_speed_demo /customer/
/ # chmod 777 /customer/prog_rpmsg_speed_demo 
/ # /customer/prog_rpmsg_speed_demo 
Create rpmsg channnel success !
Please input follow key to enter rpmsg demo test item:
'1' : Single-channel simple send-receive test
'2' : Dual-channel simple send-receive test
'3' : Single-channel single-send speed test
'4' : Dual-channel single-send speed test
'5' : Single-channel send-receive speed test
'6' : Dual-channel send-receive speed test
'7' : Async single-channel send-receive speed test
'8' : Async dual-channel send-receive speed test
'q' : Quit test

4.2.3 Test Results

Create rpmsg channnel success !
Please input follow key to enter rpmsg demo test item:
'1' : Single-channel simple send-receive test
'2' : Dual-channel simple send-receive test
'3' : Single-channel single-send speed test
'4' : Dual-channel single-send speed test
'5' : Single-channel send-receive speed test
'6' : Dual-channel send-receive speed test
'7' : Async single-channel send-receive speed test
'8' : Async dual-channel send-receive speed test
'q' : Quit test
1
Start single-channel simple send-receive test
Channel 4 send 25 bytes data to endpoint
Channel 4 receive 25 bytes data : simple send receive test
Single-channel simple send-receive test success
2
Start dual-channel simple send-receive test
Channel 4 send 25 bytes data to endpoint
Channel 5 send 25 bytes data to endpoint
Channel 4 receive 25 bytes data : simple send receive test
Channel 5 receive 25 bytes data : simple send receive test
Dual-channel simple send-receive test success
3
Start single-channel single-send speed test
Channel 4 single send speed test result : 3303360 bytes/s
4
Start dual-channel single-send speed test
Channel 5 single send speed test result : 1622912 bytes/s
Channel 4 single send speed test result : 1687888 bytes/s
5
Start single-channel send-receive speed test
Channel 4 send receive speed test result : send : 1569344 bytes/s, receive : 1569344 bytes/s
6
Start dual-channel send-receive speed test
Channel 4 send receive speed test result : send : 965712 bytes/s, receive : 965712 bytes/s
Channel 5 send receive speed test result : send : 962240 bytes/s, receive : 962240 bytes/s
7
Start async single-channel send-receive speed test
Channel 4 single receive speed test result : 2711136 bytes/s
Channel 4 single send speed test result : 1599104 bytes/s
Destroy rpmsg channnel success !
Create rpmsg channnel success !
8
Start async dual-channel send-receive speed test
Channel 4 single receive speed test result : 1729056 bytes/s
Channel 5 single receive speed test result : 1475104 bytes/s
Channel 4 single send speed test result : 767808 bytes/s
Channel 5 single send speed test result : 605616 bytes/s
Destroy rpmsg channnel success !
Create rpmsg channnel success !

5. API REFERENCE

this chaptor descript the api and data in linux.

5.1. RPMSG LINUX USERSPACE API REFERENCE

In linux, endpoint is encapsulated into RPMsg Device. So the operation create and destroy endpoint become create and destroy endpoint device. The operation send and receive data become write and read the endpoint device.

API name Function
SS_RPMSG_CREATE_EPT_IOCTL Create RPMsg Endpoint device node.
SS_RPMSG_DESTROY_EPT_IOCTL Destroy RPMsg Endpoint device node.
SS_RPMSG_DEVICES_INFO_IOCTL Get the currently connected RISCV list.
read Receive data.
write Send data.

5.1.1. SS_RPMSG_CREATE_EPT_IOCTL

  • Function

    Create an RPMsg Endpoint device node that communicates with the target chip.

  • Syntax

    struct ss_rpmsg_endpoint_info info;
    
    ioctl(fd, SS_RPMSG_CREATE_EPT_IOCTL, &info);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    fd File handle of /dev/rpmsg_ctrl0 Input
    info Attributes of the RPMsg Endpoint Input, Output
  • Return value

    • 0: Indicates success.

    • -1: Indicates failure. Check errno to get the reason.

  • Dependency

    • Header file: drivers/sstar/include/sstar_rpmsg.h & errno.h

    • Library file

  • Note

    • Each ioctl will create a new /dev/rpmsgX node (e.g. /dev/rpmsg0), representing a virtual communication channel.

    • Different mode&target_id combinations in struct ss_rpmsg_endpoint_info represent different RPMsg buses, whose address spaces are independent, so different mode&target_id combinations can use the same src address.

    • You can use the exact same struct ss_rpmsg_endpoint_info to make multiple calls to create multiple /dev/rpmsgX nodes, but once one of these nodes is opened, opening other nodes will fail, that is, only one node is allowed to be open at the same time.

    • The X in /dev/rpmsgX is returned by the id in struct ss_rpmsg_endpoint_info.

    • If mdev is used, after ioctl returns, the /dev/rpmsgX node may not have been created by mdev yet, so there will be a delay.

    • Any number of /dev/rpmsgX nodes can be created within the legal src&dst address space.

  • Example

    Linux userspace app

  • Related topic

    SS_RPMSG_DESTROY_EPT_IOCTL

5.1.2. SS_RPMSG_DESTROY_EPT_IOCTL

  • Function

    Destroy the corresponding RPMsg Endpoint device node.

  • Syntax

    ioctl(fd, SS_RPMSG_DESTROY_EPT_IOCTL);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    fd File handle of /dev/rpmsgX (e.g. /dev/rpmsg0) Input
  • Return value

    Return value description
    0 Indicates success
    -1 Indicates failure. Check errno to get the reason
  • Dependency

    • Header file: drivers/sstar/include/sstar_rpmsg.h & errno.h

    • Library file

  • Note

    • The ioctl to create the RPMsg Endpoint (i.e. /dev/rpmsgX) uses the /dev/rpmsg_ctrl0 file handle, while the ioctl to destroy the /dev/rpmsgX node uses the /dev/rpmsgX file handle. After calling SS_RPMSG_DESTROY_EPT_IOCTL, the corresponding RPMsg Endpoint device node will be destroyed after its last file handle is closed.

    • The creation/destruction and open/close of RPMsg Endpoint are independent: after opening, you can perform read/write operations; after closing, you can reopen and use it again (read/write). If there is no other requirement, you don't have to recreate it every time. When it is no longer needed, you can call SS_RPMSG_DESTROY_EPT_IOCTL to destroy it.

  • Example

    Refer to SS_RPMSG_CREATE_EPT_IOCTL for example.

  • Related topic

    SS_RPMSG_CREATE_EPT_IOCTL

5.1.3. SS_RPMSG_DEVICES_INFO_IOCTL

  • Function

    Query the list of RISCVs currently connected to the Linux system through RPMsg, and return the number and target_id list.

  • Syntax

    struct rpmsg_devices_info info;
    
    ioctl(fd, SS_RPMSG_DEVICES_INFO_IOCTL, &info);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    fd File handle of /dev/rpmsg_ctrl0 Input
    info Specify the device type to be queried and provides a buffer to store the return value Input, Output
  • Return value

    Return value description
    0 Indicates success
    -1 Indicates failure. Check errno to get the reason
  • Dependency

    • Header file: drivers/sstar/include/sstar_rpmsg.h & errno.h

    • Library file

  • Note

    • Check if RISCV is connected to Linux via RPMsg.
  • Example (Linux)

    struct rpmsg_devices_info info;
    unsigned short *pTargetIDs;
    
    info.mode = RPMSG_MODE_RISCV;
    info.count = 1;
    info.buffer = (unsigned long long)malloc(1 * sizeof(unsigned short));
    
    fd = open("/dev/rpmsg_ctrl0", O_RDWR);
    if (fd < 0)
        return -1;
    
    if (ioctl(fd, SS_RPMSG_DEVICES_INFO_IOCTL, &info) < 0) {
        close(fd);
        return -1;
    }
    
    printf(“Current %d connected RISCV: \n”, info.count);
    
    pTargetIDs = (unsigned short *)info.buffer;
    for (int i = 0; i < info.count; i++)
        printf(“target_id %hu\n”, pTargetIDs[i]);
    
    free(info.buffer);
    close(fd);
    
  • Related topic

    None.

5.1.4. Read

  • Function

    Receive the data.

  • Syntax

    ssize_t read(int fd, void *buf, size_t count);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    fd File handle of /dev/rpmsgX (e.g. /dev/rpmsg0) Input
    buf Buffer address, used to store the read data Output
    count Buffer size Input
  • Return value

    Return value description
    >= 0 Indicates success, the number of bytes read
    -1 Indicates failure, check errno to get the reason
  • Dependency

    • Header file: unistd.h & errno.h

    • Library file

  • Note

    • Supports using Linux select/poll/epoll interface to monitor the file handle (fd) of /dev/rpmsgX to check whether there is data to be read.
  • Example

    Refer to SS_RPMSG_CREATE_EPT_IOCTL for example.

  • Related topic

    SS_RPMSG_CREATE_EPT_IOCTL

5.1.5. Write

  • Function

    Send the data.

  • Syntax

    ssize_t write(int fd, const void *buf, size_t count);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    fd File handle of /dev/rpmsgX (e.g. /dev/rpmsg0) Input
    buf Buffer address, used to store the data to be sent Input
    count Number of bytes of data to be sent Input
  • Return value

    Return value description
    >= 0 Indicates success, the number of bytes sent
    -1 Indicates failure, check errno to get the reason
  • Dependency

    • Header file: unistd.h & errno.h

    • Library file

  • Note

    • Only one RPMsg data packet will be sent for each write, and one RPMsg data packet can carry up to 496 bytes of valid data, so a write can send up to 496 bytes of data. When count is greater than 496, all data can be sent by calling write multiple times.
  • Example

    Refer to SS_RPMSG_CREATE_EPT_IOCTL for example.

  • Related topic

    SS_RPMSG_CREATE_EPT_IOCTL

5.2. RPMSG LINUX USERSPACE INTERFACE DATA TYPES

The relevant data types and data structures are defined as follows:

Data types Definition
RPMSG_MODE_RISCV Indicates that the RPMsg bus where the target is located is created by the RISCV virtio device driver.
RPMSG_MODE_UNKNOWN Indicates an unknown RPMsg bus mode.
EPT_TYPE_CUSTOMER Indicates the RPMsg Endpoint address used by customers (not used by SigmaStar).
EPT_TYPE_SIGMASTAR Indicates the RPMsg Endpoint address not used by customers (used by SigmaStar).
EPT_TYPE Macro that defines the type of the RPMsg Endpoint address.
EPT_ADDR_MACRO Macro that defines the RPMsg Endpoint address.
struct ss_rpmsg_endpoint_info Attributes of the created RPMsg Endpoint.
struct ss_rpmsg_devices_info Query conditions of connected devices.

5.2.1. RPMSG_MODE_RISCV

  • Description

    Indicates that the RPMsg bus where the target is located is created by the RISCV virtio device driver.

  • Definition

    #define RPMSG_MODE_RISCV  6
    
  • Member

    None.

  • Note

    None.

  • Related data type and interface

    None.

5.2.2. RPMSG_MODE_UNKNOWN

  • Description

    Indicates an unknown RPMsg bus mode.

  • Definition

    #define RPMSG_MODE_UNKNOWN  255
    
  • Member

    None.

  • Note

    None.

  • Related data type and interface

    None.

5.2.3. EPT_TYPE_CUSTOMER

  • Description

    Indicates the RPMsg Endpoint address used by customers (not used by SigmaStar).

  • Definition

    #define EPT_TYPE_CUSTOMER    0x1
    
  • Member

    None.

  • Note

    None.

  • Related data type and interface

    None.

5.2.4. EPT_TYPE_SIGMASTAR

  • Description

    Indicates the RPMsg Endpoint address not used by customers (used by SigmaStar).

  • Definition

    #define EPT_TYPE_SIGMASTAR   0x0
    
  • Member

    None.

  • Note

    Customers are not allowed to use this type of RPMsg Endpoint when developing applications.

  • Related data type and interface

    None.

5.2.5. EPT_TYPE

  • Description

    Macro that defines the type of the RPMsg Endpoint address.

  • Definition

    #define EPT_TYPE(x)       ((x & 0x1) << 30)
    
  • Member

    None.

  • Note

    The parameter member is EPT_TYPE_CUSTOMER or EPT_TYPE_SIGMASTAR.

  • Related data type and interface

    EPT_TYPE_CUSTOMER

    EPT_TYPE_SIGMASTAR

5.2.6. EPT_ADDR_MACRO

  • Description

    Macro that defines the RPMsg Endpoint address.

  • Definition

    #define EPT_ADDR_MACRO(t, c)  (EPT_TYPE(t) | (c & 0x3fffffff))
    
  • Member

    None.

  • Note

    t indicates the address type, EPT_TYPE_CUSTOMER or EPT_TYPE_SIGMASTAR.

    c indicates the value of the address, which can be any number when using EPT_TYPE_CUSTOMER.

  • Related data type and interface

    EPT_TYPE

    EPT_TYPE_CUSTOMER

    EPT_TYPE_SIGMASTAR

    SS_RPMSG_CREATE_EPT_IOCTL

5.2.7. struct ss_rpmsg_endpoint_info

  • Description

    Attributes of the created RPMsg Endpoint.

  • Definition

    struct ss_rpmsg_endpoint_info {
            char name[32];
            __u32 src;
            __u32 dst;
            __u32 id;
            __u32 mode;
            __u16 target_id;
    };
    
  • Member

    Member name Description
    name The name of the RPMsg Endpoint.
    src The local address of the RPMsg Endpoint. If the remote end wants to send a message to this Endpoint, its dst address must fill in this value.
    dst The destination address of the RPMsg Endpoint message. When writing to the Endpoint, the message will be sent to this address.
    id The return value of ioctl, indicating the value of X in the RPMsg Endpoint node /dev/rpmsgX.
    mode The mode of the RPMsg bus where the Target is located, its value is fixed to: RPMSG_MODE_RISCV.
    target_id There is only one RISCV core, so it is fixed to 0.
  • Note

    None.

  • Related data type and interface

    EPT_TYPE_CUSTOMER

    EPT_TYPE_SIGMASTAR

    EPT_TYPE

    EPT_ADDR_MACRO

5.2.8. Struct ss_rpmsg_devices_info

  • Description

    Query conditions of connected devices.

  • Definition

    struct ss_rpmsg_devices_info {
            __u32 mode;
            __u32 count;
            __u64 buffer;
    };
    
  • Member

    Member name Description
    mode The mode of the RPMsg bus where the target is located. Its value is fixed to: RPMSG_MODE_RISCV.
    count As input, it indicates how many target_ids the buffer can store at most.
    As output, the return value indicates how many target_ids there are in the buffer.
    buffer Userspace buffer address, the kernel will fill in the target_id list of the currently connected RISCV.
  • Note

    None.

  • Related data type and interface

    RPMSG_MODE_RISCV

5.3. RPMSG FREERTOS API REFERENCE

This chaptor descript the api in FREERTOS.

API name Function
rpmsg_dualos_get_instance Get the RPMsg device instance pointer.
rpmsg_queue_create Create a queue to store messages.
rpmsg_lite_create_ept Create an RPMsg Endpoint.
rpmsg_queue_recv Get the received data from the queue.
rpmsg_lite_send Send data to the remote RPMsg Endpoint through the RPMsg Endpoint.
rpmsg_queue_destroy Destroy the queue.
rpmsg_lite_destroy_ept Destroy the RPMsg Endpoint.

5.3.1. Rpmsg_dualos_get_instance

  • Function

    Get the pointer (handle) of the RPMsg device instance under FreeRTOS. This handle is a required parameter for many other APIs (e.g. rpmsg_queue_create, rpsmg_lite_create_ept, etc.).

  • Syntax

    struct rpmsg_lite_instance *rpmsg_dualos_get_instance(int soc_id, int os_id);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    soc_id Fixed to EPT_SOC_DEFAULT. Input
    os_id Fixed to EPT_OS_LINUX. Input
  • Return value

    Return value description
    Non-NULL Indicates successful acquisition
    NULL Indicates that the RPMsg driver has not been initialized yet
  • Dependency

    • Header file: rpmsg_dualos.h

    • Library file

5.3.2. Rpmsg_queue_create

  • Function

    Create a queue to store messages. RPMsg driver will store the received and to-be-sent data in the queue specified when creating the endpoint.

  • Syntax

    rpmsg_queue_handle rpmsg_queue_create(struct rpmsg_lite_instance *rpmsg_lite_dev);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    rpmsg_lite_dev RPMsg device instance pointer. Input
  • Return value

    Return value description
    Non-RL_NULL Indicates successful creation
    RL_NULL Indicates failed creation
  • Dependency

    • Header file: rpmsg_dualos.h

    • Library file

5.3.3. Rpmsg_lite_create_ept

  • Function

    Create an endpoint for RPMsg communication.

  • Syntax

    struct rpmsg_lite_endpoint *rpmsg_lite_create_ept(struct rpmsg_lite_instance *rpmsg_lite_dev,
            unsigned long addr, rl_ept_rx_cb_t rx_cb, void *rx_cb_data);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    rpmsg_lite_dev RPMsg device instance pointer. Input
    addr The src address of endpoint. Input
    rx_cb After receiving the data packet sent to addr, the RPMsg driver will call this callback function for processing. Input
    data When calling the rx_cb function, the RPMsg driver will pass data as the value of the priv parameter to rx_cb. Input
  • Return value

    Return value description
    Non-RL_NULL Indicates successful creation
    RL_NULL Indicates failed creation
  • Dependency

    • Header file: rpmsg_dualos.h

    • Library file

5.3.4. Rpmsg_queue_recv

  • Function

    Get the received data from the queue.

  • Syntax

    int rpmsg_queue_recv(struct rpmsg_lite_instance *rpmsg_lite_dev, rpmsg_queue_handle q, unsigned long *src, char *data,
            int maxlen, int *len, unsigned long timeout);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    rpmsg_lite_dev RPMsg device instance pointer. Input
    q The handle of the queue. Input
    src Return the endpoint address of the data sender. Output
    data Buffer address, used to store data packets. Input
    maxlen Buffer size. Input
    len Return the size of the received data packet. Output
    timeout Timeout. Input
  • Return value

    Return value description
    RL_SUCCESS Indicates successful
    RL_ERR_PARAM Indicates incorrect parameters
    RL_ERR_BUF_SIZE Indicates that the data is larger than the buffer size
    RL_ERR_NO_BUFF Indicates that there is no data
  • Dependency

    • Header file: rpmsg_dualos.h

    • Library file

5.3.5. Rpmsg_lite_send

  • Function

    Send data to the remote RPMsg endpoint (specified address).

  • Syntax

    int rpmsg_lite_send(struct rpmsg_lite_instance *rpmsg_lite_dev, struct rpmsg_lite_endpoint *ept,
            unsigned long dst, char *data, unsigned long size, unsigned long timeout);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    rpmsg_lite_dev RPMsg device instance pointer. Input
    ept RPMsg Endpoint instance pointer. Input
    dst Address of the remote RPMsg Endpoint. Input
    data Buffer address of the data to be sent. Input
    size Size of the data to be sent. Input
    timeout Timeout. Input
  • Return value

    Return value description
    RL_SUCCESS Indicates successful
    RL_ERR_PARAM Indicates incorrect parameters
    RL_ERR_BUF_SIZE Indicates that the data size is larger than the maximum payload size allowed for a single RPMsg packet (i.e. 496 bytes)
    RL_ERR_NO_MEM Indicates that there is no space for sending data
  • Dependency

    • Header file: rpmsg_dualos.h

    • Library file

5.3.6. Rpmsg_queue_destroy

  • Function

    Destroy the queue created by rpmsg_queue_create().

  • Syntax

    int rpmsg_queue_destroy(struct rpmsg_lite_instance *rpmsg_lite_dev, rpmsg_queue_handle q);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    rpmsg_lite_dev RPMsg device instance pointer. Input
    q The handle of the queue to be destroyed. Input
  • Return value

    Return value description
    RL_SUCCESS Indicates successful
    RL_ERR_PARAM Indicates incorrect parameters
  • Dependency

    • Header file: rpmsg_dualos.h

    • Library file

5.3.7. Rpmsg_lite_destroy_ept

  • Function

    Destroy the RPMsg Endpoint created by rpmsg_lite_create_ept().

  • Syntax

    int rpmsg_lite_destroy_ept(struct rpmsg_lite_instance *rpmsg_lite_dev, struct rpmsg_lite_endpoint *rl_ept);
    
  • Parameter

    Parameter name Parameter meaning Input/Output
    rpmsg_lite_dev RPMsg device instance pointer. Input
    rl_ept The RPMsg Endpoint pointer to be destroyed. Input
  • Return value

    Return value description
    RL_SUCCESS Indicates successful
    RL_ERR_PARAM Indicates incorrect parameters
  • Dependency

    • Header file: rpmsg_dualos.h

    • Library file

6. FAQ

Logs from SSU938X and SSD238X Please note that the logs may vary depending on the specific chip, but the problem-solving approach remains consistent.

Q: Kernel reports "Failed to get address of rpmsg share area" and the /dev/rpmsgX node creation fails with the error "rpmsg rpmsg0: Remote side(0x5,0x0) of demo0 is gone!"

A: This issue typically occurs when the RPMsg handshake between the ARM and RISC-V sides is not completed properly, preventing normal communication. To troubleshoot, follow these steps:

Verify if RISC-V is running correctly : Connect to the RISC-V side via a serial port to confirm its status. If it's not running, check if the RISC-V firmware failed to load. Example : The red boxed print indicates the RISC-V firmware wasn't loaded.

Ensure that the RISC-V load address matches the storage address and that the firmware isn't corrupted. If RISC-V is running , check the application initialization sequence. Ensure that the application isn't dying before the RPMsg driver initializes. Also, verify that no high-priority tasks are occupying excessive time or that excessive logging hasn't slowed down the initialization process.

Q:The /dev/rpmsgX node is successfully created on the ARM side, but communication fails.

A: This could be due to a version mismatch between the RISC-V and the kernel.

If there's a version mismatch, you may see error messages indicating incompatibility. Ensure that the RISC-V and Linux SDK versions are consistent.

Q:RPMsg communication experiences increasing delays over time.

A: This is typically caused by mismatched send-receive intervals between the ARM and RISC-V sides. Check if the ARM side has added unnecessary sleep operations during sending or receiving.

Q:The /dev/rpmsgX communication node is repeatedly destroyed and re-created, leading to occasional failures in node creation.

A: This usually happens when the time interval between node creation and destruction is too short. The sequence of operations might have changed unintentionally: the application layer might be creating a node before destroying it instead of the intended order.

To fix this, add an access check after creating the rpmsg0 node to ensure it exists before opening it. Similarly, add an access check after destroying the rpmsg0 node to confirm it no longer exists before attempting to re-create it.

Q:Kernel prints "rpmsg_dualos virtio0.rpmsg_dualos.-1.33554480: timeout waiting for a tx buffer."

A: This occurs when the kernel's RPMsg tx buffer limit is reached, and the RISC-V side hasn't received the data promptly.

This could be due to high-priority, time-consuming tasks on the RISC-V side occupying the CPU or the RISC-V system hanging unexpectedly.