Skip to content

Commit 9fa48fe

Browse files
committed
Draft of icmsg_open
1 parent f3f8816 commit 9fa48fe

File tree

6 files changed

+93
-35
lines changed

6 files changed

+93
-35
lines changed

include/zephyr/ipc/icmsg.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ extern "C" {
2727
*/
2828

2929
enum icmsg_state {
30-
ICMSG_STATE_OFF,
31-
ICMSG_STATE_BUSY,
32-
ICMSG_STATE_READY,
30+
// TODO: rename as it was before
31+
ICMSG_STATE_UNINITIALIZED, /**< Instance is not initialized yet. Sending will fail. Opening allowed. */
32+
ICMSG_STATE_INITIALIZING, /**< Instance is initializing - waiting for remote to acknowledge. Sending will fail. Opening allowed, session will change and remote may or may not get unbound() callback. */
33+
ICMSG_STATE_CONNECTED, /**< Instance is connected. Sending will be successful. Opening allowed, session will change and remote will get unbound() callback. */
34+
ICMSG_STATE_DISCONNECTED, /**< Instance was connected, but get disconnected. Sending will be silently discarded, because it there may be old sends. Opening allowed. */
3335
};
3436

3537
enum icmsg_unbound_mode {
@@ -41,6 +43,7 @@ enum icmsg_unbound_mode {
4143
struct icmsg_config_t {
4244
struct mbox_dt_spec mbox_tx;
4345
struct mbox_dt_spec mbox_rx;
46+
enum icmsg_unbound_mode unbound_mode;
4447
};
4548

4649
struct icmsg_data_t {
@@ -61,6 +64,8 @@ struct icmsg_data_t {
6164
struct k_work_delayable notify_work;
6265
struct k_work mbox_work;
6366
#endif
67+
uint16_t remote_session;
68+
uint16_t local_session;
6469
atomic_t state;
6570
};
6671

subsys/ipc/ipc_service/backends/ipc_icbmsg.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,7 @@ const static struct ipc_service_backend backend_ops = {
14181418
.control_config = { \
14191419
.mbox_tx = MBOX_DT_SPEC_INST_GET(i, tx), \
14201420
.mbox_rx = MBOX_DT_SPEC_INST_GET(i, rx), \
1421+
.unbound_mode = ICMSG_UNBOUND_MODE_DISABLE, /* TODO: */ \
14211422
}, \
14221423
.tx = { \
14231424
.blocks_ptr = (uint8_t *)GET_BLOCKS_ADDR_INST(i, tx, rx), \

subsys/ipc/ipc_service/backends/ipc_icmsg.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ static int backend_init(const struct device *instance)
6060
static const struct icmsg_config_t backend_config_##i = { \
6161
.mbox_tx = MBOX_DT_SPEC_INST_GET(i, tx), \
6262
.mbox_rx = MBOX_DT_SPEC_INST_GET(i, rx), \
63+
.unbound_mode = UNBOUND_MODE(i), \
6364
}; \
6465
\
6566
PBUF_DEFINE(tx_pb_##i, \

subsys/ipc/ipc_service/backends/ipc_icmsg_me_follower.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ static int backend_init(const struct device *instance)
280280
static const struct icmsg_config_t backend_config_##i = { \
281281
.mbox_tx = MBOX_DT_SPEC_INST_GET(i, tx), \
282282
.mbox_rx = MBOX_DT_SPEC_INST_GET(i, rx), \
283+
.unbound_mode = ICMSG_UNBOUND_MODE_DISABLE, \
283284
}; \
284285
\
285286
PBUF_DEFINE(tx_pb_##i, \

subsys/ipc/ipc_service/backends/ipc_icmsg_me_initiator.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ static int backend_init(const struct device *instance)
186186
static const struct icmsg_config_t backend_config_##i = { \
187187
.mbox_tx = MBOX_DT_SPEC_INST_GET(i, tx), \
188188
.mbox_rx = MBOX_DT_SPEC_INST_GET(i, rx), \
189+
.unbound_mode = ICMSG_UNBOUND_MODE_DISABLE, \
189190
}; \
190191
\
191192
PBUF_DEFINE(tx_pb_##i, \

subsys/ipc/ipc_service/lib/icmsg.c

Lines changed: 81 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
#include <zephyr/ipc/pbuf.h>
1313
#include <zephyr/init.h>
1414

15+
#define LOCAL_SID_REQ_FROM_RX(rx_handshake) ((rx_handshake) & 0xFFFF)
16+
#define REMOTE_SID_ACK_FROM_RX(rx_handshake) ((rx_handshake) >> 16)
17+
#define REMOTE_SID_REQ_FROM_TX(tx_handshake) ((tx_handshake) & 0xFFFF)
18+
#define LOCAL_SID_ACK_FROM_TX(tx_handshake) ((tx_handshake) >> 16)
19+
#define MAKE_RX_HANDSHAKE(local_sid_req, remote_sid_ack) ((local_sid_req) | ((remote_sid_ack) << 16))
20+
#define MAKE_TX_HANDSHAKE(remote_sid_req, local_sid_ack) ((remote_sid_req) | ((local_sid_ack) << 16))
21+
22+
#define SID_DISCONNECTED_BIT 0x8000
23+
1524
#define BOND_NOTIFY_REPEAT_TO K_MSEC(CONFIG_IPC_SERVICE_ICMSG_BOND_NOTIFY_REPEAT_TO_MS)
1625
#define SHMEM_ACCESS_TO K_MSEC(CONFIG_IPC_SERVICE_ICMSG_SHMEM_ACCESS_TO_MS)
1726

@@ -259,10 +268,10 @@ int icmsg_open(const struct icmsg_config_t *conf,
259268
struct icmsg_data_t *dev_data,
260269
const struct ipc_service_cb *cb, void *ctx)
261270
{
262-
if (!atomic_cas(&dev_data->state, ICMSG_STATE_OFF, ICMSG_STATE_BUSY)) {
263-
/* Already opened. */
264-
return -EALREADY;
265-
}
271+
int ret;
272+
enum icmsg_state old_state;
273+
274+
old_state = atomic_set(&dev_data->state, ICMSG_STATE_INITIALIZING);
266275

267276
dev_data->cb = cb;
268277
dev_data->ctx = ctx;
@@ -272,55 +281,95 @@ int icmsg_open(const struct icmsg_config_t *conf,
272281
k_mutex_init(&dev_data->tx_lock);
273282
#endif
274283

275-
int ret = pbuf_tx_init(dev_data->tx_pb);
284+
if (conf->unbound_mode != ICMSG_UNBOUND_MODE_DISABLE) {
285+
// Increment local session id without conflicts with forbidden values.
286+
uint32_t local_session_ack =
287+
LOCAL_SID_ACK_FROM_TX(pbuf_handshake_read(dev_data->tx_pb));
288+
dev_data->local_session =
289+
LOCAL_SID_REQ_FROM_RX(pbuf_handshake_read(dev_data->tx_pb));
290+
dev_data->remote_session = 0;
291+
do {
292+
dev_data->local_session = (dev_data->local_session + 1) & 0x8FFF;
293+
} while (dev_data->local_session == local_session_ack || dev_data->local_session == 0);
294+
// Write local session id request without remote acknowledge
295+
pbuf_handshake_write(MAKE_RX_HANDSHAKE(dev_data->local_session, 0));
296+
// We can now initialize TX, since we know that remote, during receiving,
297+
// will first read FIFO indexes and later, it will check if session has changed
298+
// before using indexes to receive the message.
299+
// TODO: above not treue, We should reinit TX just before sending remote acknowledgement, because
300+
// remote may change read index!
301+
// Sending magic packet should be after local acknowledgement.
302+
} else {
303+
// Initialization of RX and sending magic bytes must be postponed
304+
// if unbound mode enabled. We need to wait until remote is ready.
276305

277-
if (ret < 0) {
278-
__ASSERT(false, "Incorrect configuration");
279-
return ret;
280-
}
306+
ret = pbuf_tx_init(dev_data->tx_pb);
281307

282-
(void)pbuf_rx_init(dev_data->rx_pb);
308+
if (ret < 0) {
309+
__ASSERT(false, "Incorrect Tx configuration");
310+
return ret;
311+
}
283312

284-
ret = pbuf_write(dev_data->tx_pb, magic, sizeof(magic));
313+
ret = pbuf_rx_init(dev_data->rx_pb);
285314

286-
if (ret < 0) {
287-
__ASSERT_NO_MSG(false);
288-
return ret;
289-
}
315+
if (ret < 0) {
316+
__ASSERT(false, "Incorrect Rx configuration");
317+
return ret;
318+
}
290319

291-
if (ret < (int)sizeof(magic)) {
292-
__ASSERT_NO_MSG(ret == sizeof(magic));
293-
return ret;
320+
ret = pbuf_write(dev_data->tx_pb, magic, sizeof(magic));
321+
322+
if (ret < 0) {
323+
__ASSERT_NO_MSG(false);
324+
return ret;
325+
}
326+
327+
if (ret < (int)sizeof(magic)) {
328+
__ASSERT_NO_MSG(ret == sizeof(magic));
329+
return ret;
330+
}
294331
}
295332

296-
ret = mbox_init(conf, dev_data);
297-
if (ret) {
298-
return ret;
333+
if (old_state == ICMSG_STATE_UNINITIALIZED) {
334+
// Initialize mbox only if we are doing first-time open (not re-open after unbound)
335+
ret = mbox_init(conf, dev_data);
336+
if (ret) {
337+
return ret;
338+
}
299339
}
340+
341+
if (conf->unbound_mode == ICMSG_UNBOUND_MODE_DISABLE) {
342+
// Polling is only when unbound mode is disabled.
300343
#ifdef CONFIG_MULTITHREADING
301344
ret = k_work_schedule_for_queue(workq, &dev_data->notify_work, K_NO_WAIT);
302-
if (ret < 0) {
303-
return ret;
304-
}
305345
#else
306346
notify_process(dev_data);
347+
ret = 0;
307348
#endif
308-
return 0;
349+
} else {
350+
// We need to send a notification to remote, it may not be delivered
351+
// since it may be uninitialized yet, but when it finishes the initialization
352+
// we get a notification from it. We need to send this notification in callback
353+
// again to make sure that it arrived.
354+
ret = mbox_send_dt(&conf->mbox_tx, NULL);
355+
}
356+
return ret;
309357
}
310358

311359
int icmsg_close(const struct icmsg_config_t *conf,
312360
struct icmsg_data_t *dev_data)
313361
{
314-
int ret;
362+
int ret = 0;
315363

316-
ret = mbox_deinit(conf, dev_data);
317-
if (ret) {
318-
return ret;
319-
}
364+
enum icmsg_state old_state;
320365

321-
atomic_set(&dev_data->state, ICMSG_STATE_OFF);
366+
old_state = atomic_set(&dev_data->state, ICMSG_STATE_UNINITIALIZED);
322367

323-
return 0;
368+
if (old_state != ICMSG_STATE_UNINITIALIZED) {
369+
ret = mbox_deinit(conf, dev_data);
370+
}
371+
372+
return ret;
324373
}
325374

326375
int icmsg_send(const struct icmsg_config_t *conf,

0 commit comments

Comments
 (0)