diff --git a/modules/hal_nordic/nrfs/backends/Kconfig b/modules/hal_nordic/nrfs/backends/Kconfig index 2dc97ea63ce..34cd5c847c5 100644 --- a/modules/hal_nordic/nrfs/backends/Kconfig +++ b/modules/hal_nordic/nrfs/backends/Kconfig @@ -25,4 +25,19 @@ config NRFS_BACKEND_TX_MSG_QUEUE_SIZE range 1 16 default 8 +config NRFS_SEND_RETRY_DELAY + int "Delay in us" + range 1 100 + default 1 + help + Delay when waiting for next message send retry in case of send error. + +config NRFS_SEND_RETRY_MAX_COUNT + int "Max number of send retries" + range 0 100 + default 5 + help + How many times nrfs will try to send message over ipc service until + error will be reported. For example when shared ipc memory is full. + endmenu diff --git a/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c index bf5dec9fe16..a3e7ff22100 100644 --- a/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c +++ b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c @@ -80,6 +80,10 @@ __weak void nrfs_backend_error_handler(enum nrfs_backend_error error_id, int err LOG_ERR("IPC register endpoint failure with error: %d", error); break; + case NRFS_ERROR_SEND_DATA_FROM_QUEUE: + LOG_ERR("IPC backend sent data failed."); + break; + default: LOG_ERR("Undefined error id: %d, error cause: %d", error_id, error); break; @@ -120,14 +124,45 @@ static void ipc_sysctrl_ept_recv(const void *data, size_t size, void *priv) } } +/** + * @brief This function will try to send data directly using ipc service + * In case of errors it will retry if configured. + * + * @param message Pointer to the buffer to send. + * @param size Number of bytes to send. + * @retval NRFS_SUCCESS Message sent successfully. + * @retval NRFS_ERR_IPC Backend returned error during message sending. + */ +static nrfs_err_t nrfs_backend_try_send_directly_over_ipc_service(void *message, size_t size) +{ + size_t retry_count = CONFIG_NRFS_SEND_RETRY_MAX_COUNT + 1; + int ret = 0; + + do { + ret = ipc_service_send(&ipc_cpusys_channel_config.ipc_ept, message, size); + if (ret < (int)size) { + k_usleep(CONFIG_NRFS_SEND_RETRY_DELAY); + } else { + return NRFS_SUCCESS; + } + } while (--retry_count); + + return NRFS_ERR_IPC; +} + static void nrfs_backend_send_work(struct k_work *item) { struct ipc_data_packet data_to_send; LOG_DBG("Sending data from workqueue"); while (k_msgq_get(&ipc_transmit_msgq, &data_to_send, K_NO_WAIT) == 0) { - ipc_service_send(&ipc_cpusys_channel_config.ipc_ept, &data_to_send.data, - data_to_send.size); + + nrfs_err_t ret = nrfs_backend_try_send_directly_over_ipc_service(&data_to_send.data, + data_to_send.size); + + if (ret != NRFS_SUCCESS) { + nrfs_backend_error_handler(NRFS_ERROR_SEND_DATA_FROM_QUEUE, 0, true); + } } } @@ -177,8 +212,8 @@ nrfs_err_t nrfs_backend_send(void *message, size_t size) nrfs_err_t nrfs_backend_send_ex(void *message, size_t size, k_timeout_t timeout, bool high_prio) { if (!k_is_in_isr() && nrfs_backend_connected()) { - return ipc_service_send(&ipc_cpusys_channel_config.ipc_ept, message, size) ? - NRFS_SUCCESS : NRFS_ERR_IPC; + return nrfs_backend_try_send_directly_over_ipc_service(message, size); + } else if (size <= MAX_PACKET_DATA_SIZE) { int err; struct ipc_data_packet tx_data; diff --git a/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h index 572c05e864c..015d3f99643 100644 --- a/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h +++ b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h @@ -36,6 +36,7 @@ enum nrfs_backend_error { NRFS_ERROR_IPC_OPEN_INSTANCE, NRFS_ERROR_IPC_REGISTER_ENDPOINT, NRFS_ERROR_BACKEND_NOT_CONNECTED, + NRFS_ERROR_SEND_DATA_FROM_QUEUE, NRFS_ERROR_COUNT };