drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* drivers/rpmsg/rpmsg_router_hub.c
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright ownership. The
|
|
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
|
|
* "License"); you may not use this file except in compliance with the
|
|
|
|
* License. You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
|
|
|
|
#include <debug.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
|
|
|
#include <nuttx/mutex.h>
|
|
|
|
#include <nuttx/kmalloc.h>
|
|
|
|
#include <rpmsg/rpmsg_internal.h>
|
|
|
|
|
|
|
|
#include "rpmsg_router.h"
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Rpmsg-router Model:
|
|
|
|
*
|
|
|
|
* +------+ +------+ +------+
|
|
|
|
* | edge |<----->| hub |<----->| edge |
|
|
|
|
* +------+ +------+ +------+
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* edge CPUs (edge) are physically linked to the central router cpu (hub),
|
|
|
|
* edge CPUs' communication reply on hub cpu message forwarding.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Types
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
struct rpmsg_router_hub_s
|
|
|
|
{
|
|
|
|
struct rpmsg_endpoint ept[2];
|
|
|
|
char cpuname[2][RPMSG_ROUTER_CPUNAME_LEN];
|
|
|
|
mutex_t lock;
|
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_hub_cb
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This is the callback function for router core.
|
|
|
|
* It will receive data from source edge core by ept(r:cpu:name), and find
|
|
|
|
* dest edge core communicating with it, send data to dest edge core.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - rpmsg_endpoint for communicating with edge core (r:dst_cpu:name)
|
|
|
|
* data - received data
|
|
|
|
* len - received data length
|
|
|
|
* src - source address
|
|
|
|
* priv - save dest edge core rpmsg_endpoint (r:src_cpu:name)
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* Returns number of bytes it has sent or negative error value on failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int rpmsg_router_hub_cb(FAR struct rpmsg_endpoint *ept,
|
|
|
|
FAR void *data, size_t len,
|
|
|
|
uint32_t src, FAR void *priv)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_endpoint *dst_ept = priv;
|
|
|
|
|
|
|
|
/* Retransmit data to dest edge core */
|
|
|
|
|
|
|
|
if (!dst_ept)
|
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rpmsg_send(dst_ept, data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_hub_unbind
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This is the unbind callback function for router core.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - rpmsg_endpoint for communicating with edge core (r:cpu:name)
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_hub_unbind(FAR struct rpmsg_endpoint *ept)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_endpoint *dst_ept = ept->priv;
|
|
|
|
|
|
|
|
/* Destroy dest edge ept firstly */
|
|
|
|
|
|
|
|
if (dst_ept)
|
|
|
|
{
|
|
|
|
rpmsg_destroy_ept(dst_ept);
|
|
|
|
kmm_free(dst_ept);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Destroy source edge ept */
|
|
|
|
|
|
|
|
rpmsg_destroy_ept(ept);
|
|
|
|
kmm_free(ept);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_hub_bound
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This is the bound callback function for router core.
|
|
|
|
* It will create endpoint to source edge after dest edge
|
|
|
|
* core is bound.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - rpmsg_endpoint for communicating with edge core (r:cpu:name)
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_hub_bound(FAR struct rpmsg_endpoint *ept)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_endpoint *src_ept = ept->priv;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Create endpoint (r:dst_cpu:name) and send ACK to source edge core */
|
|
|
|
|
|
|
|
ret = rpmsg_create_ept(src_ept, src_ept->rdev, src_ept->name,
|
|
|
|
RPMSG_ADDR_ANY, src_ept->dest_addr,
|
|
|
|
rpmsg_router_hub_cb, rpmsg_router_hub_unbind);
|
|
|
|
DEBUGASSERT(ret == RPMSG_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_hub_match
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to match the router core device.
|
|
|
|
* rpmsg_router_hub_bind will be called if the device is matched.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* rdev - real rpmsg device
|
|
|
|
* priv - rpmsg router hub for router core
|
|
|
|
* name - endpoint name (r:dst_cpu:name)
|
|
|
|
* dest - destination address
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* true on success; false on failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static bool rpmsg_router_hub_match(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *priv, FAR const char *name,
|
|
|
|
uint32_t dest)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_hub_s *hub = priv;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (strncmp(name, RPMSG_ROUTER_NAME_PREFIX, RPMSG_ROUTER_NAME_PREFIX_LEN))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Must match both source edge CPU and dest edge CPU simultaneously */
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(rpmsg_get_cpuname(rdev), hub->cpuname[i]))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strncmp(name + RPMSG_ROUTER_NAME_PREFIX_LEN,
|
|
|
|
hub->cpuname[1 - i], strlen(hub->cpuname[1 - i])))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return i < 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_hub_bind
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to bind the router core device.
|
|
|
|
* It will try to create endpoint (r:src_cpu:name) to another dest cpu.
|
|
|
|
* The source endpoint information will be saved in the private field of
|
|
|
|
* the dest endpoint.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* rdev - real rpmsg device
|
|
|
|
* priv - rpmsg router hub for router core
|
|
|
|
* name - source edge core endpoint name (r:dst_cpu:name)
|
|
|
|
* dest - destination address
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_hub_bind(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *priv, FAR const char *name,
|
|
|
|
uint32_t dest)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_hub_s *hub = priv;
|
|
|
|
FAR struct rpmsg_endpoint *src_ept;
|
|
|
|
FAR struct rpmsg_endpoint *dst_ept;
|
|
|
|
FAR struct rpmsg_device *dst_rdev;
|
|
|
|
char dst_name[RPMSG_NAME_SIZE];
|
|
|
|
int ret;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
nxmutex_lock(&hub->lock);
|
|
|
|
metal_mutex_acquire(&rdev->lock);
|
|
|
|
if (rpmsg_get_endpoint(rdev, name, RPMSG_ADDR_ANY, dest))
|
|
|
|
{
|
|
|
|
metal_mutex_release(&rdev->lock);
|
|
|
|
nxmutex_unlock(&hub->lock);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
metal_mutex_release(&rdev->lock);
|
|
|
|
|
|
|
|
/* Try to create endpoint name(r:src_cpu:name) of another dest cpu */
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (!strcmp(hub->cpuname[i], rpmsg_get_cpuname(rdev)))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUGASSERT(i < 2);
|
|
|
|
|
|
|
|
dst_rdev = hub->ept[1 - i].rdev;
|
|
|
|
snprintf(dst_name, RPMSG_NAME_SIZE,
|
|
|
|
RPMSG_ROUTER_NAME_PREFIX"%s%s", hub->cpuname[i],
|
|
|
|
name + RPMSG_ROUTER_NAME_PREFIX_LEN +
|
|
|
|
strlen(hub->cpuname[1 - i]));
|
|
|
|
|
|
|
|
src_ept = kmm_zalloc(sizeof(*src_ept));
|
|
|
|
dst_ept = kmm_zalloc(sizeof(*dst_ept));
|
|
|
|
|
|
|
|
DEBUGASSERT(src_ept && dst_ept);
|
|
|
|
|
|
|
|
/* Save information for the ept(r:dst_cpu:name) of the source cpu */
|
|
|
|
|
|
|
|
src_ept->priv = dst_ept;
|
|
|
|
src_ept->rdev = rdev;
|
|
|
|
src_ept->dest_addr = dest;
|
|
|
|
strlcpy(src_ept->name, name, sizeof(src_ept->name));
|
|
|
|
|
|
|
|
/* Create endpoint (r:src_cpu:name) to another dest cpu */
|
|
|
|
|
|
|
|
dst_ept->priv = src_ept;
|
|
|
|
dst_ept->ns_bound_cb = rpmsg_router_hub_bound;
|
|
|
|
ret = rpmsg_create_ept(dst_ept, dst_rdev, dst_name,
|
|
|
|
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
|
|
|
|
rpmsg_router_hub_cb,
|
|
|
|
rpmsg_router_hub_unbind);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
kmm_free(dst_ept);
|
|
|
|
kmm_free(src_ept);
|
|
|
|
}
|
|
|
|
|
|
|
|
nxmutex_unlock(&hub->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_bound
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to send tx/rx buffer size
|
|
|
|
* when both cores are ready
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ept - rpmsg endpoint for communicating with edge core
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_bound(FAR struct rpmsg_endpoint *ept)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_hub_s *hub = ept->priv;
|
|
|
|
struct rpmsg_router_s msg;
|
|
|
|
int ret;
|
2024-06-21 14:50:42 +02:00
|
|
|
int i;
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
|
|
|
|
if (!is_rpmsg_ept_ready(&hub->ept[0]) ||
|
|
|
|
!is_rpmsg_ept_ready(&hub->ept[1]))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-06-21 14:50:42 +02:00
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
2024-07-02 12:31:52 +02:00
|
|
|
msg.cmd = RPMSG_ROUTER_CREATE;
|
2024-06-21 14:50:42 +02:00
|
|
|
msg.tx_len = MIN(rpmsg_get_rx_buffer_size(hub->ept[i].rdev),
|
|
|
|
rpmsg_get_tx_buffer_size(hub->ept[1 - i].rdev));
|
|
|
|
msg.rx_len = MIN(rpmsg_get_tx_buffer_size(hub->ept[i].rdev),
|
|
|
|
rpmsg_get_rx_buffer_size(hub->ept[1 - i].rdev));
|
2024-06-24 11:10:12 +02:00
|
|
|
strlcpy(msg.cpuname, hub->cpuname[i], sizeof(msg.cpuname));
|
2024-06-21 14:50:42 +02:00
|
|
|
ret = rpmsg_send(&hub->ept[i], &msg, sizeof(msg));
|
|
|
|
DEBUGASSERT(ret >= 0);
|
|
|
|
}
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_cb
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static int rpmsg_router_cb(FAR struct rpmsg_endpoint *ept, FAR void *data,
|
|
|
|
size_t len, uint32_t src, FAR void *priv)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_created
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to create endpoint to edge core,
|
|
|
|
* for synchronizing ready messages.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* rdev - real rpmsg device
|
|
|
|
* priv - rpmsg router hub
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_created(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *priv)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_hub_s *hub = priv;
|
|
|
|
char name[RPMSG_NAME_SIZE];
|
|
|
|
int ret;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(rpmsg_get_cpuname(rdev), hub->cpuname[i]))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
hub->ept[i].priv = hub;
|
|
|
|
hub->ept[i].ns_bound_cb = rpmsg_router_bound;
|
|
|
|
snprintf(name, RPMSG_NAME_SIZE, RPMSG_ROUTER_NAME"%s",
|
|
|
|
hub->cpuname[1 - i]);
|
|
|
|
|
|
|
|
ret = rpmsg_create_ept(&hub->ept[i], rdev, name,
|
|
|
|
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
|
|
|
|
rpmsg_router_cb, NULL);
|
|
|
|
DEBUGASSERT(ret == RPMSG_SUCCESS);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_destroy
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to destroy the rpmsg router hub.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* priv - rpmsg router hub
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void rpmsg_router_destroy(FAR struct rpmsg_device *rdev,
|
|
|
|
FAR void *priv)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_hub_s *hub = priv;
|
2024-07-02 12:31:52 +02:00
|
|
|
struct rpmsg_router_s msg;
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(rpmsg_get_cpuname(rdev), hub->cpuname[i]))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmsg_destroy_ept(&hub->ept[i]);
|
2024-07-02 12:31:52 +02:00
|
|
|
|
|
|
|
/* Notify the other edge core to destroy router device */
|
|
|
|
|
|
|
|
msg.cmd = RPMSG_ROUTER_DESTROY;
|
|
|
|
rpmsg_send(&hub->ept[1 - i], &msg, sizeof(msg));
|
drivers/rpmsg: add rpmsg router support
Rpmsg Router is new rpmsg transport layer, it can router the rpmsg
messages to a cpu that not directly connected with local cpu by Rpmsg,
For the rpmsg services, it is as if there is a real Rpmsg Channel between
the local cpu and the remote cpu.
For examples, there are three cpus: ap, cp and audio.
ap and cp, ap and audio has share memory and be connected by Rpmsg VirtIO,
so ap and cp, ap and audio can communicate with each other by Rpmsg, but
cp can not communicate with audio direclty.
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
With rpmsg router, the cp can communicate with audip by Rpmsg dereclty because
the router in ap will forward the rpmsg message from cp/audio to audio/cp, like
this:
+<----- rpmsg router --> hub <-- rpmsg router ------>+
| | |
[cp] <-- rpmsg virtio --> [ap] <-- rpmsg virtio --> [audio]
Signed-off-by: yintao <yintao@xiaomi.com>
2024-04-14 07:17:05 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: rpmsg_router_hub_init
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* This function is used to initialize the rpmsg router hub.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* edge0 - edge cpu name
|
|
|
|
* edge1 - edge cpu name
|
|
|
|
*
|
|
|
|
* Returned Values:
|
|
|
|
* OK on success; A negated errno value is returned on any failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int rpmsg_router_hub_init(FAR const char *edge0,
|
|
|
|
FAR const char *edge1)
|
|
|
|
{
|
|
|
|
FAR struct rpmsg_router_hub_s *hub;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!edge0 || !edge1)
|
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
hub = kmm_zalloc(sizeof(*hub));
|
|
|
|
if (!hub)
|
|
|
|
{
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
nxmutex_init(&hub->lock);
|
|
|
|
strlcpy(hub->cpuname[0], edge0, sizeof(hub->cpuname[0]));
|
|
|
|
strlcpy(hub->cpuname[1], edge1, sizeof(hub->cpuname[1]));
|
|
|
|
|
|
|
|
/* Register callback for retranmitting data between edge cores */
|
|
|
|
|
|
|
|
ret = rpmsg_register_callback(hub,
|
|
|
|
rpmsg_router_created,
|
|
|
|
rpmsg_router_destroy,
|
|
|
|
rpmsg_router_hub_match,
|
|
|
|
rpmsg_router_hub_bind);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
rpmsgerr("Register rpmsg callback failed: %d\n", ret);
|
|
|
|
nxmutex_destroy(&hub->lock);
|
|
|
|
kmm_free(hub);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|