Zephyr Project API 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
zbus.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Rodrigo Peixoto <rodrigopex@gmail.com>
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6#ifndef ZEPHYR_INCLUDE_ZBUS_ZBUS_H_
7#define ZEPHYR_INCLUDE_ZBUS_ZBUS_H_
8
9#include <string.h>
10
11#include <zephyr/kernel.h>
12#include <zephyr/sys/check.h>
14
15#ifdef __cplusplus
16extern "C" {
17#endif
18
27
35
39 int16_t observers_start_idx;
40
44 int16_t observers_end_idx;
45
49 struct k_sem sem;
50
51#if defined(CONFIG_ZBUS_PRIORITY_BOOST)
55 int highest_observer_priority;
56#endif /* CONFIG_ZBUS_PRIORITY_BOOST */
57
58#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
62 sys_slist_t observers;
63#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
64
65#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION) || defined(__DOXYGEN__)
69 struct net_buf_pool *msg_subscriber_pool;
70#endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */
71
72#if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) || defined(__DOXYGEN__)
74 k_ticks_t publish_timestamp;
76 uint32_t publish_count;
77#endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */
78
80};
81
91typedef bool (*zbus_validator)(const void *msg, size_t msg_size);
92
101#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
103 const char *name;
104#endif
105#if defined(CONFIG_ZBUS_CHANNEL_ID) || defined(__DOXYGEN__)
107 uint32_t id;
108#endif
112 void *message;
113
115 size_t message_size;
116
120 void *user_data;
121
126 zbus_validator validator;
127
129 struct zbus_channel_data *data;
131};
132
142
154
156struct zbus_observer_data {
158 bool enabled;
159
160#if defined(CONFIG_ZBUS_PRIORITY_BOOST)
162 int priority;
163#endif /* CONFIG_ZBUS_PRIORITY_BOOST */
164};
166
184#if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
186 const char *name;
187#endif
189 enum zbus_observer_type type;
190
192 struct zbus_observer_data *data;
193
194 union {
196 struct k_msgq *queue;
197
199 void (*callback)(const struct zbus_channel *chan);
200
201#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
205 struct k_fifo *message_fifo;
206#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
207
208#if defined(CONFIG_ZBUS_ASYNC_LISTENER) || defined(__DOXYGEN__)
212 struct k_work *work;
213#endif /* CONFIG_ZBUS_ASYNC_LISTENER */
214 };
216};
217
219struct zbus_channel_observation_mask {
220 bool enabled;
221};
222
226struct zbus_channel_observation {
227 const struct zbus_channel *chan;
228 const struct zbus_observer *obs;
229};
230
231#ifdef __cplusplus
232#define _ZBUS_CPP_EXTERN extern
233#else
234#define _ZBUS_CPP_EXTERN
235#endif /* __cplusplus */
236
237#define ZBUS_MIN_THREAD_PRIORITY (CONFIG_NUM_PREEMPT_PRIORITIES - 1)
238
239#if defined(CONFIG_ZBUS_ASSERT_MOCK)
240#define _ZBUS_ASSERT(_cond, _fmt, ...) \
241 do { \
242 if (!(_cond)) { \
243 printk("ZBUS ASSERT: "); \
244 printk(_fmt, ##__VA_ARGS__); \
245 printk("\n"); \
246 return -EFAULT; \
247 } \
248 } while (0)
249#else
250#define _ZBUS_ASSERT(_cond, _fmt, ...) __ASSERT(_cond, _fmt, ##__VA_ARGS__)
251#endif
252
253#if defined(CONFIG_ZBUS_CHANNEL_NAME)
254#define ZBUS_CHANNEL_NAME_INIT(_name) .name = #_name,
255#define _ZBUS_CHAN_NAME(_chan) (_chan)->name
256#else
257#define ZBUS_CHANNEL_NAME_INIT(_name)
258#define _ZBUS_CHAN_NAME(_chan) ""
259#endif
260
261#if defined(CONFIG_ZBUS_OBSERVER_NAME)
262#define ZBUS_OBSERVER_NAME_INIT(_name) .name = #_name,
263#define _ZBUS_OBS_NAME(_obs) (_obs)->name
264#else
265#define ZBUS_OBSERVER_NAME_INIT(_name)
266#define _ZBUS_OBS_NAME(_obs) ""
267#endif
268
269#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS)
270#define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name) static sys_slist_t _slist_name
271#define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) .runtime_observers = &_slist_name,
272#else
273#define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name)
274#define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) /* No runtime observers */
275#endif
276
277#define _ZBUS_OBS_EXTERN(_name) extern const struct zbus_observer _name
278
279#define _ZBUS_CHAN_EXTERN(_name) extern const struct zbus_channel _name
280
281#define ZBUS_REF(_value) &(_value)
282
283#define FOR_EACH_FIXED_ARG_NONEMPTY_TERM(F, sep, fixed_arg, ...) \
284 COND_CODE_0(/* are there zero non-empty arguments ? */ \
285 NUM_VA_ARGS_LESS_1( \
286 LIST_DROP_EMPTY(__VA_ARGS__, _)), /* if so, expand to nothing */ \
287 (), /* otherwise, expand to: */ \
288 (FOR_EACH_IDX_FIXED_ARG( \
289 F, sep, fixed_arg, \
290 LIST_DROP_EMPTY(__VA_ARGS__)) /* plus a final terminator */ \
291 __DEBRACKET sep))
292
293#define _ZBUS_OBSERVATION_PREFIX(_idx) \
294 GET_ARG_N(_idx, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, \
295 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, \
296 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, \
297 58, 59, 60, 61, 62, 63)
298
299#define _ZBUS_CHAN_OBSERVATION(_idx, _obs, _chan) \
300 const STRUCT_SECTION_ITERABLE( \
301 zbus_channel_observation, \
302 _CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx)))) = {.chan = &_chan, \
303 .obs = &_obs}; \
304 STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask, \
305 _CONCAT(_CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx))), \
306 _mask)) = {.enabled = false};
307
308#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
309#define _ZBUS_RUNTIME_OBSERVERS(_name) .observers = &(_CONCAT(_observers_, _name)),
310#define _ZBUS_RUNTIME_OBSERVERS_DECL(_name) static sys_slist_t _CONCAT(_observers_, _name);
311#else
312#define _ZBUS_RUNTIME_OBSERVERS(_name)
313#define _ZBUS_RUNTIME_OBSERVERS_DECL(_name)
314#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
315
316#define _ZBUS_MESSAGE_NAME(_name) _CONCAT(_zbus_message_, _name)
317
318/* clang-format off */
319#define _ZBUS_CHAN_DEFINE(_name, _id, _type, _validator, _user_data) \
320 static struct zbus_channel_data _CONCAT(_zbus_chan_data_, _name) = { \
321 .observers_start_idx = -1, \
322 .observers_end_idx = -1, \
323 .sem = Z_SEM_INITIALIZER(_CONCAT(_zbus_chan_data_, _name).sem, 1, 1), \
324 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, \
325 (.highest_observer_priority = ZBUS_MIN_THREAD_PRIORITY,)) \
326 IF_ENABLED(CONFIG_ZBUS_RUNTIME_OBSERVERS, \
327 (.observers = SYS_SLIST_STATIC_INIT( \
328 &_CONCAT(_zbus_chan_data_, _name).observers),)) \
329 IF_ENABLED(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION, \
330 (.msg_subscriber_pool = NULL,)) \
331 }; \
332 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_channel, _name) = { \
333 ZBUS_CHANNEL_NAME_INIT(_name) /* Maybe removed */ \
334 IF_ENABLED(CONFIG_ZBUS_CHANNEL_ID, (.id = _id,)) \
335 .message = &_ZBUS_MESSAGE_NAME(_name), \
336 .message_size = sizeof(_type), \
337 .user_data = _user_data, \
338 .validator = _validator, \
339 .data = &_CONCAT(_zbus_chan_data_, _name), \
340 }
341/* clang-format on */
342
344
345/* clang-format off */
346
358#define ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, _masked, _prio) \
359 const STRUCT_SECTION_ITERABLE(zbus_channel_observation, \
360 _CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs))) = { \
361 .chan = &_chan, \
362 .obs = &_obs, \
363 }; \
364 STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask, \
365 _CONCAT(_CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs)), \
366 _mask)) = {.enabled = _masked}
367/* clang-format on */
368
379#define ZBUS_CHAN_ADD_OBS(_chan, _obs, _prio) ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, false, _prio)
380
386#define ZBUS_OBS_DECLARE(...) FOR_EACH_NONEMPTY_TERM(_ZBUS_OBS_EXTERN, (;), __VA_ARGS__)
387
393#define ZBUS_CHAN_DECLARE(...) FOR_EACH(_ZBUS_CHAN_EXTERN, (;), __VA_ARGS__)
394
399#define ZBUS_OBSERVERS_EMPTY
400
406#define ZBUS_OBSERVERS(...) __VA_ARGS__
407
412#define ZBUS_CHAN_ID_INVALID UINT32_MAX
413
429#define ZBUS_CHAN_DEFINE(_name, _type, _validator, _user_data, _observers, _init_val) \
430 static _type _ZBUS_MESSAGE_NAME(_name) = _init_val; \
431 _ZBUS_CHAN_DEFINE(_name, ZBUS_CHAN_ID_INVALID, _type, _validator, _user_data); \
432 /* Extern declaration of observers */ \
433 ZBUS_OBS_DECLARE(_observers); \
434 /* Create all channel observations from observers list */ \
435 FOR_EACH_FIXED_ARG_NONEMPTY_TERM(_ZBUS_CHAN_OBSERVATION, (;), _name, _observers)
436
453#define ZBUS_CHAN_DEFINE_WITH_ID(_name, _id, _type, _validator, _user_data, _observers, _init_val) \
454 static _type _ZBUS_MESSAGE_NAME(_name) = _init_val; \
455 _ZBUS_CHAN_DEFINE(_name, _id, _type, _validator, _user_data); \
456 /* Extern declaration of observers */ \
457 ZBUS_OBS_DECLARE(_observers); \
458 /* Create all channel observations from observers list */ \
459 FOR_EACH_FIXED_ARG_NONEMPTY_TERM(_ZBUS_CHAN_OBSERVATION, (;), _name, _observers)
460
470#define ZBUS_MSG_INIT(_val, ...) {_val, ##__VA_ARGS__}
471
472/* clang-format off */
473
485#define ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, _enable) \
486 K_MSGQ_DEFINE_STATIC_TYPE(_zbus_observer_queue_##_name, \
487 struct zbus_channel *, _queue_size \
488 ); \
489 static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = { \
490 .enabled = _enable, \
491 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, ( \
492 .priority = ZBUS_MIN_THREAD_PRIORITY, \
493 )) \
494 }; \
495 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
496 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
497 .type = ZBUS_OBSERVER_SUBSCRIBER_TYPE, \
498 .data = &_CONCAT(_zbus_obs_data_, _name), \
499 .queue = &_zbus_observer_queue_##_name, \
500 }
501/* clang-format on */
502
514#define ZBUS_SUBSCRIBER_DEFINE(_name, _queue_size) \
515 ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, true)
516
517/* clang-format off */
518
530#define ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, _enable) \
531 static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = { \
532 .enabled = _enable, \
533 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, ( \
534 .priority = ZBUS_MIN_THREAD_PRIORITY, \
535 )) \
536 }; \
537 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
538 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
539 .type = ZBUS_OBSERVER_LISTENER_TYPE, \
540 .data = &_CONCAT(_zbus_obs_data_, _name), \
541 .callback = (_cb) \
542 }
543/* clang-format on */
544
555#define ZBUS_LISTENER_DEFINE(_name, _cb) ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, true)
556
557/* clang-format off */
558
569#define ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _enable) \
570 static K_FIFO_DEFINE(_zbus_observer_fifo_##_name); \
571 static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = { \
572 .enabled = _enable, \
573 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, ( \
574 .priority = ZBUS_MIN_THREAD_PRIORITY, \
575 )) \
576 }; \
577 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
578 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
579 .type = ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE, \
580 .data = &_CONCAT(_zbus_obs_data_, _name), \
581 .message_fifo = &_zbus_observer_fifo_##_name, \
582 }
583/* clang-format on */
584
596#define ZBUS_MSG_SUBSCRIBER_DEFINE(_name) ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, true)
597
598#if defined(CONFIG_ZBUS_ASYNC_LISTENER) || defined(__DOXYGEN__)
600struct zbus_async_listener_work {
601 struct k_work work;
602 struct k_fifo *message_fifo;
603 struct k_work_q *queue;
604 void (*callback)(const struct zbus_channel *chan, const void *msg);
605};
606
607void async_listener_work_handler(struct k_work *item);
609
610/* clang-format off */
624#define ZBUS_ASYNC_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, _enable) \
625 static K_FIFO_DEFINE(_zbus_observer_work_fifo_##_name); \
626 static struct zbus_async_listener_work _zbus_observer_work_##_name = { \
627 .work = Z_WORK_INITIALIZER(async_listener_work_handler), \
628 .message_fifo = &_CONCAT(_zbus_observer_work_fifo_, _name), \
629 .queue = &k_sys_work_q, \
630 .callback = _cb, \
631 }; \
632 static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = { \
633 .enabled = _enable, \
634 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, ( \
635 .priority = ZBUS_MIN_THREAD_PRIORITY, \
636 )) \
637 }; \
638 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
639 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
640 .type = ZBUS_OBSERVER_ASYNC_LISTENER_TYPE, \
641 .data = &_CONCAT(_zbus_obs_data_, _name), \
642 .work = &_CONCAT(_zbus_observer_work_, _name).work, \
643 }
644
657#define ZBUS_ASYNC_LISTENER_DEFINE(_name, _cb) \
658 ZBUS_ASYNC_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, true)
659/* clang-format on */
660
677static inline int zbus_async_listener_set_work_queue(const struct zbus_observer *obs,
678 struct k_work_q *queue)
679{
680 CHECKIF(obs == NULL) {
681 return -EINVAL;
682 }
683
685 return -EINVAL;
686 }
687
688 CHECKIF(queue == NULL) {
689 return -EINVAL;
690 }
691
692 static struct k_spinlock zbus_async_listener_slock;
693
694 K_SPINLOCK(&zbus_async_listener_slock) {
695 struct zbus_async_listener_work *async_listener =
696 CONTAINER_OF(obs->work, struct zbus_async_listener_work, work);
697
698 async_listener->queue = queue;
699 }
700 return 0;
701}
702
703#endif /* CONFIG_ZBUS_ASYNC_LISTENER */
704
726int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t timeout);
727
745int zbus_chan_read(const struct zbus_channel *chan, void *msg, k_timeout_t timeout);
746
768int zbus_chan_claim(const struct zbus_channel *chan, k_timeout_t timeout);
769
784int zbus_chan_finish(const struct zbus_channel *chan);
785
804int zbus_chan_notify(const struct zbus_channel *chan, k_timeout_t timeout);
805
806#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
807
819static inline const char *zbus_chan_name(const struct zbus_channel *chan)
820{
821 __ASSERT(chan != NULL, "chan is required");
822
823 return chan->name;
824}
825
826#endif
827
828#if defined(CONFIG_ZBUS_CHANNEL_ID) || defined(__DOXYGEN__)
829
840const struct zbus_channel *zbus_chan_from_id(uint32_t channel_id);
841
842#endif
843
844#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
845
856const struct zbus_channel *zbus_chan_from_name(const char *name);
857
858#endif
859
860#if defined(CONFIG_ZBUS_RUNTIME_CHANNEL_REGISTRATION) || defined(__DOXYGEN__)
861
875static inline void zbus_runtime_channel_init(struct zbus_runtime_channel *chan,
876 struct zbus_channel_data *data, const char *name,
877 uint32_t id, zbus_validator validator, void *message,
878 size_t message_size, void *user_data)
879{
880 __ASSERT(chan != NULL, "chan is required");
881 __ASSERT(data != NULL, "data is required");
882 __ASSERT(message != NULL, "message is required");
883 __ASSERT(message_size > 0, "message_size must be positive");
884#if defined(CONFIG_ZBUS_CHANNEL_NAME)
885 __ASSERT(name != NULL, "name is required");
886 chan->channel.name = name;
887#endif
888#if defined(CONFIG_ZBUS_CHANNEL_ID)
889 chan->channel.id = id;
890#endif
891 chan->channel.data = data;
892 chan->channel.message = message;
893 chan->channel.message_size = message_size;
894 chan->channel.validator = validator;
895 chan->channel.user_data = user_data;
896
897 memset(data, 0x00, sizeof(*data));
898#if defined(CONFIG_ZBUS_PRIORITY_BOOST)
899 data->highest_observer_priority = ZBUS_MIN_THREAD_PRIORITY;
900#endif
901 k_sem_init(&data->sem, 1, 1);
902}
903
917
931
932#if defined(CONFIG_ZTEST)
933
937void zbus_runtime_channel_unregister_all(void);
938
939#endif /* CONFIG_ZTEST */
940
941#endif /* CONFIG_ZBUS_RUNTIME_CHANNEL_REGISTRATION */
942
955static inline void *zbus_chan_msg(const struct zbus_channel *chan)
956{
957 __ASSERT(chan != NULL, "chan is required");
958
959 return chan->message;
960}
961
976static inline const void *zbus_chan_const_msg(const struct zbus_channel *chan)
977{
978 __ASSERT(chan != NULL, "chan is required");
979
980 return chan->message;
981}
982
992static inline uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
993{
994 __ASSERT(chan != NULL, "chan is required");
995
996 return chan->message_size;
997}
998
1008static inline void *zbus_chan_user_data(const struct zbus_channel *chan)
1009{
1010 __ASSERT(chan != NULL, "chan is required");
1011
1012 return chan->user_data;
1013}
1014
1015#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION) || defined(__DOXYGEN__)
1016
1025static inline void zbus_chan_set_msg_sub_pool(const struct zbus_channel *chan,
1026 struct net_buf_pool *pool)
1027{
1028 __ASSERT(chan != NULL, "chan is required");
1029 __ASSERT(pool != NULL, "pool is required");
1030
1031 chan->data->msg_subscriber_pool = pool;
1032}
1033
1034#endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */
1035
1036#if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) || defined(__DOXYGEN__)
1037
1051static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan)
1052{
1053 __ASSERT(chan != NULL, "chan is required");
1054
1055 chan->data->publish_timestamp = k_uptime_ticks();
1056 chan->data->publish_count += 1;
1057}
1058
1071{
1072 __ASSERT(chan != NULL, "chan is required");
1073
1074 return chan->data->publish_timestamp;
1075}
1076
1088static inline uint32_t zbus_chan_pub_stats_count(const struct zbus_channel *chan)
1089{
1090 __ASSERT(chan != NULL, "chan is required");
1091
1092 return chan->data->publish_count;
1093}
1094
1107{
1108 __ASSERT(chan != NULL, "chan is required");
1109
1110 /* Not yet published, period = 0ms */
1111 if (chan->data->publish_count == 0) {
1112 return 0;
1113 }
1114 /* Average period across application runtime */
1115 return k_uptime_get() / chan->data->publish_count;
1116}
1117
1128static inline uint64_t zbus_chan_pub_stats_msg_age(const struct zbus_channel *chan)
1129{
1130 if (zbus_chan_pub_stats_count(chan) == 0) {
1131 return UINT64_MAX;
1132 }
1134}
1135
1136#else
1137
1138static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan)
1139{
1140 (void)chan;
1141}
1142
1143#endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */
1144
1145#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
1146
1154 const struct zbus_observer *obs;
1155#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE)
1156 const struct zbus_channel *chan;
1157#endif
1158};
1159
1160#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE) || defined(__DOXYGEN__)
1182int zbus_chan_add_obs_with_node(const struct zbus_channel *chan, const struct zbus_observer *obs,
1183 struct zbus_observer_node *node, k_timeout_t timeout);
1184#else
1185static inline int zbus_chan_add_obs_with_node(const struct zbus_channel *chan,
1186 const struct zbus_observer *obs,
1187 struct zbus_observer_node *node, k_timeout_t timeout)
1188{
1189 ARG_UNUSED(chan);
1190 ARG_UNUSED(obs);
1191 ARG_UNUSED(node);
1192 ARG_UNUSED(timeout);
1193
1194 return -ENOTSUP;
1195}
1196#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE */
1197
1198#if !defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE) || defined(__DOXYGEN__)
1219int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
1220 k_timeout_t timeout);
1221#else
1222static inline int zbus_chan_add_obs(const struct zbus_channel *chan,
1223 const struct zbus_observer *obs, k_timeout_t timeout)
1224{
1225 ARG_UNUSED(chan);
1226 ARG_UNUSED(obs);
1227 ARG_UNUSED(timeout);
1228
1229 return -ENOTSUP;
1230}
1231
1232#endif /* !CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE */
1250int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
1251 k_timeout_t timeout);
1252
1253#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
1254
1268int zbus_obs_set_enable(const struct zbus_observer *obs, bool enabled);
1269
1280static inline int zbus_obs_is_enabled(const struct zbus_observer *obs, bool *enable)
1281{
1282 _ZBUS_ASSERT(obs != NULL, "obs is required");
1283 _ZBUS_ASSERT(enable != NULL, "enable is required");
1284
1285 *enable = obs->data->enabled;
1286
1287 return 0;
1288}
1289
1305 const struct zbus_channel *chan, bool masked);
1306
1320 const struct zbus_channel *chan, bool *masked);
1321
1322#if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
1323
1335static inline const char *zbus_obs_name(const struct zbus_observer *obs)
1336{
1337 __ASSERT(obs != NULL, "obs is required");
1338
1339 return obs->name;
1340}
1341
1342#endif
1343
1344#if defined(CONFIG_ZBUS_PRIORITY_BOOST) || defined(__DOXYGEN__)
1345
1358
1371
1372#endif /* CONFIG_ZBUS_PRIORITY_BOOST */
1373
1392int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan,
1393 k_timeout_t timeout);
1394
1395#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
1396
1417int zbus_sub_wait_msg(const struct zbus_observer *sub, const struct zbus_channel **chan, void *msg,
1418 k_timeout_t timeout);
1419
1420#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
1421
1435bool zbus_iterate_over_channels(bool (*iterator_func)(const struct zbus_channel *chan));
1451 bool (*iterator_func)(const struct zbus_channel *chan, void *user_data), void *user_data);
1452
1466bool zbus_iterate_over_observers(bool (*iterator_func)(const struct zbus_observer *obs));
1482 bool (*iterator_func)(const struct zbus_observer *obs, void *user_data), void *user_data);
1483
1487
1488#ifdef __cplusplus
1489}
1490#endif
1491
1492#endif /* ZEPHYR_INCLUDE_ZBUS_ZBUS_H_ */
Header file for configurable error checking.
int64_t k_uptime_ticks(void)
Get system uptime, in system ticks.
uint32_t k_ticks_t
Tick precision used in timeout APIs.
Definition clock.h:48
static int64_t k_uptime_get(void)
Get system uptime.
Definition kernel.h:2265
int k_sem_init(struct k_sem *sem, unsigned int initial_count, unsigned int limit)
Initialize a semaphore.
struct _slist sys_slist_t
Single-linked list structure.
Definition slist.h:54
struct _snode sys_snode_t
Single-linked list node structure.
Definition slist.h:44
#define K_SPINLOCK(lck)
Guards a code block with the given spinlock, automatically acquiring the lock before executing the co...
Definition spinlock.h:457
#define CONTAINER_OF(ptr, type, field)
Get a pointer to a structure containing the element.
Definition util.h:281
#define CHECKIF(expr)
Guard error-handling code with a configurable check.
Definition check.h:54
#define EINVAL
Invalid argument.
Definition errno.h:61
#define ENOTSUP
Unsupported value.
Definition errno.h:115
#define k_ticks_to_ms_floor64(t)
Convert ticks to milliseconds.
Definition time_units.h:1734
int zbus_chan_claim(const struct zbus_channel *chan, k_timeout_t timeout)
Claim a channel.
static const char * zbus_chan_name(const struct zbus_channel *chan)
Get the channel's name.
Definition zbus.h:819
static uint32_t zbus_chan_pub_stats_avg_period(const struct zbus_channel *chan)
Get the average period between publishes to a channel.
Definition zbus.h:1106
bool zbus_iterate_over_observers_with_user_data(bool(*iterator_func)(const struct zbus_observer *obs, void *user_data), void *user_data)
Iterate over observers with user data.
bool zbus_iterate_over_observers(bool(*iterator_func)(const struct zbus_observer *obs))
Iterate over observers.
static int zbus_obs_is_enabled(const struct zbus_observer *obs, bool *enable)
Get the observer state.
Definition zbus.h:1280
static void zbus_chan_set_msg_sub_pool(const struct zbus_channel *chan, struct net_buf_pool *pool)
Set the channel's msg subscriber net_buf pool.
Definition zbus.h:1025
int zbus_obs_is_chan_notification_masked(const struct zbus_observer *obs, const struct zbus_channel *chan, bool *masked)
Get the notifications masking state from a channel to an observer.
bool(* zbus_validator)(const void *msg, size_t msg_size)
Check validity of message before publishing.
Definition zbus.h:91
int zbus_obs_detach_from_thread(const struct zbus_observer *obs)
Clear the observer thread priority by detaching it from a thread.
const struct zbus_channel * zbus_chan_from_name(const char *name)
Retrieve a zbus channel from its name string.
static uint64_t zbus_chan_pub_stats_msg_age(const struct zbus_channel *chan)
Get the age of a message in a channel.
Definition zbus.h:1128
static int zbus_async_listener_set_work_queue(const struct zbus_observer *obs, struct k_work_q *queue)
Set the work queue for an async listener.
Definition zbus.h:677
static uint32_t zbus_chan_pub_stats_count(const struct zbus_channel *chan)
Get the number of times a channel has been published to.
Definition zbus.h:1088
static const char * zbus_obs_name(const struct zbus_observer *obs)
Get the observer's name.
Definition zbus.h:1335
bool zbus_iterate_over_channels(bool(*iterator_func)(const struct zbus_channel *chan))
Iterate over channels.
int zbus_chan_notify(const struct zbus_channel *chan, k_timeout_t timeout)
Force a channel notification.
int zbus_chan_add_obs_with_node(const struct zbus_channel *chan, const struct zbus_observer *obs, struct zbus_observer_node *node, k_timeout_t timeout)
Add an observer to a channel.
int zbus_chan_finish(const struct zbus_channel *chan)
Finish a channel claim.
int zbus_runtime_channel_register(struct zbus_runtime_channel *chan)
Register a runtime channel with the ZBus infrastructure.
int zbus_chan_read(const struct zbus_channel *chan, void *msg, k_timeout_t timeout)
Read a channel.
int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan, k_timeout_t timeout)
Wait for a channel notification.
zbus_observer_type
Type used to represent an observer type.
Definition zbus.h:148
static uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
Get the channel's message size.
Definition zbus.h:992
int zbus_obs_set_chan_notification_mask(const struct zbus_observer *obs, const struct zbus_channel *chan, bool masked)
Mask notifications from a channel to an observer.
int zbus_obs_set_enable(const struct zbus_observer *obs, bool enabled)
Change the observer state.
static void * zbus_chan_msg(const struct zbus_channel *chan)
Get the reference for a channel message directly.
Definition zbus.h:955
bool zbus_iterate_over_channels_with_user_data(bool(*iterator_func)(const struct zbus_channel *chan, void *user_data), void *user_data)
Iterate over channels with user data.
int zbus_obs_attach_to_thread(const struct zbus_observer *obs)
Set the observer thread priority by attaching it to a thread.
static void * zbus_chan_user_data(const struct zbus_channel *chan)
Get the channel's user data.
Definition zbus.h:1008
static k_ticks_t zbus_chan_pub_stats_last_time(const struct zbus_channel *chan)
Get the time a channel was last published to.
Definition zbus.h:1070
const struct zbus_channel * zbus_chan_from_id(uint32_t channel_id)
Retrieve a zbus channel from its numeric identifier.
int zbus_runtime_channel_unregister(struct zbus_runtime_channel *chan)
Unregister a runtime channel from the ZBus infrastructure.
int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs, k_timeout_t timeout)
Add an observer to a channel.
int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t timeout)
Publish to a channel.
int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs, k_timeout_t timeout)
Remove an observer from a channel.
static void zbus_chan_pub_stats_update(const struct zbus_channel *chan)
Update the publishing statistics for a channel.
Definition zbus.h:1051
int zbus_sub_wait_msg(const struct zbus_observer *sub, const struct zbus_channel **chan, void *msg, k_timeout_t timeout)
Wait for a channel message.
static void zbus_runtime_channel_init(struct zbus_runtime_channel *chan, struct zbus_channel_data *data, const char *name, uint32_t id, zbus_validator validator, void *message, size_t message_size, void *user_data)
Initialise a ZBus runtime channel structure.
Definition zbus.h:875
static const void * zbus_chan_const_msg(const struct zbus_channel *chan)
Get a constant reference for a channel message directly.
Definition zbus.h:976
@ ZBUS_OBSERVER_LISTENER_TYPE
Definition zbus.h:149
@ ZBUS_OBSERVER_ASYNC_LISTENER_TYPE
Definition zbus.h:152
@ ZBUS_OBSERVER_SUBSCRIBER_TYPE
Definition zbus.h:150
@ ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE
Definition zbus.h:151
#define NULL
Definition iar_missing_defs.h:20
Public kernel APIs.
#define bool
Definition stdbool.h:13
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINT64_TYPE__ uint64_t
Definition stdint.h:91
#define UINT64_MAX
Definition stdint.h:30
__UINT16_TYPE__ uint16_t
Definition stdint.h:89
__INT16_TYPE__ int16_t
Definition stdint.h:73
void * memset(void *buf, int c, size_t n)
Kernel FIFO structure.
Definition kernel.h:3023
Message Queue Structure.
Definition kernel.h:5316
Semaphore structure.
Definition kernel.h:3798
Kernel Spin Lock.
Definition spinlock.h:45
Kernel timeout type.
Definition clock.h:65
Kernel workqueue structure.
Definition kernel.h:4906
A structure used to submit work.
Definition kernel.h:4708
Network buffer pool representation.
Definition net_buf.h:1184
Type used to represent a channel mutable data.
Definition zbus.h:33
Type used to represent a channel.
Definition zbus.h:99
Structure used to register runtime observers.
Definition zbus.h:1152
const struct zbus_observer * obs
Definition zbus.h:1154
sys_snode_t node
Definition zbus.h:1153
Type used to represent an observer.
Definition zbus.h:182
Type used to represent a runtime channel.
Definition zbus.h:136
struct zbus_channel channel
Refer to zbus_channel.
Definition zbus.h:138
Iterable sections helpers.