rtos侧
RPMessageParams_init(¶ms);
params.requestedEndpt = ENDPOINT;
params.buf = buf;
params.bufSize = bufSize;
handle = RPMessage_create(¶ms, &myEndPt);
RPMessage_announce(RPMESSAGE_ALL, myEndPt, "rpmsg_chrdev"); //向所有处理器或仅向一个处理器宣布端点的可用性
while(TRUE)
{
RPMessage_recv(handle, (Ptr)msg, &msg_len, &remoteEndPt, &remoteProcId,
IPC_RPMESSAGE_TIMEOUT_FOREVER);
...
/* do something with message */
service_func(msg, msg_len, remoteEndPt, remoteProcId, resp, &resp_len);
...
RPMessage_send(handle, remoteProcId, remoteEndPt, myEndPt, resp, resp_len);
}
参考下面code
//linux侧
系统默认初始化代码在rtos-sdk/vision_apps/utils/ipc/src/app_ipc_linux_rpmsg_char.c这里
使用方法见rtos-sdk/vision_apps/utils/ipc/src/app_ipc_linux_rpmsg_char.c
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/eventfd.h>
#include <ti_rpmsg_char.h>
#include <utils/ipc/src/app_ipc_linux_priv.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static uint32_t map_vision_apps_cpu_id_to_rpmsg_char_cpu_id(uint32_t cpu_id)
{
uint32_t rpmsg_char_id = RPROC_ID_MAX;
if (APP_IPC_CPU_MCU1_0 == cpu_id)
{
rpmsg_char_id = R5F_MCU0_0;
}
else if (APP_IPC_CPU_MCU1_1 == cpu_id)
{
rpmsg_char_id = R5F_MCU0_1;
}
else if (APP_IPC_CPU_MCU2_0 == cpu_id)
{
rpmsg_char_id = R5F_MAIN0_0;
}
else if (APP_IPC_CPU_MCU2_1 == cpu_id)
{
rpmsg_char_id = R5F_MAIN0_1;
}
else if (APP_IPC_CPU_MCU3_0 == cpu_id)
{
rpmsg_char_id = R5F_MAIN1_0;
}
else if (APP_IPC_CPU_MCU3_1 == cpu_id)
{
rpmsg_char_id = R5F_MAIN1_1;
}
#if defined (SOC_J721E)
else if (APP_IPC_CPU_C6x_1 == cpu_id)
{
rpmsg_char_id = DSP_C66_0;
}
else if (APP_IPC_CPU_C6x_2 == cpu_id)
{
rpmsg_char_id = DSP_C66_1;
}
#endif
else if (APP_IPC_CPU_C7x_1 == cpu_id)
{
rpmsg_char_id = DSP_C71_0;
}
#if 0 // TODO: Enable this once we have a Linux FS
#if defined (SOC_J721S2)
else if (APP_IPC_CPU_C7x_2 == cpu_id)
{
rpmsg_char_id = DSP_C71_1;
}
#endif
#endif
return rpmsg_char_id;
}
static void appIpcRpmsgRxHandler(uint32_t app_cpu_id, uint32_t payload)
{
app_ipc_obj_t *obj = &g_app_ipc_obj;
if(app_cpu_id<APP_IPC_CPU_MAX)
{
#ifdef APP_IPC_DEBUG
appLogPrintf("IPC: RX: %s -> %s (port %d) msg = 0x%08x\n",
appIpcGetCpuName(app_cpu_id),
appIpcGetCpuName(appIpcGetSelfCpuId()),
(uint32_t)obj->local_endpt[app_cpu_id],
payload);
#endif
if((payload & 0xFFFF0000) == 0xDEAD0000)
{
/* echo message dont send to handler */
printf("IPC: RX: %s -> %s (port %d) msg = 0x%08x\n",
appIpcGetCpuName(app_cpu_id),
appIpcGetCpuName(appIpcGetSelfCpuId()),
(uint32_t)obj->prm.tiovx_rpmsg_port_id,
payload);
}
else
{
if(obj->ipc_notify_handler)
{
obj->ipc_notify_handler(app_cpu_id, payload);
}
}
}
}
void *appIpcRpmsgRxTaskMain(void *arg)
{
app_ipc_obj_t *obj = &g_app_ipc_obj;
uint32_t payload;
uint32_t maxfd;
uint32_t nfds;
int32_t status;
fd_set rfds;
uint32_t i;
uint32_t done;
done = 0;
while(!done)
{
maxfd = 0;
status = 0;
FD_ZERO(&rfds);
/* Initialize rx fds to wait on messages */
for(i = 0; i< APP_IPC_CPU_MAX; i++)
{
if(appIpcIsCpuEnabled(i) && i != appIpcGetSelfCpuId())
{
/* same file handle used for RX and TX */
maxfd = MAX(maxfd, obj->tx_fds[i]);
FD_SET(obj->tx_fds[i], &rfds);
}
}
/* add fd to unblock from select and break from loop on exit */
FD_SET(obj->unblockfd, &rfds);
/* Add one to last fd created, this is mandated by select() */
nfds = MAX(maxfd, obj->unblockfd) + 1;
status = select(nfds, &rfds, NULL, NULL, NULL);
if (status)
{
if (FD_ISSET(obj->unblockfd, &rfds))
{
/*
* Event was signalled to break the loop
*
* This is typically done during a shutdown sequence, where
* the intention of the client would be to ignore (i.e. not fetch)
* any pending messages in the transport's queue.
* Thus, we shall not check for nor return any messages.
*/
done = 1;
}
else
{
/* Process all messages received on different Rx sockets */
for(i = 0; i< APP_IPC_CPU_MAX; i++)
{
if( appIpcIsCpuEnabled(i)
&& i != appIpcGetSelfCpuId()
&& FD_ISSET(obj->tx_fds[i], &rfds)
)
{
/* same file handle used for RX and TX */
status = read(
obj->tx_fds[i],
&payload, sizeof(uint32_t));
if(status > 0)
{
appIpcRpmsgRxHandler(
i,
payload);
}
}
}
}
}
} /* while(! done) */
return NULL;
}
int32_t appIpcSendNotifyPort(uint32_t dest_cpu_id, uint32_t payload, uint32_t port_id)
{
int32_t status = -1;
app_ipc_obj_t *obj = &g_app_ipc_obj;
/* NOTE: port_id is unsed in this function */
if( (dest_cpu_id<APP_IPC_CPU_MAX) && (obj->tx_fds[dest_cpu_id] > 0))
{
#ifdef APP_IPC_DEBUG
appLogPrintf("IPC: TX: %s -> %s (port %d) msg = 0x%08x\n",
appIpcGetCpuName(appIpcGetSelfCpuId()),
appIpcGetCpuName(dest_cpu_id),
(uint32_t)port_id,
payload);
#endif
status = write(obj->tx_fds[dest_cpu_id], &payload, sizeof(payload));
if(status < 0 || status != sizeof(payload))
{
appLogPrintf("IPC: TX: FAILED: %s -> %s (port %d) msg = 0x%08x\n",
appIpcGetCpuName(appIpcGetSelfCpuId()),
appIpcGetCpuName(dest_cpu_id),
(uint32_t)port_id,
payload);
}
else
{
status = 0;
}
}
return status;
}
int32_t appIpcSendNotify(uint32_t dest_cpu_id, uint32_t payload)
{
int32_t status = -1;
app_ipc_obj_t *obj = &g_app_ipc_obj;
if( (dest_cpu_id<APP_IPC_CPU_MAX) && (obj->tx_fds[dest_cpu_id] > 0))
{
status = appIpcSendNotifyPort(dest_cpu_id, payload,
(uint32_t)obj->prm.tiovx_rpmsg_port_id);
}
return status;
}
int32_t appIpcCreateTxCh(uint32_t remote_app_cpu_id, uint32_t remote_endpt, uint32_t *local_endpt, rpmsg_char_dev_t **rcdev)
{
int fd = -1;
rpmsg_char_dev_t rcdev_local;
char eptdev_name[32] = { 0 };
uint32_t rproc_id;
rproc_id = map_vision_apps_cpu_id_to_rpmsg_char_cpu_id(remote_app_cpu_id);
sprintf(eptdev_name, "rpmsg-char-%d-%d", rproc_id, getpid());
*rcdev = rpmsg_char_open(rproc_id,
NULL,
remote_endpt,
eptdev_name,
0
);
if (NULL != *rcdev)
{
rcdev_local = **rcdev;
*local_endpt = rcdev_local.endpt;
fd = rcdev_local.fd;
}
return fd;
}
int32_t appIpcDeleteCh(rpmsg_char_dev_t *rcdev)
{
rpmsg_char_close(rcdev);
return 0;
}
static void appIpcUnblockRpmsgTask(app_ipc_obj_t *obj)
{
uint64_t buf = 1;
/* Write 8 bytes to shutdown */
write(obj->unblockfd, &buf, sizeof(buf));
}
int32_t appIpcCreateRpmsgRxTask(app_ipc_obj_t *obj)
{
pthread_attr_t thread_attr;
int32_t status = 0;
obj->unblockfd = eventfd(0, 0);
if(obj->unblockfd < 0)
{
status = -1;
printf("IPC: ERROR: Unable to create unblock event !!!\n");
}
if(status==0)
{
status |= pthread_attr_init(&thread_attr);
if(status!=0)
{
printf("IPC: ERROR: Unable to set thread attr !!!\n");
}
if(status==0)
{
status |= pthread_create(&obj->task, &thread_attr, (void*)appIpcRpmsgRxTaskMain, obj);
}
pthread_attr_destroy(&thread_attr);
}
if(status!=0)
{
printf("IPC: ERROR: Unable to create RX thread !!!\n");
}
return status;
}
int32_t appIpcDeleteRpmsgRxTask(app_ipc_obj_t *obj)
{
void *task_status;
appIpcUnblockRpmsgTask(obj);
pthread_join(obj->task, &task_status);
close(obj->unblockfd);
return 0;
}