From d078aadfc58cc8f29d975b788e47d16b14df1016 Mon Sep 17 00:00:00 2001 From: Georgios Vasilakis Date: Wed, 27 Nov 2024 13:37:32 +0100 Subject: [PATCH] nrf_rpc: Add function for single group initialization Adds the function nrf_rpc_init_group to allow initializing an nrf_rpc group individually. This is useful when groups need to be initialized in different boot stages. nrf_rpc_init now takes into account that a group could could be initialized using the nrf_rpc_init_group and avoids initializiting again. Signed-off-by: Georgios Vasilakis --- nrf_rpc/include/nrf_rpc.h | 14 ++++ nrf_rpc/nrf_rpc.c | 146 +++++++++++++++++++++++++++----------- 2 files changed, 119 insertions(+), 41 deletions(-) diff --git a/nrf_rpc/include/nrf_rpc.h b/nrf_rpc/include/nrf_rpc.h index ed81b46bf6..c373ba0243 100644 --- a/nrf_rpc/include/nrf_rpc.h +++ b/nrf_rpc/include/nrf_rpc.h @@ -357,6 +357,20 @@ 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 a single nRF RPC group + * + * Initialize a single nRF RPC group. It can be used to initialize all groups using this function + * and avoid calling nrf_rpc_init. It is also possible to initialize a subset of the groups and + * then call nrf_rpc_init. + * This function doesn't support providing an error handler, a default error handler will be used + * if an erorr occurs. If a custom error handler is needed, use nrf_rpc_init. + * + * @param group Group to initialize + * + * @return 0 on success or negative error code. + */ +int nrf_rpc_init_group(const struct nrf_rpc_group *group); + /** @brief Send a command and provide callback to handle response. * * @param group Group that command belongs to. diff --git a/nrf_rpc/nrf_rpc.c b/nrf_rpc/nrf_rpc.c index b8e41d82dc..f7339c75c4 100644 --- a/nrf_rpc/nrf_rpc.c +++ b/nrf_rpc/nrf_rpc.c @@ -411,49 +411,51 @@ static void internal_tx_handler(void) } } -static int transport_init(nrf_rpc_tr_receive_handler_t receive_cb) +static int transport_init_single(nrf_rpc_tr_receive_handler_t receive_cb, const struct nrf_rpc_group *group) { - int err = 0; - void *iter; - const struct nrf_rpc_group *group; + const struct nrf_rpc_tr *transport = group->transport; + struct nrf_rpc_group_data *data = group->data; + int err; - 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; + NRF_RPC_ASSERT(transport != NULL); - NRF_RPC_ASSERT(transport != NULL); + if (group->data->transport_initialized) { + return 0; + } - /* Initialize all dependencies of `receive_handler` before calling the transport - * init to avoid possible data race if `receive_handler` was invoked before this - * function was completed. */ - if (auto_free_rx_buf(transport)) { - err = nrf_rpc_os_event_init(&data->decode_done_event); - if (err < 0) { - continue; - } + /* Initialize all dependencies of `receive_handler` before calling the transport + * init to avoid possible data race if `receive_handler` was invoked before this + * function was completed. */ + if (auto_free_rx_buf(transport)) { + err = nrf_rpc_os_event_init(&data->decode_done_event); + if (err < 0) { + return err; } + } - err = transport->api->init(transport, receive_cb, NULL); - if (err) { - NRF_RPC_ERR("Failed to initialize transport, err: %d", err); - continue; - } + err = transport->api->init(transport, receive_cb, NULL); + if (err) { + NRF_RPC_ERR("Failed to initialize transport, err: %d", err); + return err; + } - group->data->transport_initialized = true; + 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; - } + 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); + return err; } } - /* Group initialization errors are not propagated to the caller. */ - err = 0; + return 0; +} + +static int groups_init_event_wait(void) +{ + int err = 0; if (waiting_group_count > 0) { err = nrf_rpc_os_event_wait(&groups_init_event, CONFIG_NRF_RPC_GROUP_INIT_WAIT_TIME); @@ -465,6 +467,27 @@ static int transport_init(nrf_rpc_tr_receive_handler_t receive_cb) return err; } +static int transport_init_all(nrf_rpc_tr_receive_handler_t receive_cb) +{ + 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)) { + + transport_init_single(receive_cb, group); + } + + /* Group initialization errors are not propagated to the caller. */ + return groups_init_event_wait(); +} + +static void default_err_handler(const struct nrf_rpc_err_report *report) +{ + NRF_RPC_ERR("nRF RPC error %d ocurred. See nRF RPC logs for more details", report->code); + k_oops(); +} + /* ======================== Receiving Packets ======================== */ /* Find in array and execute command or event handler */ @@ -1091,23 +1114,18 @@ 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) +static int nrf_rpc_prepare_init(void) { int err; - int i; void *iter; const struct nrf_rpc_group *group; uint8_t group_id = 0; uint8_t wait_count = 0; - NRF_RPC_DBG("Initializing nRF RPC module"); - if (is_initialized) { return 0; } - global_err_handler = err_handler; - for (NRF_RPC_AUTO_ARR_FOR(iter, group, &nrf_rpc_groups_array, const struct nrf_rpc_group)) { struct nrf_rpc_group_data *data = group->data; @@ -1144,7 +1162,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 (size_t i = 0; i < CONFIG_NRF_RPC_CMD_CTX_POOL_SIZE; i++) { cmd_ctx_pool[i].id = i; err = nrf_rpc_os_msg_init(&cmd_ctx_pool[i].recv_msg); if (err < 0) { @@ -1152,12 +1170,58 @@ int nrf_rpc_init(nrf_rpc_err_handler_t err_handler) } } - err = transport_init(receive_handler); + global_err_handler = default_err_handler; + + is_initialized = true; + + return 0; +} + +int nrf_rpc_init_group(const struct nrf_rpc_group *group) +{ + int err = nrf_rpc_prepare_init(); + if (err < 0) { + return err; + } + + err = transport_init_single(receive_handler, group); + if (err < 0) { + return err; + } + + NRF_RPC_ASSERT(group_count > 0); + if (initialized_group_count == group_count - 1) { + return groups_init_event_wait(); + } + + return 0; +} + +int nrf_rpc_init(nrf_rpc_err_handler_t err_handler) +{ + int err; + + /* Everything is initialized, nothing to do here */ + if (group_count > 0 && group_count == initialized_group_count) { + return 0; + } + + NRF_RPC_DBG("Initializing nRF RPC module"); + + err = nrf_rpc_prepare_init(); + if (err < 0) { + return err; + } + + /* The nrf_rpc_prepare_init sets a default error handler, + * override it here with the one passed as parameter */ + global_err_handler = err_handler; + + err = transport_init_all(receive_handler); if (err < 0) { return err; } - is_initialized = true; NRF_RPC_DBG("Done initializing nRF RPC module"); return err;