Zephyr API Documentation  3.5.0
A Scalable Open Source RTOS
3.5.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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_H_
7#define ZEPHYR_INCLUDE_ZBUS_H_
8
9#include <string.h>
10
11#include <zephyr/kernel.h>
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
35
40
44 struct k_mutex mutex;
45
46#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
51#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
52};
53
61#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
63 const char *const name;
64#endif
68 void *const message;
69
71 const size_t message_size;
72
76 void *const user_data;
77
82 bool (*const validator)(const void *msg, size_t msg_size);
83
85 struct zbus_channel_data *const data;
86};
87
93enum __packed zbus_observer_type {
97};
98
115#if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
117 const char *const name;
118#endif
121
124
125 union {
127 struct k_msgq *const queue;
128
130 void (*const callback)(const struct zbus_channel *chan);
131
132#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
136 struct k_fifo *const message_fifo;
137#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
138 };
139};
140
142struct zbus_channel_observation_mask {
143 bool enabled;
144};
145
146struct zbus_channel_observation {
147 const struct zbus_channel *const chan;
148 const struct zbus_observer *const obs;
149};
150
151#if defined(CONFIG_ZBUS_ASSERT_MOCK)
152#define _ZBUS_ASSERT(_cond, _fmt, ...) \
153 do { \
154 if (!(_cond)) { \
155 printk("ZBUS ASSERT: "); \
156 printk(_fmt, ##__VA_ARGS__); \
157 printk("\n"); \
158 return -EFAULT; \
159 } \
160 } while (0)
161#else
162#define _ZBUS_ASSERT(_cond, _fmt, ...) __ASSERT(_cond, _fmt, ##__VA_ARGS__)
163#endif
164
165#if defined(CONFIG_ZBUS_CHANNEL_NAME)
166#define ZBUS_CHANNEL_NAME_INIT(_name) .name = #_name,
167#define _ZBUS_CHAN_NAME(_chan) (_chan)->name
168#else
169#define ZBUS_CHANNEL_NAME_INIT(_name)
170#define _ZBUS_CHAN_NAME(_chan) ""
171#endif
172
173#if defined(CONFIG_ZBUS_OBSERVER_NAME)
174#define ZBUS_OBSERVER_NAME_INIT(_name) .name = #_name,
175#define _ZBUS_OBS_NAME(_obs) (_obs)->name
176#else
177#define ZBUS_OBSERVER_NAME_INIT(_name)
178#define _ZBUS_OBS_NAME(_obs) ""
179#endif
180
181#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS)
182#define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name) static sys_slist_t _slist_name
183#define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) .runtime_observers = &_slist_name,
184#else
185#define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name)
186#define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) /* No runtime observers */
187#endif
188
189#define _ZBUS_OBS_EXTERN(_name) extern struct zbus_observer _name
190
191#define _ZBUS_CHAN_EXTERN(_name) extern const struct zbus_channel _name
192
193#define ZBUS_REF(_value) &(_value)
194
195#define FOR_EACH_FIXED_ARG_NONEMPTY_TERM(F, sep, fixed_arg, ...) \
196 COND_CODE_0(/* are there zero non-empty arguments ? */ \
197 NUM_VA_ARGS_LESS_1( \
198 LIST_DROP_EMPTY(__VA_ARGS__, _)), /* if so, expand to nothing */ \
199 (), /* otherwise, expand to: */ \
200 (FOR_EACH_IDX_FIXED_ARG( \
201 F, sep, fixed_arg, \
202 LIST_DROP_EMPTY(__VA_ARGS__)) /* plus a final terminator */ \
203 __DEBRACKET sep))
204
205#define _ZBUS_OBSERVATION_PREFIX(_idx) \
206 GET_ARG_N(_idx, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, \
207 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, \
208 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, \
209 58, 59, 60, 61, 62, 63)
210
211#define _ZBUS_CHAN_OBSERVATION(_idx, _obs, _chan) \
212 const STRUCT_SECTION_ITERABLE( \
213 zbus_channel_observation, \
214 _CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx)))) = {.chan = &_chan, \
215 .obs = &_obs}; \
216 STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask, \
217 _CONCAT(_CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx))), \
218 _mask)) = {.enabled = false};
219
220#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
221#define _ZBUS_RUNTIME_OBSERVERS(_name) .observers = &(_CONCAT(_observers_, _name)),
222#define _ZBUS_RUNTIME_OBSERVERS_DECL(_name) static sys_slist_t _CONCAT(_observers_, _name);
223#else
224#define _ZBUS_RUNTIME_OBSERVERS(_name)
225#define _ZBUS_RUNTIME_OBSERVERS_DECL(_name)
226#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
227
241#define ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, _masked, _prio) \
242 const STRUCT_SECTION_ITERABLE(zbus_channel_observation, \
243 _CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs))) = { \
244 .chan = &_chan, .obs = &_obs}; \
245 STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask, \
246 _CONCAT(_CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs)), \
247 _mask)) = {.enabled = _masked}
258#define ZBUS_CHAN_ADD_OBS(_chan, _obs, _prio) ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, false, _prio)
259
265#define ZBUS_OBS_DECLARE(...) FOR_EACH_NONEMPTY_TERM(_ZBUS_OBS_EXTERN, (;), __VA_ARGS__)
266
272#define ZBUS_CHAN_DECLARE(...) FOR_EACH(_ZBUS_CHAN_EXTERN, (;), __VA_ARGS__)
273
278#define ZBUS_OBSERVERS_EMPTY
279
285#define ZBUS_OBSERVERS(...) __VA_ARGS__
286
302#define ZBUS_CHAN_DEFINE(_name, _type, _validator, _user_data, _observers, _init_val) \
303 static _type _CONCAT(_zbus_message_, _name) = _init_val; \
304 static struct zbus_channel_data _CONCAT(_zbus_chan_data_, _name) = { \
305 .observers_start_idx = -1, .observers_end_idx = -1}; \
306 static K_MUTEX_DEFINE(_CONCAT(_zbus_mutex_, _name)); \
307 const STRUCT_SECTION_ITERABLE(zbus_channel, _name) = { \
308 ZBUS_CHANNEL_NAME_INIT(_name) /* Maybe removed */ \
309 .message = &_CONCAT(_zbus_message_, _name), \
310 .message_size = sizeof(_type), .user_data = _user_data, .validator = (_validator), \
311 .data = &_CONCAT(_zbus_chan_data_, _name)}; \
312 /* Extern declaration of observers */ \
313 ZBUS_OBS_DECLARE(_observers); \
314 /* Create all channel observations from observers list */ \
315 FOR_EACH_FIXED_ARG_NONEMPTY_TERM(_ZBUS_CHAN_OBSERVATION, (;), _name, _observers)
316
326#define ZBUS_MSG_INIT(_val, ...) \
327 { \
328 _val, ##__VA_ARGS__ \
329 }
330
342#define ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, _enable) \
343 K_MSGQ_DEFINE(_zbus_observer_queue_##_name, sizeof(const struct zbus_channel *), \
344 _queue_size, sizeof(const struct zbus_channel *)); \
345 STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
346 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
347 .type = ZBUS_OBSERVER_SUBSCRIBER_TYPE, \
348 .enabled = _enable, .queue = &_zbus_observer_queue_##_name}
360#define ZBUS_SUBSCRIBER_DEFINE(_name, _queue_size) \
361 ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, true)
362
374#define ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, _enable) \
375 STRUCT_SECTION_ITERABLE(zbus_observer, \
376 _name) = {ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
377 .type = ZBUS_OBSERVER_LISTENER_TYPE, \
378 .enabled = _enable, .callback = (_cb)}
389#define ZBUS_LISTENER_DEFINE(_name, _cb) ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, true)
390
401#define ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _enable) \
402 static K_FIFO_DEFINE(_zbus_observer_fifo_##_name); \
403 STRUCT_SECTION_ITERABLE(zbus_observer, _name) = { \
404 ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
405 .type = ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE, \
406 .enabled = _enable, \
407 .message_fifo = &_zbus_observer_fifo_##_name, \
408 }
409
421#define ZBUS_MSG_SUBSCRIBER_DEFINE(_name) ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, true)
443int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t timeout);
444
462int zbus_chan_read(const struct zbus_channel *chan, void *msg, k_timeout_t timeout);
463
485int zbus_chan_claim(const struct zbus_channel *chan, k_timeout_t timeout);
486
503int zbus_chan_finish(const struct zbus_channel *chan);
504
523int zbus_chan_notify(const struct zbus_channel *chan, k_timeout_t timeout);
524
525#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
526
536static inline const char *zbus_chan_name(const struct zbus_channel *chan)
537{
538 __ASSERT(chan != NULL, "chan is required");
539
540 return chan->name;
541}
542
543#endif
544
557static inline void *zbus_chan_msg(const struct zbus_channel *chan)
558{
559 __ASSERT(chan != NULL, "chan is required");
560
561 return chan->message;
562}
563
578static inline const void *zbus_chan_const_msg(const struct zbus_channel *chan)
579{
580 __ASSERT(chan != NULL, "chan is required");
581
582 return chan->message;
583}
584
594static inline uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
595{
596 __ASSERT(chan != NULL, "chan is required");
597
598 return chan->message_size;
599}
600
610static inline void *zbus_chan_user_data(const struct zbus_channel *chan)
611{
612 __ASSERT(chan != NULL, "chan is required");
613
614 return chan->user_data;
615}
616
617#if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
618
635int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
636 k_timeout_t timeout);
637
655int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
656 k_timeout_t timeout);
657
660struct zbus_observer_node {
661 sys_snode_t node;
662 const struct zbus_observer *obs;
663};
664
667#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
668
682static inline int zbus_obs_set_enable(struct zbus_observer *obs, bool enabled)
683{
684 _ZBUS_ASSERT(obs != NULL, "obs is required");
685
686 obs->enabled = enabled;
687
688 return 0;
689}
690
701static inline int zbus_obs_is_enabled(struct zbus_observer *obs, bool *enable)
702{
703 _ZBUS_ASSERT(obs != NULL, "obs is required");
704 _ZBUS_ASSERT(enable != NULL, "enable is required");
705
706 *enable = obs->enabled;
707
708 return 0;
709}
710
726 const struct zbus_channel *chan, bool masked);
727
741 const struct zbus_channel *chan, bool *masked);
742
743#if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
744
754static inline const char *zbus_obs_name(const struct zbus_observer *obs)
755{
756 __ASSERT(obs != NULL, "obs is required");
757
758 return obs->name;
759}
760
761#endif
762
781int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan,
782 k_timeout_t timeout);
783
784#if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
785
804int zbus_sub_wait_msg(const struct zbus_observer *sub, const struct zbus_channel **chan, void *msg,
805 k_timeout_t timeout);
806
807#endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
808
822bool zbus_iterate_over_channels(bool (*iterator_func)(const struct zbus_channel *chan));
838 bool (*iterator_func)(const struct zbus_channel *chan, void *user_data), void *user_data);
839
853bool zbus_iterate_over_observers(bool (*iterator_func)(const struct zbus_observer *obs));
869 bool (*iterator_func)(const struct zbus_observer *obs, void *user_data), void *user_data);
870
875#ifdef __cplusplus
876}
877#endif
878
879#endif /* ZEPHYR_INCLUDE_ZBUS_H_ */
struct _slist sys_slist_t
Single-linked list structure.
Definition: slist.h:49
struct _snode sys_snode_t
Single-linked list node structure.
Definition: slist.h:39
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:536
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.
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.
static const char * zbus_obs_name(const struct zbus_observer *obs)
Get the observer's name.
Definition: zbus.h:754
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_finish(const struct zbus_channel *chan)
Finish a channel claim.
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:93
static uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
Get the channel's message size.
Definition: zbus.h:594
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.
static int zbus_obs_is_enabled(struct zbus_observer *obs, bool *enable)
Get the observer state.
Definition: zbus.h:701
static void * zbus_chan_msg(const struct zbus_channel *chan)
Get the reference for a channel message directly.
Definition: zbus.h:557
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.
static void * zbus_chan_user_data(const struct zbus_channel *chan)
Get the channel's user data.
Definition: zbus.h:610
static int zbus_obs_set_enable(struct zbus_observer *obs, bool enabled)
Change the observer state.
Definition: zbus.h:682
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.
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 const void * zbus_chan_const_msg(const struct zbus_channel *chan)
Get a constant reference for a channel message directly.
Definition: zbus.h:578
@ ZBUS_OBSERVER_LISTENER_TYPE
Definition: zbus.h:94
@ ZBUS_OBSERVER_SUBSCRIBER_TYPE
Definition: zbus.h:95
@ ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE
Definition: zbus.h:96
Public kernel APIs.
#define bool
Definition: stdbool.h:13
__UINT16_TYPE__ uint16_t
Definition: stdint.h:89
__INT16_TYPE__ int16_t
Definition: stdint.h:73
Definition: kernel.h:2385
Message Queue Structure.
Definition: kernel.h:4406
Mutex Structure.
Definition: kernel.h:2911
Kernel timeout type.
Definition: sys_clock.h:65
Type used to represent a channel mutable data.
Definition: zbus.h:30
struct k_mutex mutex
Access control mutex.
Definition: zbus.h:44
int16_t observers_end_idx
Static channel observer list end index.
Definition: zbus.h:39
int16_t observers_start_idx
Static channel observer list start index.
Definition: zbus.h:34
sys_slist_t observers
Channel observer list.
Definition: zbus.h:50
Type used to represent a channel.
Definition: zbus.h:60
bool(*const validator)(const void *msg, size_t msg_size)
Message validator.
Definition: zbus.h:82
struct zbus_channel_data *const data
Mutable channel data struct.
Definition: zbus.h:85
const size_t message_size
Message size.
Definition: zbus.h:71
void *const message
Message reference.
Definition: zbus.h:68
const char *const name
Channel name.
Definition: zbus.h:63
void *const user_data
User data available to extend zbus features.
Definition: zbus.h:76
Type used to represent an observer.
Definition: zbus.h:114
enum zbus_observer_type type
Type indication.
Definition: zbus.h:120
void(*const callback)(const struct zbus_channel *chan)
Observer callback function.
Definition: zbus.h:130
struct k_msgq *const queue
Observer message queue.
Definition: zbus.h:127
bool enabled
Enabled flag.
Definition: zbus.h:123
struct k_fifo *const message_fifo
Observer message FIFO.
Definition: zbus.h:136
const char *const name
Observer name.
Definition: zbus.h:117