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
38
43
47 struct k_sem sem;
48
49#if defined(CONFIG_ZBUS_PRIORITY_BOOST)
53 int highest_observer_priority;
54#endif /* CONFIG_ZBUS_PRIORITY_BOOST */
55
56#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
61#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
62
63#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION) || defined(__DOXYGEN__)
68#endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */
69
70#if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) || defined(__DOXYGEN__)
75#endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */
76};
77
87typedef bool (*zbus_validator)(const void *msg, size_t msg_size);
88
96#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
98 const char *name;
99#endif
100#if defined(CONFIG_ZBUS_CHANNEL_ID) || defined(__DOXYGEN__)
103#endif
107 void *message;
108
111
116
122
125};
126
136
148
152
153#if defined(CONFIG_ZBUS_PRIORITY_BOOST)
155 int priority;
156#endif /* CONFIG_ZBUS_PRIORITY_BOOST */
157};
158
175#if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
177 const char *name;
178#endif
181
184
185 union {
187 struct k_msgq *queue;
188
190 void (*callback)(const struct zbus_channel *chan);
191
192#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
197#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
198
199#if defined(CONFIG_ZBUS_ASYNC_LISTENER) || defined(__DOXYGEN__)
203 struct k_work *work;
204#endif /* CONFIG_ZBUS_ASYNC_LISTENER */
205 };
206};
207
209struct zbus_channel_observation_mask {
210 bool enabled;
211};
212
216struct zbus_channel_observation {
217 const struct zbus_channel *chan;
218 const struct zbus_observer *obs;
219};
220
221#ifdef __cplusplus
222#define _ZBUS_CPP_EXTERN extern
223#else
224#define _ZBUS_CPP_EXTERN
225#endif /* __cplusplus */
226
227#define ZBUS_MIN_THREAD_PRIORITY (CONFIG_NUM_PREEMPT_PRIORITIES - 1)
228
229#if defined(CONFIG_ZBUS_ASSERT_MOCK)
230#define _ZBUS_ASSERT(_cond, _fmt, ...) \
231 do { \
232 if (!(_cond)) { \
233 printk("ZBUS ASSERT: "); \
234 printk(_fmt, ##__VA_ARGS__); \
235 printk("\n"); \
236 return -EFAULT; \
237 } \
238 } while (0)
239#else
240#define _ZBUS_ASSERT(_cond, _fmt, ...) __ASSERT(_cond, _fmt, ##__VA_ARGS__)
241#endif
242
243#if defined(CONFIG_ZBUS_CHANNEL_NAME)
244#define ZBUS_CHANNEL_NAME_INIT(_name) .name = #_name,
245#define _ZBUS_CHAN_NAME(_chan) (_chan)->name
246#else
247#define ZBUS_CHANNEL_NAME_INIT(_name)
248#define _ZBUS_CHAN_NAME(_chan) ""
249#endif
250
251#if defined(CONFIG_ZBUS_OBSERVER_NAME)
252#define ZBUS_OBSERVER_NAME_INIT(_name) .name = #_name,
253#define _ZBUS_OBS_NAME(_obs) (_obs)->name
254#else
255#define ZBUS_OBSERVER_NAME_INIT(_name)
256#define _ZBUS_OBS_NAME(_obs) ""
257#endif
258
259#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS)
260#define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name) static sys_slist_t _slist_name
261#define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) .runtime_observers = &_slist_name,
262#else
263#define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name)
264#define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) /* No runtime observers */
265#endif
266
267#define _ZBUS_OBS_EXTERN(_name) extern const struct zbus_observer _name
268
269#define _ZBUS_CHAN_EXTERN(_name) extern const struct zbus_channel _name
270
271#define ZBUS_REF(_value) &(_value)
272
273#define FOR_EACH_FIXED_ARG_NONEMPTY_TERM(F, sep, fixed_arg, ...) \
274 COND_CODE_0(/* are there zero non-empty arguments ? */ \
275 NUM_VA_ARGS_LESS_1( \
276 LIST_DROP_EMPTY(__VA_ARGS__, _)), /* if so, expand to nothing */ \
277 (), /* otherwise, expand to: */ \
278 (FOR_EACH_IDX_FIXED_ARG( \
279 F, sep, fixed_arg, \
280 LIST_DROP_EMPTY(__VA_ARGS__)) /* plus a final terminator */ \
281 __DEBRACKET sep))
282
283#define _ZBUS_OBSERVATION_PREFIX(_idx) \
284 GET_ARG_N(_idx, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, \
285 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, \
286 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, \
287 58, 59, 60, 61, 62, 63)
288
289#define _ZBUS_CHAN_OBSERVATION(_idx, _obs, _chan) \
290 const STRUCT_SECTION_ITERABLE( \
291 zbus_channel_observation, \
292 _CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx)))) = {.chan = &_chan, \
293 .obs = &_obs}; \
294 STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask, \
295 _CONCAT(_CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx))), \
296 _mask)) = {.enabled = false};
297
298#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
299#define _ZBUS_RUNTIME_OBSERVERS(_name) .observers = &(_CONCAT(_observers_, _name)),
300#define _ZBUS_RUNTIME_OBSERVERS_DECL(_name) static sys_slist_t _CONCAT(_observers_, _name);
301#else
302#define _ZBUS_RUNTIME_OBSERVERS(_name)
303#define _ZBUS_RUNTIME_OBSERVERS_DECL(_name)
304#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
305
306#define _ZBUS_MESSAGE_NAME(_name) _CONCAT(_zbus_message_, _name)
307
308/* clang-format off */
309#define _ZBUS_CHAN_DEFINE(_name, _id, _type, _validator, _user_data) \
310 static struct zbus_channel_data _CONCAT(_zbus_chan_data_, _name) = { \
311 .observers_start_idx = -1, \
312 .observers_end_idx = -1, \
313 .sem = Z_SEM_INITIALIZER(_CONCAT(_zbus_chan_data_, _name).sem, 1, 1), \
314 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, \
315 (.highest_observer_priority = ZBUS_MIN_THREAD_PRIORITY,)) \
316 IF_ENABLED(CONFIG_ZBUS_RUNTIME_OBSERVERS, \
317 (.observers = SYS_SLIST_STATIC_INIT( \
318 &_CONCAT(_zbus_chan_data_, _name).observers),)) \
319 IF_ENABLED(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION, \
320 (.msg_subscriber_pool = NULL,)) \
321 }; \
322 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_channel, _name) = { \
323 ZBUS_CHANNEL_NAME_INIT(_name) /* Maybe removed */ \
324 IF_ENABLED(CONFIG_ZBUS_CHANNEL_ID, (.id = _id,)) \
325 .message = &_ZBUS_MESSAGE_NAME(_name), \
326 .message_size = sizeof(_type), \
327 .user_data = _user_data, \
328 .validator = _validator, \
329 .data = &_CONCAT(_zbus_chan_data_, _name), \
330 }
331/* clang-format on */
332
334
335/* clang-format off */
336
348#define ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, _masked, _prio) \
349 const STRUCT_SECTION_ITERABLE(zbus_channel_observation, \
350 _CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs))) = { \
351 .chan = &_chan, \
352 .obs = &_obs, \
353 }; \
354 STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask, \
355 _CONCAT(_CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs)), \
356 _mask)) = {.enabled = _masked}
357/* clang-format on */
358
369#define ZBUS_CHAN_ADD_OBS(_chan, _obs, _prio) ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, false, _prio)
370
376#define ZBUS_OBS_DECLARE(...) FOR_EACH_NONEMPTY_TERM(_ZBUS_OBS_EXTERN, (;), __VA_ARGS__)
377
383#define ZBUS_CHAN_DECLARE(...) FOR_EACH(_ZBUS_CHAN_EXTERN, (;), __VA_ARGS__)
384
389#define ZBUS_OBSERVERS_EMPTY
390
396#define ZBUS_OBSERVERS(...) __VA_ARGS__
397
402#define ZBUS_CHAN_ID_INVALID UINT32_MAX
403
419#define ZBUS_CHAN_DEFINE(_name, _type, _validator, _user_data, _observers, _init_val) \
420 static _type _ZBUS_MESSAGE_NAME(_name) = _init_val; \
421 _ZBUS_CHAN_DEFINE(_name, ZBUS_CHAN_ID_INVALID, _type, _validator, _user_data); \
422 /* Extern declaration of observers */ \
423 ZBUS_OBS_DECLARE(_observers); \
424 /* Create all channel observations from observers list */ \
425 FOR_EACH_FIXED_ARG_NONEMPTY_TERM(_ZBUS_CHAN_OBSERVATION, (;), _name, _observers)
426
443#define ZBUS_CHAN_DEFINE_WITH_ID(_name, _id, _type, _validator, _user_data, _observers, _init_val) \
444 static _type _ZBUS_MESSAGE_NAME(_name) = _init_val; \
445 _ZBUS_CHAN_DEFINE(_name, _id, _type, _validator, _user_data); \
446 /* Extern declaration of observers */ \
447 ZBUS_OBS_DECLARE(_observers); \
448 /* Create all channel observations from observers list */ \
449 FOR_EACH_FIXED_ARG_NONEMPTY_TERM(_ZBUS_CHAN_OBSERVATION, (;), _name, _observers)
450
460#define ZBUS_MSG_INIT(_val, ...) {_val, ##__VA_ARGS__}
461
462/* clang-format off */
463
475#define ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, _enable) \
476 K_MSGQ_DEFINE(_zbus_observer_queue_##_name, \
477 sizeof(struct zbus_channel *), \
478 _queue_size, sizeof(struct zbus_channel *) \
479 ); \
480 static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = { \
481 .enabled = _enable, \
482 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, ( \
483 .priority = ZBUS_MIN_THREAD_PRIORITY, \
484 )) \
485 }; \
486 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
487 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
488 .type = ZBUS_OBSERVER_SUBSCRIBER_TYPE, \
489 .data = &_CONCAT(_zbus_obs_data_, _name), \
490 .queue = &_zbus_observer_queue_##_name, \
491 }
492/* clang-format on */
493
505#define ZBUS_SUBSCRIBER_DEFINE(_name, _queue_size) \
506 ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, true)
507
508/* clang-format off */
509
521#define ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, _enable) \
522 static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = { \
523 .enabled = _enable, \
524 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, ( \
525 .priority = ZBUS_MIN_THREAD_PRIORITY, \
526 )) \
527 }; \
528 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
529 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
530 .type = ZBUS_OBSERVER_LISTENER_TYPE, \
531 .data = &_CONCAT(_zbus_obs_data_, _name), \
532 .callback = (_cb) \
533 }
534/* clang-format on */
535
546#define ZBUS_LISTENER_DEFINE(_name, _cb) ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, true)
547
548/* clang-format off */
549
560#define ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _enable) \
561 static K_FIFO_DEFINE(_zbus_observer_fifo_##_name); \
562 static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = { \
563 .enabled = _enable, \
564 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, ( \
565 .priority = ZBUS_MIN_THREAD_PRIORITY, \
566 )) \
567 }; \
568 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
569 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
570 .type = ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE, \
571 .data = &_CONCAT(_zbus_obs_data_, _name), \
572 .message_fifo = &_zbus_observer_fifo_##_name, \
573 }
574/* clang-format on */
575
587#define ZBUS_MSG_SUBSCRIBER_DEFINE(_name) ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, true)
588
589#if defined(CONFIG_ZBUS_ASYNC_LISTENER) || defined(__DOXYGEN__)
591struct zbus_async_listener_work {
592 struct k_work work;
593 struct k_fifo *message_fifo;
594 struct k_work_q *queue;
595 void (*callback)(const struct zbus_channel *chan, const void *msg);
596};
597
598void async_listener_work_handler(struct k_work *item);
600
601/* clang-format off */
615#define ZBUS_ASYNC_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, _enable) \
616 static K_FIFO_DEFINE(_zbus_observer_work_fifo_##_name); \
617 static struct zbus_async_listener_work _zbus_observer_work_##_name = { \
618 .work = Z_WORK_INITIALIZER(async_listener_work_handler), \
619 .message_fifo = &_CONCAT(_zbus_observer_work_fifo_, _name), \
620 .queue = &k_sys_work_q, \
621 .callback = _cb, \
622 }; \
623 static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = { \
624 .enabled = _enable, \
625 IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, ( \
626 .priority = ZBUS_MIN_THREAD_PRIORITY, \
627 )) \
628 }; \
629 _ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
630 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
631 .type = ZBUS_OBSERVER_ASYNC_LISTENER_TYPE, \
632 .data = &_CONCAT(_zbus_obs_data_, _name), \
633 .work = &_CONCAT(_zbus_observer_work_, _name).work, \
634 }
635
648#define ZBUS_ASYNC_LISTENER_DEFINE(_name, _cb) \
649 ZBUS_ASYNC_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, true)
650/* clang-format on */
651
668static inline int zbus_async_listener_set_work_queue(const struct zbus_observer *obs,
669 struct k_work_q *queue)
670{
671 CHECKIF(obs == NULL) {
672 return -EINVAL;
673 }
674
676 return -EINVAL;
677 }
678
679 CHECKIF(queue == NULL) {
680 return -EINVAL;
681 }
682
683 static struct k_spinlock zbus_async_listener_slock;
684
685 K_SPINLOCK(&zbus_async_listener_slock) {
686 struct zbus_async_listener_work *async_listener =
687 CONTAINER_OF(obs->work, struct zbus_async_listener_work, work);
688
689 async_listener->queue = queue;
690 }
691 return 0;
692}
693
694#endif /* CONFIG_ZBUS_ASYNC_LISTENER */
695
717int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t timeout);
718
736int zbus_chan_read(const struct zbus_channel *chan, void *msg, k_timeout_t timeout);
737
759int zbus_chan_claim(const struct zbus_channel *chan, k_timeout_t timeout);
760
775int zbus_chan_finish(const struct zbus_channel *chan);
776
795int zbus_chan_notify(const struct zbus_channel *chan, k_timeout_t timeout);
796
797#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
798
808static inline const char *zbus_chan_name(const struct zbus_channel *chan)
809{
810 __ASSERT(chan != NULL, "chan is required");
811
812 return chan->name;
813}
814
815#endif
816
817#if defined(CONFIG_ZBUS_CHANNEL_ID) || defined(__DOXYGEN__)
818
827const struct zbus_channel *zbus_chan_from_id(uint32_t channel_id);
828
829#endif
830
831#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
832
841const struct zbus_channel *zbus_chan_from_name(const char *name);
842
843#endif
844
845#if defined(CONFIG_ZBUS_RUNTIME_CHANNEL_REGISTRATION) || defined(__DOXYGEN__)
846
860static inline void zbus_runtime_channel_init(struct zbus_runtime_channel *chan,
861 struct zbus_channel_data *data, const char *name,
863 size_t message_size, void *user_data)
864{
865 __ASSERT(chan != NULL, "chan is required");
866 __ASSERT(data != NULL, "data is required");
867 __ASSERT(message != NULL, "message is required");
868 __ASSERT(message_size > 0, "message_size must be positive");
869#if defined(CONFIG_ZBUS_CHANNEL_NAME)
870 __ASSERT(name != NULL, "name is required");
871 chan->channel.name = name;
872#endif
873#if defined(CONFIG_ZBUS_CHANNEL_ID)
874 chan->channel.id = id;
875#endif
876 chan->channel.data = data;
877 chan->channel.message = message;
881
882 memset(data, 0x00, sizeof(*data));
883#if defined(CONFIG_ZBUS_PRIORITY_BOOST)
884 data->highest_observer_priority = ZBUS_MIN_THREAD_PRIORITY;
885#endif
886 k_sem_init(&data->sem, 1, 1);
887}
888
902
916
917#if defined(CONFIG_ZTEST)
918
922void zbus_runtime_channel_unregister_all(void);
923
924#endif /* CONFIG_ZTEST */
925
926#endif /* CONFIG_ZBUS_RUNTIME_CHANNEL_REGISTRATION */
927
940static inline void *zbus_chan_msg(const struct zbus_channel *chan)
941{
942 __ASSERT(chan != NULL, "chan is required");
943
944 return chan->message;
945}
946
961static inline const void *zbus_chan_const_msg(const struct zbus_channel *chan)
962{
963 __ASSERT(chan != NULL, "chan is required");
964
965 return chan->message;
966}
967
977static inline uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
978{
979 __ASSERT(chan != NULL, "chan is required");
980
981 return chan->message_size;
982}
983
993static inline void *zbus_chan_user_data(const struct zbus_channel *chan)
994{
995 __ASSERT(chan != NULL, "chan is required");
996
997 return chan->user_data;
998}
999
1000#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION) || defined(__DOXYGEN__)
1001
1008static inline void zbus_chan_set_msg_sub_pool(const struct zbus_channel *chan,
1009 struct net_buf_pool *pool)
1010{
1011 __ASSERT(chan != NULL, "chan is required");
1012 __ASSERT(pool != NULL, "pool is required");
1013
1014 chan->data->msg_subscriber_pool = pool;
1015}
1016
1017#endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */
1018
1019#if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) || defined(__DOXYGEN__)
1020
1032static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan)
1033{
1034 __ASSERT(chan != NULL, "chan is required");
1035
1037 chan->data->publish_count += 1;
1038}
1039
1050{
1051 __ASSERT(chan != NULL, "chan is required");
1052
1053 return chan->data->publish_timestamp;
1054}
1055
1065static inline uint32_t zbus_chan_pub_stats_count(const struct zbus_channel *chan)
1066{
1067 __ASSERT(chan != NULL, "chan is required");
1068
1069 return chan->data->publish_count;
1070}
1071
1082{
1083 __ASSERT(chan != NULL, "chan is required");
1084
1085 /* Not yet published, period = 0ms */
1086 if (chan->data->publish_count == 0) {
1087 return 0;
1088 }
1089 /* Average period across application runtime */
1090 return k_uptime_get() / chan->data->publish_count;
1091}
1092
1101static inline uint64_t zbus_chan_pub_stats_msg_age(const struct zbus_channel *chan)
1102{
1103 if (zbus_chan_pub_stats_count(chan) == 0) {
1104 return UINT64_MAX;
1105 }
1107}
1108
1109#else
1110
1111static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan)
1112{
1113 (void)chan;
1114}
1115
1116#endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */
1117
1118#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
1119
1126 const struct zbus_observer *obs;
1127#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE)
1128 const struct zbus_channel *chan;
1129#endif
1130};
1131
1132#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE) || defined(__DOXYGEN__)
1152int zbus_chan_add_obs_with_node(const struct zbus_channel *chan, const struct zbus_observer *obs,
1153 struct zbus_observer_node *node, k_timeout_t timeout);
1154#else
1155static inline int zbus_chan_add_obs_with_node(const struct zbus_channel *chan,
1156 const struct zbus_observer *obs,
1157 struct zbus_observer_node *node, k_timeout_t timeout)
1158{
1159 ARG_UNUSED(chan);
1160 ARG_UNUSED(obs);
1161 ARG_UNUSED(node);
1162 ARG_UNUSED(timeout);
1163
1164 return -ENOTSUP;
1165}
1166#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE */
1167
1168#if !defined(CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE) || defined(__DOXYGEN__)
1189int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
1190 k_timeout_t timeout);
1191#else
1192static inline int zbus_chan_add_obs(const struct zbus_channel *chan,
1193 const struct zbus_observer *obs, k_timeout_t timeout)
1194{
1195 ARG_UNUSED(chan);
1196 ARG_UNUSED(obs);
1197 ARG_UNUSED(timeout);
1198
1199 return -ENOTSUP;
1200}
1201
1202#endif /* !CONFIG_ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_NONE */
1218int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
1219 k_timeout_t timeout);
1220
1221#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
1222
1236int zbus_obs_set_enable(const struct zbus_observer *obs, bool enabled);
1237
1248static inline int zbus_obs_is_enabled(const struct zbus_observer *obs, bool *enable)
1249{
1250 _ZBUS_ASSERT(obs != NULL, "obs is required");
1251 _ZBUS_ASSERT(enable != NULL, "enable is required");
1252
1253 *enable = obs->data->enabled;
1254
1255 return 0;
1256}
1257
1273 const struct zbus_channel *chan, bool masked);
1274
1288 const struct zbus_channel *chan, bool *masked);
1289
1290#if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
1291
1301static inline const char *zbus_obs_name(const struct zbus_observer *obs)
1302{
1303 __ASSERT(obs != NULL, "obs is required");
1304
1305 return obs->name;
1306}
1307
1308#endif
1309
1310#if defined(CONFIG_ZBUS_PRIORITY_BOOST) || defined(__DOXYGEN__)
1311
1322
1333
1334#endif /* CONFIG_ZBUS_PRIORITY_BOOST */
1335
1354int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan,
1355 k_timeout_t timeout);
1356
1357#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
1358
1377int zbus_sub_wait_msg(const struct zbus_observer *sub, const struct zbus_channel **chan, void *msg,
1378 k_timeout_t timeout);
1379
1380#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
1381
1395bool zbus_iterate_over_channels(bool (*iterator_func)(const struct zbus_channel *chan));
1411 bool (*iterator_func)(const struct zbus_channel *chan, void *user_data), void *user_data);
1412
1426bool zbus_iterate_over_observers(bool (*iterator_func)(const struct zbus_observer *obs));
1442 bool (*iterator_func)(const struct zbus_observer *obs, void *user_data), void *user_data);
1443
1447
1448#ifdef __cplusplus
1449}
1450#endif
1451
1452#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:52
struct _snode sys_snode_t
Single-linked list node structure.
Definition slist.h:42
#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:52
#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:808
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:1081
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:1248
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:1008
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:87
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:1101
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:668
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:1065
static const char * zbus_obs_name(const struct zbus_observer *obs)
Get the observer's name.
Definition zbus.h:1301
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:142
static uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
Get the channel's message size.
Definition zbus.h:977
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:940
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:993
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:1049
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:1032
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:860
static const void * zbus_chan_const_msg(const struct zbus_channel *chan)
Get a constant reference for a channel message directly.
Definition zbus.h:961
@ ZBUS_OBSERVER_LISTENER_TYPE
Definition zbus.h:143
@ ZBUS_OBSERVER_ASYNC_LISTENER_TYPE
Definition zbus.h:146
@ ZBUS_OBSERVER_SUBSCRIBER_TYPE
Definition zbus.h:144
@ ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE
Definition zbus.h:145
#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:1151
Type used to represent a channel mutable data.
Definition zbus.h:33
k_ticks_t publish_timestamp
Kernel timestamp of the last publish action on this channel.
Definition zbus.h:72
struct net_buf_pool * msg_subscriber_pool
Net buf pool for message subscribers and async listeners.
Definition zbus.h:67
uint32_t publish_count
Number of times data has been published to this channel.
Definition zbus.h:74
int16_t observers_end_idx
Static channel observer list end index.
Definition zbus.h:42
int16_t observers_start_idx
Static channel observer list start index.
Definition zbus.h:37
struct k_sem sem
Access control semaphore.
Definition zbus.h:47
sys_slist_t observers
Channel observer list.
Definition zbus.h:60
Type used to represent a channel.
Definition zbus.h:95
zbus_validator validator
Message validator.
Definition zbus.h:121
void * user_data
User data available to extend zbus features.
Definition zbus.h:115
uint32_t id
Unique numeric channel identifier.
Definition zbus.h:102
struct zbus_channel_data * data
Mutable channel data struct.
Definition zbus.h:124
size_t message_size
Message size.
Definition zbus.h:110
const char * name
Channel name.
Definition zbus.h:98
void * message
Message reference.
Definition zbus.h:107
Definition zbus.h:149
bool enabled
Enabled flag.
Definition zbus.h:151
Structure used to register runtime observers.
Definition zbus.h:1124
const struct zbus_observer * obs
Definition zbus.h:1126
sys_snode_t node
Definition zbus.h:1125
Type used to represent an observer.
Definition zbus.h:174
enum zbus_observer_type type
Type indication.
Definition zbus.h:180
struct k_fifo * message_fifo
Observer message FIFO.
Definition zbus.h:196
void(* callback)(const struct zbus_channel *chan)
Observer callback function.
Definition zbus.h:190
struct zbus_observer_data * data
Mutable observer data struct.
Definition zbus.h:183
struct k_msgq * queue
Observer message queue.
Definition zbus.h:187
const char * name
Observer name.
Definition zbus.h:177
struct k_work * work
Observer work.
Definition zbus.h:203
Type used to represent a runtime channel.
Definition zbus.h:130
struct zbus_channel channel
Refer to zbus_channel.
Definition zbus.h:132
Iterable sections helpers.