From 0620cb1fe1807a4a0e1ea83b300138d27b7fc175 Mon Sep 17 00:00:00 2001 From: Radoslaw Koppel Date: Tue, 15 Nov 2022 15:12:25 +0100 Subject: [PATCH] ipc: ipc_service: icmsg: Increase reliability of bonding This commit changes the way bonding between endpoints is processed. There is no blind attempt to read the buffer without mbox notification. On second side the notification is repeated multiple times until valid bonding is detected. Signed-off-by: Radoslaw Koppel --- include/zephyr/ipc/icmsg.h | 2 ++ subsys/ipc/ipc_service/backends/Kconfig | 8 ++++++ subsys/ipc/ipc_service/lib/icmsg.c | 37 ++++++++++++++++++++----- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/include/zephyr/ipc/icmsg.h b/include/zephyr/ipc/icmsg.h index 0ff547ba2bb..27f4764ad57 100644 --- a/include/zephyr/ipc/icmsg.h +++ b/include/zephyr/ipc/icmsg.h @@ -37,6 +37,8 @@ struct icmsg_data_t { void *ctx; /* General */ + const struct icmsg_config_t *cfg; + struct k_work_delayable notify_work; struct k_work mbox_work; atomic_t state; }; diff --git a/subsys/ipc/ipc_service/backends/Kconfig b/subsys/ipc/ipc_service/backends/Kconfig index 43f487122ff..4b8d5d16f54 100644 --- a/subsys/ipc/ipc_service/backends/Kconfig +++ b/subsys/ipc/ipc_service/backends/Kconfig @@ -89,5 +89,13 @@ config SYSTEM_WORKQUEUE_PRIORITY depends on IPC_SERVICE_ICMSG range -256 -1 +config IPC_SERVICE_BACKEND_ICMSG_BOND_NOTIFY_REPEAT_TO_MS + int "Bond notification timeout in miliseconds" + range 1 100 + default 1 + help + Time to wait for remote bonding notification before the + notification is repeated. + rsource "Kconfig.icmsg_me" rsource "Kconfig.rpmsg" diff --git a/subsys/ipc/ipc_service/lib/icmsg.c b/subsys/ipc/ipc_service/lib/icmsg.c index c51bc9e2160..583db86aac0 100644 --- a/subsys/ipc/ipc_service/lib/icmsg.c +++ b/subsys/ipc/ipc_service/lib/icmsg.c @@ -12,6 +12,7 @@ #include #define CB_BUF_SIZE CONFIG_IPC_SERVICE_ICMSG_CB_BUF_SIZE +#define BOND_NOTIFY_REPEAT_TO K_MSEC(CONFIG_IPC_SERVICE_BACKEND_ICMSG_BOND_NOTIFY_REPEAT_TO_MS) static const uint8_t magic[] = {0x45, 0x6d, 0x31, 0x6c, 0x31, 0x4b, 0x30, 0x72, 0x6e, 0x33, 0x6c, 0x69, 0x34}; @@ -34,10 +35,30 @@ static int mbox_deinit(const struct icmsg_config_t *conf, } (void)k_work_cancel(&dev_data->mbox_work); + (void)k_work_cancel_delayable(&dev_data->notify_work); return 0; } +static void notify_process(struct k_work *item) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(item); + struct icmsg_data_t *dev_data = + CONTAINER_OF(dwork, struct icmsg_data_t, notify_work); + + (void)mbox_send(&dev_data->cfg->mbox_tx, NULL); + + atomic_t state = atomic_get(&dev_data->state); + + if (state != ICMSG_STATE_READY) { + int ret; + + ret = k_work_reschedule(dwork, BOND_NOTIFY_REPEAT_TO); + __ASSERT_NO_MSG(ret >= 0); + (void)ret; + } +} + static void mbox_callback_process(struct k_work *item) { struct icmsg_data_t *dev_data = CONTAINER_OF(item, struct icmsg_data_t, mbox_work); @@ -61,6 +82,8 @@ static void mbox_callback_process(struct k_work *item) dev_data->cb->received(cb_buffer, len, dev_data->ctx); } } else { + int ret; + __ASSERT_NO_MSG(state == ICMSG_STATE_BUSY); if (len != sizeof(magic) || memcmp(magic, cb_buffer, len)) { __ASSERT_NO_MSG(false); @@ -72,6 +95,9 @@ static void mbox_callback_process(struct k_work *item) } atomic_set(&dev_data->state, ICMSG_STATE_READY); + ret = k_work_cancel_delayable(&dev_data->notify_work); + __ASSERT_NO_MSG(ret >= 0); + (void)ret; } /* Reading with NULL buffer to know if there are data in the @@ -102,6 +128,7 @@ static int mbox_init(const struct icmsg_config_t *conf, int err; k_work_init(&dev_data->mbox_work, mbox_callback_process); + k_work_init_delayable(&dev_data->notify_work, notify_process); err = mbox_register_callback(&conf->mbox_rx, mbox_callback, dev_data); if (err != 0) { @@ -137,6 +164,7 @@ int icmsg_open(const struct icmsg_config_t *conf, dev_data->cb = cb; dev_data->ctx = ctx; + dev_data->cfg = conf; ret = mbox_init(conf, dev_data); if (ret) { @@ -154,16 +182,11 @@ int icmsg_open(const struct icmsg_config_t *conf, return ret; } - ret = mbox_send(&conf->mbox_tx, NULL); - if (ret) { + ret = k_work_schedule(&dev_data->notify_work, K_NO_WAIT); + if (ret < 0) { return ret; } - ret = spsc_pbuf_read(dev_data->rx_ib, NULL, 0); - if (ret > 0) { - (void)k_work_submit(&dev_data->mbox_work); - } - return 0; }