Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions nrf_rpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@ config NRF_RPC_GROUP_INIT_WAIT_TIME
The number of milliseconds to wait for the remote cores to send group
init packets with destination group IDs. Set to -1 to wait forever.

config NRF_RPC_GROUP_DEFAULT_INITIATOR
bool "Initiate group binding by default"
default y
help
For each group defined with NRF_RPC_GROUP_DEFINE macro, initiate the
group binding when calling nrf_rpc_init(). This is achieved by sending
an initialization packet to the peer.

config NRF_RPC_GROUP_DEFAULT_WAIT_ON_INIT
bool "Wait for group binding by default"
default y
help
For each group defined with NRF_RPC_GROUP_DEFINE macro, wait until the
group is bound when calling nrf_rpc_init().

config NRF_RPC_THREAD_POOL_SIZE
int "Number of threads in local thread pool"
default 3
Expand Down
58 changes: 53 additions & 5 deletions nrf_rpc/include/nrf_rpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,11 @@ struct nrf_rpc_cleanup_handler
* error occurred in context of this group. Can be NULL if
* group does not want to receive error notifications.
*/
#define NRF_RPC_GROUP_DEFINE(_name, _strid, _transport, _ack_handler, _ack_data, \
_err_handler) \
NRF_RPC_GROUP_DEFINE_INTERNAL__(_name, _strid, _transport, _ack_handler, \
_ack_data, _err_handler, NULL, true, \
true) \
#define NRF_RPC_GROUP_DEFINE(_name, _strid, _transport, _ack_handler, _ack_data, _err_handler) \
NRF_RPC_GROUP_DEFINE_INTERNAL__(_name, _strid, _transport, _ack_handler, _ack_data, \
_err_handler, NULL, \
IS_ENABLED(CONFIG_NRF_RPC_GROUP_DEFAULT_WAIT_ON_INIT), \
IS_ENABLED(CONFIG_NRF_RPC_GROUP_DEFAULT_INITIATOR))

/** @brief Define a non-blocking group of commands and events.
*
Expand Down Expand Up @@ -363,6 +363,8 @@ struct nrf_rpc_cleanup_handler
void nrf_rpc_set_bound_handler(nrf_rpc_group_bound_handler_t bound_handler);

/** @brief Initialize the nRF RPC
*
* Calling this function is equivalent to calling both @ref nrf_rpc_setup and @ref nrf_rpc_bind.
*
* @param err_handler Error handler that will be called to report error in
* nRF RPC.
Expand All @@ -371,6 +373,52 @@ void nrf_rpc_set_bound_handler(nrf_rpc_group_bound_handler_t bound_handler);
*/
int nrf_rpc_init(nrf_rpc_err_handler_t err_handler);

/** @brief Initialize the nRF RPC internal state.
*
* Sets up all variables related to nRF RPC, including contexts, groups, and transports.
* It does not initiate any communication with the peer.
*
* @note This function can be invoked multiple times; however, only the first call has an effect.
* @note This function is not thread-safe and should not be called concurrently from multiple
* threads.
*
* @warning This function is experimental and subject to change or removal without prior notice.
*
* @param err_handler Error handler that will be called to report an error in the nRF RPC.
* @param bound_handler Bound handler that will be called when a group is bound with the peer.
*
* @return 0 on success or negative error code.
*/
int nrf_rpc_setup(nrf_rpc_err_handler_t err_handler, nrf_rpc_group_bound_handler_t bound_handler);

/** @brief Binds the nRF RPC groups.
*
* Sends an initializaton packet to the peer for each group defined with the @ref
* NRF_RPC_FLAGS_INITIATOR flag. It then waits until all groups defined with the @ref
* NRF_RPC_FLAGS_WAIT_ON_INIT flag have been bound.
*
* A group is considered bound when an initialization packet for that group is received from the
* peer, indicating the numerical identifier assigned to the group by the peer.
*
* The function may time out if some groups are not bound within the duration specified by the
* CONFIG_NRF_RPC_GROUP_INIT_WAIT_TIME Kconfig option.
*
* @note This function is not thread-safe; should not be called concurrently from multiple threads.
*
* @warning This function is experimental and subject to change or removal without prior notice.
*
* @return 0 on success or negative error code.
*/
int nrf_rpc_bind(void);

/** @brief Unbinds the nRF RPC groups.
*
* Resets the effect of @ref nrf_rpc_bind so that no groups are considered bound after returning
* from this function.
*
* @warning This function is experimental and subject to change or removal without prior notice.
*/
void nrf_rpc_unbind(void);

/** @brief Registers the cleanup handler.
*
Expand Down
128 changes: 76 additions & 52 deletions nrf_rpc/nrf_rpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,48 +419,6 @@ static void internal_tx_handler(void)
}
}

static int transport_init(nrf_rpc_tr_receive_handler_t receive_cb)
{
int err = 0;
void *iter;
const struct nrf_rpc_group *group;

for (NRF_RPC_AUTO_ARR_FOR(iter, group, &nrf_rpc_groups_array,
const struct nrf_rpc_group)) {
const struct nrf_rpc_tr *transport = group->transport;
struct nrf_rpc_group_data *data = group->data;

err = transport->api->init(transport, receive_cb, NULL);
if (err) {
NRF_RPC_ERR("Failed to initialize transport, err: %d", err);
continue;
}

group->data->transport_initialized = true;

if (group->flags & NRF_RPC_FLAGS_INITIATOR) {
err = group_init_send(group);
if (err) {
NRF_RPC_ERR("Failed to send group init packet for group id: %d strid: %s err: %d",
data->src_group_id, group->strid, err);
continue;
}
}
}

/* Group initialization errors are not propagated to the caller. */
err = 0;

if (waiting_group_count > 0) {
err = nrf_rpc_os_event_wait(&groups_init_event, CONFIG_NRF_RPC_GROUP_INIT_WAIT_TIME);
if (err) {
NRF_RPC_ERR("Not all groups are ready to use.");
}
}

return err;
}

/* ======================== Receiving Packets ======================== */

/* Find in array and execute command or event handler */
Expand Down Expand Up @@ -1143,10 +1101,9 @@ void nrf_rpc_set_bound_handler(nrf_rpc_group_bound_handler_t bound_handler)
global_bound_handler = bound_handler;
}

int nrf_rpc_init(nrf_rpc_err_handler_t err_handler)
int nrf_rpc_setup(nrf_rpc_err_handler_t err_handler, nrf_rpc_group_bound_handler_t bound_handler)
{
int err;
int i;
void *iter;
const struct nrf_rpc_group *group;
uint8_t group_id = 0;
Expand All @@ -1161,6 +1118,7 @@ int nrf_rpc_init(nrf_rpc_err_handler_t err_handler)
nrf_rpc_os_mutex_init(&cleanup_mutex);

global_err_handler = err_handler;
global_bound_handler = bound_handler;

for (NRF_RPC_AUTO_ARR_FOR(iter, group, &nrf_rpc_groups_array,
const struct nrf_rpc_group)) {
Expand Down Expand Up @@ -1194,8 +1152,6 @@ int nrf_rpc_init(nrf_rpc_err_handler_t err_handler)
group_count = group_id;
waiting_group_count = wait_count;

memset(&cmd_ctx_pool, 0, sizeof(cmd_ctx_pool));

err = nrf_rpc_os_init(execute_packet);
if (err < 0) {
return err;
Expand All @@ -1211,7 +1167,7 @@ int nrf_rpc_init(nrf_rpc_err_handler_t err_handler)
return err;
}

for (i = 0; i < CONFIG_NRF_RPC_CMD_CTX_POOL_SIZE; i++) {
for (int i = 0; i < CONFIG_NRF_RPC_CMD_CTX_POOL_SIZE; i++) {
cmd_ctx_pool[i].id = i;
err = nrf_rpc_os_mutex_init(&cmd_ctx_pool[i].mutex);
if (err < 0) {
Expand All @@ -1223,17 +1179,85 @@ int nrf_rpc_init(nrf_rpc_err_handler_t err_handler)
}
}

err = transport_init(receive_handler);
if (err < 0) {
return err;
}

is_initialized = true;
NRF_RPC_DBG("Done initializing nRF RPC module");

return err;
}

int nrf_rpc_bind(void)
{
int err;
void *iter;
const struct nrf_rpc_group *group;

for (NRF_RPC_AUTO_ARR_FOR(iter, group, &nrf_rpc_groups_array, const struct nrf_rpc_group)) {
const struct nrf_rpc_tr *transport = group->transport;
struct nrf_rpc_group_data *data = group->data;

if (!group->data->transport_initialized) {
err = transport->api->init(transport, receive_handler, NULL);
if (err) {
NRF_RPC_ERR("Failed to initialize transport, err: %d", err);
continue;
}

group->data->transport_initialized = true;
}

if (group->flags & NRF_RPC_FLAGS_INITIATOR) {
err = group_init_send(group);
if (err) {
NRF_RPC_ERR("Failed to send group init packet for group id: %d "
"strid: %s err: %d",
data->src_group_id, group->strid, err);
continue;
}
}
}

/* Group initialization errors are not propagated to the caller. */
err = 0;

if (waiting_group_count > 0) {
err = nrf_rpc_os_event_wait(&groups_init_event,
CONFIG_NRF_RPC_GROUP_INIT_WAIT_TIME);
if (err) {
NRF_RPC_ERR("Not all groups are ready to use.");
}
}

return err;
}

void nrf_rpc_unbind(void)
{
void *iter;
const struct nrf_rpc_group *group;

initialized_group_count = 0;

for (NRF_RPC_AUTO_ARR_FOR(iter, group, &nrf_rpc_groups_array, const struct nrf_rpc_group)) {
group->data->dst_group_id = NRF_RPC_ID_UNKNOWN;
}
}

int nrf_rpc_init(nrf_rpc_err_handler_t err_handler)
{
int err;

if (is_initialized) {
return 0;
}

err = nrf_rpc_setup(err_handler, global_bound_handler);
if (err < 0) {
return err;
}

return nrf_rpc_bind();
}

void nrf_rpc_register_cleanup_handler(struct nrf_rpc_cleanup_handler *handler)
{
nrf_rpc_os_mutex_lock(&cleanup_mutex);
Expand Down