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
-
Related topic
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
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
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
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
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
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
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
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.