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>
This commit is contained in:
parent
a662c7aab3
commit
7c933874e8
@ -45,6 +45,10 @@ if(CONFIG_RPMSG)
|
||||
list(APPEND SRCS rpmsg_virtio_ivshmem.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_RPMSG_ROUTER)
|
||||
list(APPEND SRCS rpmsg_router_hub.c rpmsg_router_edge.c)
|
||||
endif()
|
||||
|
||||
target_include_directories(drivers PRIVATE ${NUTTX_DIR}/openamp/open-amp/lib)
|
||||
target_sources(drivers PRIVATE ${SRCS})
|
||||
endif()
|
||||
|
@ -23,6 +23,13 @@ config RPMSG_PING
|
||||
|
||||
endif # RPMSG
|
||||
|
||||
config RPMSG_ROUTER
|
||||
bool "rpmsg router support"
|
||||
default n
|
||||
---help---
|
||||
Rpmsg router driver for enabling communication
|
||||
without physical channels.
|
||||
|
||||
config RPMSG_PORT
|
||||
bool
|
||||
default n
|
||||
|
@ -28,6 +28,10 @@ ifeq ($(CONFIG_RPMSG_PING),y)
|
||||
CSRCS += rpmsg_ping.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RPMSG_ROUTER),y)
|
||||
CSRCS += rpmsg_router_hub.c rpmsg_router_edge.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RPMSG_PORT),y)
|
||||
CSRCS += rpmsg_port.c
|
||||
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)openamp$(DELIM)open-amp$(DELIM)lib
|
||||
|
53
drivers/rpmsg/rpmsg_router.h
Normal file
53
drivers/rpmsg/rpmsg_router.h
Normal file
@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
* drivers/rpmsg/rpmsg_router.h
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __DRIVERS_RPMSG_RPMSG_ROUTER_H
|
||||
#define __DRIVERS_RPMSG_RPMSG_ROUTER_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/rpmsg/rpmsg.h>
|
||||
|
||||
#ifdef CONFIG_RPMSG_ROUTER
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define RPMSG_ROUTER_NAME "router:"
|
||||
#define RPMSG_ROUTER_NAME_LEN 7
|
||||
#define RPMSG_ROUTER_NAME_PREFIX "r:"
|
||||
#define RPMSG_ROUTER_NAME_PREFIX_LEN 2
|
||||
#define RPMSG_ROUTER_CPUNAME_LEN 8
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
begin_packed_struct struct rpmsg_router_s
|
||||
{
|
||||
uint32_t tx_len;
|
||||
uint32_t rx_len;
|
||||
} end_packed_struct;
|
||||
|
||||
#endif /* CONFIG_RPMSG_ROUTER */
|
||||
#endif /* __DRIVERS_RPMSG_RPMSG_ROUTER_H */
|
722
drivers/rpmsg/rpmsg_router_edge.c
Normal file
722
drivers/rpmsg/rpmsg_router_edge.c
Normal file
@ -0,0 +1,722 @@
|
||||
/****************************************************************************
|
||||
* drivers/rpmsg/rpmsg_router_edge.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 <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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define rpmsg_router_edge_from_rdev(d) \
|
||||
metal_container_of(d, struct rpmsg_router_edge_s, rdev)
|
||||
|
||||
#define RPMSG_ROUTER_USER_NAME_SIZE \
|
||||
(RPMSG_NAME_SIZE - RPMSG_ROUTER_NAME_PREFIX_LEN - RPMSG_ROUTER_CPUNAME_LEN)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct rpmsg_router_edge_s
|
||||
{
|
||||
struct rpmsg_s rpmsg;
|
||||
struct rpmsg_device rdev;
|
||||
struct rpmsg_device *hubdev;
|
||||
char remotecpu[RPMSG_ROUTER_CPUNAME_LEN];
|
||||
|
||||
/* Tx/Rx buffer size */
|
||||
|
||||
uint32_t tx_len;
|
||||
uint32_t rx_len;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static FAR const char *
|
||||
rpmsg_router_edge_get_cpuname(FAR struct rpmsg_s *rpmsg);
|
||||
static int rpmsg_router_edge_get_tx_buffer_size(FAR struct rpmsg_s *rpmsg);
|
||||
static int rpmsg_router_edge_get_rx_buffer_size(FAR struct rpmsg_s *rpmsg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct rpmsg_ops_s g_rpmsg_router_edge_ops =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
rpmsg_router_edge_get_cpuname,
|
||||
rpmsg_router_edge_get_tx_buffer_size,
|
||||
rpmsg_router_edge_get_rx_buffer_size,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_get_cpuname
|
||||
****************************************************************************/
|
||||
|
||||
static FAR const char *
|
||||
rpmsg_router_edge_get_cpuname(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_router_edge_s *edge =
|
||||
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
||||
|
||||
return edge->remotecpu;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_get_tx_buffer_size
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsg_router_edge_get_tx_buffer_size(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_router_edge_s *edge =
|
||||
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
||||
|
||||
return edge->tx_len;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_get_rx_buffer_size
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsg_router_edge_get_rx_buffer_size(FAR struct rpmsg_s *rpmsg)
|
||||
{
|
||||
FAR struct rpmsg_router_edge_s *edge =
|
||||
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
||||
|
||||
return edge->rx_len;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_get_tx_payload_buffer
|
||||
****************************************************************************/
|
||||
|
||||
static FAR void *
|
||||
rpmsg_router_edge_get_tx_payload_buffer(FAR struct rpmsg_device *rdev,
|
||||
FAR uint32_t *len, int wait)
|
||||
{
|
||||
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
||||
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
||||
FAR void *buf;
|
||||
|
||||
if (!hubdev->ops.get_tx_payload_buffer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = hubdev->ops.get_tx_payload_buffer(hubdev, len, wait);
|
||||
*len = edge->tx_len - (rpmsg_get_tx_buffer_size(rdev) - *len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_hold_rx_buffer
|
||||
****************************************************************************/
|
||||
|
||||
static void rpmsg_router_edge_hold_rx_buffer(FAR struct rpmsg_device *rdev,
|
||||
FAR void *rxbuf)
|
||||
{
|
||||
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
||||
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
||||
|
||||
if (!hubdev->ops.hold_rx_buffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hubdev->ops.hold_rx_buffer(hubdev, rxbuf);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_release_rx_buffer
|
||||
****************************************************************************/
|
||||
|
||||
static void
|
||||
rpmsg_router_edge_release_rx_buffer(FAR struct rpmsg_device *rdev,
|
||||
FAR void *rxbuf)
|
||||
{
|
||||
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
||||
struct rpmsg_device *hubdev = edge->hubdev;
|
||||
|
||||
if (!hubdev->ops.release_rx_buffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hubdev->ops.release_rx_buffer(hubdev, rxbuf);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_release_tx_buffer
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsg_router_edge_release_tx_buffer(FAR struct rpmsg_device *rdev,
|
||||
FAR void *txbuf)
|
||||
{
|
||||
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
||||
struct rpmsg_device *hubdev = edge->hubdev;
|
||||
|
||||
if (!hubdev->ops.release_tx_buffer)
|
||||
{
|
||||
return RPMSG_ERR_PERM;
|
||||
}
|
||||
|
||||
return hubdev->ops.release_tx_buffer(hubdev, txbuf);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_send_nocopy
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsg_router_edge_send_nocopy(FAR struct rpmsg_device *rdev,
|
||||
uint32_t src, uint32_t dst,
|
||||
FAR const void *data, int len)
|
||||
{
|
||||
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
||||
struct rpmsg_device *hubdev = edge->hubdev;
|
||||
|
||||
if (!hubdev->ops.send_offchannel_nocopy)
|
||||
{
|
||||
return RPMSG_ERR_PARAM;
|
||||
}
|
||||
|
||||
return hubdev->ops.send_offchannel_nocopy(hubdev, src, dst, data, len);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_cb
|
||||
*
|
||||
* Description:
|
||||
* This is the callback function for edge core.
|
||||
* It will receive data from real rpmsg channel by ept(r:cpu:name),
|
||||
* and find the corresponding user ept, then processing data through
|
||||
* the user ept callback.
|
||||
*
|
||||
* Parameters:
|
||||
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
||||
* data - received data
|
||||
* len - received data length
|
||||
* src - source address
|
||||
* priv - save user rpmsg_endpoint generally
|
||||
*
|
||||
* Returned Values:
|
||||
* 0 on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsg_router_edge_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsg_endpoint *usr_ept = priv;
|
||||
|
||||
if (!usr_ept)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Processing data through the user ept callback */
|
||||
|
||||
return usr_ept->cb(usr_ept, data, len, src, usr_ept->priv);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_bound
|
||||
*
|
||||
* Description:
|
||||
* This is the callback function for edge core.
|
||||
* It will be called when the edge core is bound to the router core
|
||||
* by r:cpu:name, save the destination address of the edge core, and
|
||||
* call the bound function of the user endpoint.
|
||||
*
|
||||
* Parameters:
|
||||
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void rpmsg_router_edge_bound(FAR struct rpmsg_endpoint *ept)
|
||||
{
|
||||
FAR struct rpmsg_endpoint *usr_ept = ept->priv;
|
||||
|
||||
if (!usr_ept)
|
||||
{
|
||||
rpmsgerr("Try to get user ept failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
usr_ept->dest_addr = ept->dest_addr;
|
||||
if (usr_ept->ns_bound_cb)
|
||||
{
|
||||
usr_ept->ns_bound_cb(usr_ept);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_unbind
|
||||
*
|
||||
* Description:
|
||||
* This is the unbind callback function for edge core.
|
||||
*
|
||||
* Parameters:
|
||||
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void rpmsg_router_edge_unbind(FAR struct rpmsg_endpoint *ept)
|
||||
{
|
||||
FAR struct rpmsg_endpoint *usr_ept = ept->priv;
|
||||
|
||||
if (!usr_ept)
|
||||
{
|
||||
rpmsgerr("Try to get user ept failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (usr_ept->ns_unbind_cb)
|
||||
{
|
||||
usr_ept->ns_unbind_cb(usr_ept);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_release
|
||||
****************************************************************************/
|
||||
|
||||
static void rpmsg_router_edge_release(FAR struct rpmsg_endpoint *ept)
|
||||
{
|
||||
kmm_free(ept);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_send_offchannel_raw
|
||||
*
|
||||
* Description:
|
||||
* This function sends normal rpmsg message or ns message to remote device.
|
||||
* If the destination address is RPMSG_NS_EPT_ADDR, it will create a new
|
||||
* endpoint(r:cpu:name) for real communication, and save the user endpoint
|
||||
* information in the private field of the new endpoint.
|
||||
*
|
||||
* Parameters:
|
||||
* rdev - rpmsg_device for router core
|
||||
* src - source address
|
||||
* dst - destination address
|
||||
* data - data to send
|
||||
* len - data length
|
||||
* wait - boolean, wait or not for buffer to become available
|
||||
*
|
||||
* Returned Values:
|
||||
* size of data sent or negative value for failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int
|
||||
rpmsg_router_edge_send_offchannel_raw(FAR struct rpmsg_device *rdev,
|
||||
uint32_t src, uint32_t dst,
|
||||
FAR const void *data,
|
||||
int len, int wait)
|
||||
{
|
||||
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
||||
FAR struct rpmsg_ns_msg *ns_msg = (FAR struct rpmsg_ns_msg *)data;
|
||||
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
||||
FAR struct rpmsg_endpoint *usr_ept;
|
||||
FAR struct rpmsg_endpoint *ept;
|
||||
char name[RPMSG_ROUTER_USER_NAME_SIZE];
|
||||
int ret;
|
||||
|
||||
/* Send normal rpmsg "message" to remote device */
|
||||
|
||||
if (dst != RPMSG_NS_EPT_ADDR)
|
||||
{
|
||||
if (!hubdev->ops.send_offchannel_raw)
|
||||
{
|
||||
return RPMSG_ERR_PARAM;
|
||||
}
|
||||
|
||||
return hubdev->ops.send_offchannel_raw(hubdev, src,
|
||||
dst, data, len, wait);
|
||||
}
|
||||
|
||||
/* Try to get user ept firstly */
|
||||
|
||||
metal_mutex_acquire(&rdev->lock);
|
||||
usr_ept = rpmsg_get_endpoint(rdev, ns_msg->name, src, dst);
|
||||
metal_mutex_release(&rdev->lock);
|
||||
if (!usr_ept)
|
||||
{
|
||||
rpmsgerr("Try to get user ept failed.\n");
|
||||
return RPMSG_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Set hub endpoint name(r:cpu:name) for real communication */
|
||||
|
||||
strlcpy(name, ns_msg->name, sizeof(name));
|
||||
snprintf(ns_msg->name, sizeof(ns_msg->name),
|
||||
RPMSG_ROUTER_NAME_PREFIX"%s:%s", edge->remotecpu, name);
|
||||
|
||||
if (ns_msg->flags == RPMSG_NS_DESTROY)
|
||||
{
|
||||
/* Processing RPMSG_NS_DESTROY message */
|
||||
|
||||
metal_mutex_acquire(&hubdev->lock);
|
||||
ept = rpmsg_get_endpoint(hubdev, ns_msg->name,
|
||||
RPMSG_ADDR_ANY, usr_ept->dest_addr);
|
||||
metal_mutex_release(&hubdev->lock);
|
||||
if (!ept)
|
||||
{
|
||||
rpmsgerr("Try to get router endpoint (r:ept) failed.\n");
|
||||
return RPMSG_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Destroy endpoint(r:cpu:name) of real communication */
|
||||
|
||||
rpmsg_destroy_ept(ept);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Processing RPMSG_NS_CREATE or RPMSG_NS_CREATE_ACK message */
|
||||
|
||||
ept = kmm_zalloc(sizeof(*ept));
|
||||
if (!ept)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Save user endpoint */
|
||||
|
||||
ept->priv = usr_ept;
|
||||
ept->ns_bound_cb = rpmsg_router_edge_bound;
|
||||
ept->release_cb = rpmsg_router_edge_release;
|
||||
|
||||
/* Create endpoint (r:cpu:name) for real communication */
|
||||
|
||||
ret = rpmsg_create_ept(ept, hubdev, ns_msg->name,
|
||||
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
|
||||
rpmsg_router_edge_cb,
|
||||
rpmsg_router_edge_unbind);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgerr("Create router endpoint failed: %d\n", ret);
|
||||
kmm_free(ept);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_match
|
||||
*
|
||||
* Description:
|
||||
* This function is used to match the edge core device.
|
||||
* rpmsg_router_edge_bind will be called if the device is matched.
|
||||
*
|
||||
* Parameters:
|
||||
* rdev - real rpmsg device
|
||||
* priv - rpmsg router device for edge core
|
||||
* name - endpoint name (r:cpu:name)
|
||||
* dest - destination address
|
||||
*
|
||||
* Returned Values:
|
||||
* true on success; false on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool rpmsg_router_edge_match(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv, FAR const char *name,
|
||||
uint32_t dest)
|
||||
{
|
||||
FAR struct rpmsg_router_edge_s *edge = priv;
|
||||
|
||||
if (strncmp(name, RPMSG_ROUTER_NAME_PREFIX, RPMSG_ROUTER_NAME_PREFIX_LEN))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !strncmp(name + RPMSG_ROUTER_NAME_PREFIX_LEN, edge->remotecpu,
|
||||
strlen(edge->remotecpu));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_bind
|
||||
*
|
||||
* Description:
|
||||
* This function is used to bind the edge core device.
|
||||
* It will try to find rpmsg_user_ns_bind_cb by user ept name.
|
||||
*
|
||||
* Parameters:
|
||||
* rdev - real rpmsg device
|
||||
* priv - rpmsg router device for edge core
|
||||
* name - endpoint name (r:cpu:name)
|
||||
* dest - destination address
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void rpmsg_router_edge_bind(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv, FAR const char *name,
|
||||
uint32_t dest)
|
||||
{
|
||||
FAR struct rpmsg_router_edge_s *edge = priv;
|
||||
FAR struct rpmsg_device *edgedev = &edge->rdev;
|
||||
|
||||
edgedev->ns_bind_cb(edgedev,
|
||||
name + RPMSG_ROUTER_NAME_PREFIX_LEN +
|
||||
strlen(edge->remotecpu) + 1, dest);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_cb
|
||||
*
|
||||
* Description:
|
||||
* This function is used to receive sync message from router core,
|
||||
* and initialize the router rpmsg device.
|
||||
*
|
||||
* Parameters:
|
||||
* ept - endpoint for synchronizing ready messages
|
||||
* data - received data
|
||||
* len - received data length
|
||||
* src - source address
|
||||
* priv - private data
|
||||
*
|
||||
* Returned Values:
|
||||
* 0 on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsg_router_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsg_router_s *msg = data;
|
||||
FAR struct rpmsg_router_edge_s *edge;
|
||||
FAR struct rpmsg_device *rdev;
|
||||
char name[32];
|
||||
int ret;
|
||||
|
||||
edge = kmm_zalloc(sizeof(*edge));
|
||||
if (!edge)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Initialize router device */
|
||||
|
||||
strlcpy(edge->remotecpu, ept->name + RPMSG_ROUTER_NAME_LEN,
|
||||
sizeof(edge->remotecpu));
|
||||
edge->rx_len = msg->rx_len;
|
||||
edge->tx_len = msg->tx_len;
|
||||
edge->hubdev = ept->rdev;
|
||||
ept->priv = edge;
|
||||
|
||||
/* Initialize router rpmsg device */
|
||||
|
||||
rdev = &edge->rdev;
|
||||
metal_mutex_init(&rdev->lock);
|
||||
rdev->ns_bind_cb = rpmsg_ns_bind;
|
||||
rdev->ns_unbind_cb = rpmsg_ns_unbind;
|
||||
rdev->ops.hold_rx_buffer = rpmsg_router_edge_hold_rx_buffer;
|
||||
rdev->ops.release_rx_buffer = rpmsg_router_edge_release_rx_buffer;
|
||||
rdev->ops.release_tx_buffer = rpmsg_router_edge_release_tx_buffer;
|
||||
rdev->ops.send_offchannel_nocopy = rpmsg_router_edge_send_nocopy;
|
||||
rdev->ops.send_offchannel_raw = rpmsg_router_edge_send_offchannel_raw;
|
||||
rdev->ops.get_tx_payload_buffer = rpmsg_router_edge_get_tx_payload_buffer;
|
||||
|
||||
metal_list_init(&rdev->endpoints);
|
||||
rdev->support_ack = true;
|
||||
rdev->support_ns = true;
|
||||
|
||||
/* Register rpmsg for edge core */
|
||||
|
||||
snprintf(name, sizeof(name), "/dev/rpmsg/%s", edge->remotecpu);
|
||||
ret = rpmsg_register(name, &edge->rpmsg, &g_rpmsg_router_edge_ops);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgerr("rpmsg_register failed: %d\n", ret);
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* Register callback for edge core */
|
||||
|
||||
ret = rpmsg_register_callback(edge, NULL, NULL,
|
||||
rpmsg_router_edge_match,
|
||||
rpmsg_router_edge_bind);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgerr("Register rpmsg callback failed: %d\n", ret);
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
/* Broadcast device_created to all registers */
|
||||
|
||||
rpmsg_device_created(&edge->rpmsg);
|
||||
return 0;
|
||||
|
||||
unregister:
|
||||
rpmsg_unregister(name, &edge->rpmsg);
|
||||
free:
|
||||
kmm_free(edge);
|
||||
ept->priv = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_unbind
|
||||
*
|
||||
* Description:
|
||||
* This function is used to destroy the sync endpoint
|
||||
* when another edge core is disconnected.
|
||||
*
|
||||
* Parameters:
|
||||
* ept - rpmsg endpoint for synchronizing message.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void rpmsg_router_unbind(FAR struct rpmsg_endpoint *ept)
|
||||
{
|
||||
struct rpmsg_router_edge_s *edge = ept->priv;
|
||||
|
||||
if (edge)
|
||||
{
|
||||
kmm_free(edge);
|
||||
ept->priv = NULL;
|
||||
}
|
||||
|
||||
rpmsg_destroy_ept(ept);
|
||||
kmm_free(ept);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_match
|
||||
*
|
||||
* Description:
|
||||
* This function is used to match the endpoint for
|
||||
* synchronizing ready messages.
|
||||
*
|
||||
* Parameters:
|
||||
* rdev - real rpmsg device
|
||||
* priv - rpmsg_router_priv
|
||||
* name - endpoint name
|
||||
* dest - destination address
|
||||
*
|
||||
* Returned Values:
|
||||
* true on success; false on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool rpmsg_router_match(FAR struct rpmsg_device *rdev, FAR void *priv,
|
||||
FAR const char *name, uint32_t dest)
|
||||
{
|
||||
return !strncmp(name, RPMSG_ROUTER_NAME, RPMSG_ROUTER_NAME_LEN);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_bind
|
||||
*
|
||||
* Description:
|
||||
* This function is used to bind the endpoint for
|
||||
* synchronizing ready messages.
|
||||
*
|
||||
* Parameters:
|
||||
* rdev - real rpmsg device
|
||||
* priv - private data
|
||||
* name - endpoint name
|
||||
* dest - destination address
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void rpmsg_router_bind(FAR struct rpmsg_device *rdev, FAR void *priv,
|
||||
FAR const char *name, uint32_t dest)
|
||||
{
|
||||
FAR struct rpmsg_endpoint *ept;
|
||||
int ret;
|
||||
|
||||
ept = kmm_zalloc(sizeof(*ept));
|
||||
DEBUGASSERT(ept);
|
||||
|
||||
ret = rpmsg_create_ept(ept, rdev, name, RPMSG_ADDR_ANY, dest,
|
||||
rpmsg_router_cb, rpmsg_router_unbind);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgerr("Create router endpoint failed: %d\n", ret);
|
||||
kmm_free(ept);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_init
|
||||
*
|
||||
* Description:
|
||||
* This function is used to initialize the edge core.
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rpmsg_router_edge_init(void)
|
||||
{
|
||||
/* Register callback for listening sync message from router hub */
|
||||
|
||||
return rpmsg_register_callback(NULL, NULL, NULL,
|
||||
rpmsg_router_match,
|
||||
rpmsg_router_bind);
|
||||
}
|
468
drivers/rpmsg/rpmsg_router_hub.c
Normal file
468
drivers/rpmsg/rpmsg_router_hub.c
Normal file
@ -0,0 +1,468 @@
|
||||
/****************************************************************************
|
||||
* 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;
|
||||
|
||||
if (!is_rpmsg_ept_ready(&hub->ept[0]) ||
|
||||
!is_rpmsg_ept_ready(&hub->ept[1]))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
msg.tx_len = MIN(rpmsg_get_tx_buffer_size(hub->ept[0].rdev),
|
||||
rpmsg_get_tx_buffer_size(hub->ept[1].rdev));
|
||||
msg.rx_len = MIN(rpmsg_get_rx_buffer_size(hub->ept[0].rdev),
|
||||
rpmsg_get_rx_buffer_size(hub->ept[1].rdev));
|
||||
|
||||
ret = rpmsg_send(&hub->ept[0], &msg, sizeof(msg));
|
||||
DEBUGASSERT(ret >= 0);
|
||||
ret = rpmsg_send(&hub->ept[1], &msg, sizeof(msg));
|
||||
DEBUGASSERT(ret >= 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (strcmp(rpmsg_get_cpuname(rdev), hub->cpuname[i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rpmsg_destroy_ept(&hub->ept[i]);
|
||||
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;
|
||||
}
|
82
include/nuttx/rpmsg/rpmsg_router.h
Normal file
82
include/nuttx/rpmsg/rpmsg_router.h
Normal file
@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/rpmsg/rpmsg_router.h
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_RPMSG_RPMSG_ROUTER_H
|
||||
#define __INCLUDE_NUTTX_RPMSG_RPMSG_ROUTER_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#ifdef CONFIG_RPMSG_ROUTER
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* 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);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rpmsg_router_edge_init
|
||||
*
|
||||
* Description:
|
||||
* This function is used to initialize the edge core.
|
||||
*
|
||||
* Returned Values:
|
||||
* OK on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int rpmsg_router_edge_init(void);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_RPMSG_ROUTER */
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_RPMSG_RPMSG_ROUTER_H */
|
Loading…
Reference in New Issue
Block a user