Zephyr Project API  3.4.0
A Scalable Open Source RTOS
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
32#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
34 const char *const name;
35#endif
38
42 void *const user_data;
43
47 void *const message;
48
53 bool (*const validator)(const void *msg, size_t msg_size);
54
58 struct k_mutex *mutex;
59#if (CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE > 0) || defined(__DOXYGEN__)
64#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE */
65
69 const struct zbus_observer *const *observers;
70};
71
88#if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
90 const char *const name;
91#endif
93 bool enabled;
95 struct k_msgq *const queue;
96
98 void (*const callback)(const struct zbus_channel *chan);
99};
100
103#if defined(CONFIG_ZBUS_ASSERT_MOCK)
104#define _ZBUS_ASSERT(_cond, _fmt, ...) \
105 do { \
106 if (!(_cond)) { \
107 printk("ZBUS ASSERT: "); \
108 printk(_fmt, ##__VA_ARGS__); \
109 printk("\n"); \
110 return -EFAULT; \
111 } \
112 } while (0)
113#else
114#define _ZBUS_ASSERT(_cond, _fmt, ...) __ASSERT(_cond, _fmt, ##__VA_ARGS__)
115#endif
116
117#if defined(CONFIG_ZBUS_CHANNEL_NAME)
118#define ZBUS_CHANNEL_NAME_INIT(_name) .name = #_name,
119#else
120#define ZBUS_CHANNEL_NAME_INIT(_name)
121#endif
122
123#if defined(CONFIG_ZBUS_OBSERVER_NAME)
124#define ZBUS_OBSERVER_NAME_INIT(_name) .name = #_name,
125#define _ZBUS_OBS_NAME(_obs) (_obs)->name
126#else
127#define ZBUS_OBSERVER_NAME_INIT(_name)
128#define _ZBUS_OBS_NAME(_obs) ""
129#endif
130
131#if CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE > 0
132#define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name) static sys_slist_t _slist_name
133#define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) .runtime_observers = &_slist_name,
134#else
135#define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name)
136#define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) /* No runtime observers */
137#endif
138
139#if defined(CONFIG_ZBUS_STRUCTS_ITERABLE_ACCESS)
140#define _ZBUS_STRUCT_DECLARE(_type, _name) STRUCT_SECTION_ITERABLE(_type, _name)
141#else
142#define _ZBUS_STRUCT_DECLARE(_type, _name) struct _type _name
143#endif /* CONFIG_ZBUS_STRUCTS_ITERABLE_ACCESS */
144
145#define _ZBUS_OBS_EXTERN(_name) extern struct zbus_observer _name
146
147#define _ZBUS_CHAN_EXTERN(_name) extern const struct zbus_channel _name
148
149#define ZBUS_REF(_value) &(_value)
150
151k_timeout_t _zbus_timeout_remainder(uint64_t end_ticks);
159#define ZBUS_OBS_DECLARE(...) FOR_EACH(_ZBUS_OBS_EXTERN, (;), __VA_ARGS__)
160
166#define ZBUS_CHAN_DECLARE(...) FOR_EACH(_ZBUS_CHAN_EXTERN, (;), __VA_ARGS__)
167
172#define ZBUS_OBSERVERS_EMPTY
173
179#define ZBUS_OBSERVERS(...) __VA_ARGS__
180
196#define ZBUS_CHAN_DEFINE(_name, _type, _validator, _user_data, _observers, _init_val) \
197 static _type _CONCAT(_zbus_message_, _name) = _init_val; \
198 static K_MUTEX_DEFINE(_CONCAT(_zbus_mutex_, _name)); \
199 ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_CONCAT(_runtime_observers_, _name)); \
200 FOR_EACH_NONEMPTY_TERM(_ZBUS_OBS_EXTERN, (;), _observers) \
201 static const struct zbus_observer *const _CONCAT(_zbus_observers_, _name)[] = { \
202 FOR_EACH_NONEMPTY_TERM(ZBUS_REF, (,), _observers) NULL}; \
203 const _ZBUS_STRUCT_DECLARE(zbus_channel, _name) = { \
204 ZBUS_CHANNEL_NAME_INIT(_name) /* Name */ \
205 .message_size = sizeof(_type), /* Message size */ \
206 .user_data = _user_data, /* User data */ \
207 .message = &_CONCAT(_zbus_message_, _name), /* Reference to the message */\
208 .validator = (_validator), /* Validator function */ \
209 .mutex = &_CONCAT(_zbus_mutex_, _name), /* Channel's Mutex */ \
210 ZBUS_RUNTIME_OBSERVERS_LIST_INIT( \
211 _CONCAT(_runtime_observers_, _name)) /* Runtime observer list */ \
212 .observers = _CONCAT(_zbus_observers_, _name)} /* Static observer list */
213
223#define ZBUS_MSG_INIT(_val, ...) \
224 { \
225 _val, ##__VA_ARGS__ \
226 }
227
238#define ZBUS_SUBSCRIBER_DEFINE(_name, _queue_size) \
239 K_MSGQ_DEFINE(_zbus_observer_queue_##_name, sizeof(const struct zbus_channel *), \
240 _queue_size, sizeof(const struct zbus_channel *)); \
241 _ZBUS_STRUCT_DECLARE(zbus_observer, \
242 _name) = {ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
243 .enabled = true, \
244 .queue = &_zbus_observer_queue_##_name, .callback = NULL}
245
256#define ZBUS_LISTENER_DEFINE(_name, _cb) \
257 _ZBUS_STRUCT_DECLARE(zbus_observer, \
258 _name) = {ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */ \
259 .enabled = true, \
260 .queue = NULL, .callback = (_cb)}
261
283int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t timeout);
284
302int zbus_chan_read(const struct zbus_channel *chan, void *msg, k_timeout_t timeout);
303
326
343int zbus_chan_finish(const struct zbus_channel *chan);
344
364
365#if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
366
376static inline const char *zbus_chan_name(const struct zbus_channel *chan)
377{
378 __ASSERT(chan != NULL, "chan is required");
379
380 return chan->name;
381}
382
383#endif
384
397static inline void *zbus_chan_msg(const struct zbus_channel *chan)
398{
399 __ASSERT(chan != NULL, "chan is required");
400
401 return chan->message;
402}
403
418static inline const void *zbus_chan_const_msg(const struct zbus_channel *chan)
419{
420 __ASSERT(chan != NULL, "chan is required");
421
422 return chan->message;
423}
424
434static inline uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
435{
436 __ASSERT(chan != NULL, "chan is required");
437
438 return chan->message_size;
439}
440
450static inline void *zbus_chan_user_data(const struct zbus_channel *chan)
451{
452 __ASSERT(chan != NULL, "chan is required");
453
454 return chan->user_data;
455}
456
457#if (CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE > 0) || defined(__DOXYGEN__)
458
475int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
477
495int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
497
505struct k_mem_slab *zbus_runtime_obs_pool(void);
506
509struct zbus_observer_node {
510 sys_snode_t node;
511 const struct zbus_observer *obs;
512};
513
516#endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS_POOL_SIZE */
517
531static inline int zbus_obs_set_enable(struct zbus_observer *obs, bool enabled)
532{
533 _ZBUS_ASSERT(obs != NULL, "obs is required");
534
535 obs->enabled = enabled;
536
537 return 0;
538}
539
540#if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
541
551static inline const char *zbus_obs_name(const struct zbus_observer *obs)
552{
553 __ASSERT(obs != NULL, "obs is required");
554
555 return obs->name;
556}
557
558#endif
559
578int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan,
580
581#if defined(CONFIG_ZBUS_STRUCTS_ITERABLE_ACCESS) || defined(__DOXYGEN__)
593bool zbus_iterate_over_channels(bool (*iterator_func)(const struct zbus_channel *chan));
594
606bool zbus_iterate_over_observers(bool (*iterator_func)(const struct zbus_observer *obs));
607
608#endif /* CONFIG_ZBUS_STRUCTS_ITERABLE_ACCESS */
613#ifdef __cplusplus
614}
615#endif
616
617#endif /* ZEPHYR_INCLUDE_ZBUS_H_ */
ZTEST_BMEM int timeout
Definition: main.c:31
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:376
struct k_mem_slab * zbus_runtime_obs_pool(void)
Get zbus runtime observers pool.
bool zbus_iterate_over_observers(bool(*iterator_func)(const struct zbus_observer *obs))
Iterate over observers.
static const char * zbus_obs_name(const struct zbus_observer *obs)
Get the observer's name.
Definition: zbus.h:551
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.
static uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
Get the channel's message size.
Definition: zbus.h:434
static void * zbus_chan_msg(const struct zbus_channel *chan)
Get the reference for a channel message directly.
Definition: zbus.h:397
static void * zbus_chan_user_data(const struct zbus_channel *chan)
Get the channel's user data.
Definition: zbus.h:450
static int zbus_obs_set_enable(struct zbus_observer *obs, bool enabled)
Change the observer state.
Definition: zbus.h:531
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 const void * zbus_chan_const_msg(const struct zbus_channel *chan)
Get a constant reference for a channel message directly.
Definition: zbus.h:418
Public kernel APIs.
struct _slist sys_slist_t
Definition: slist.h:40
struct _snode sys_snode_t
Definition: slist.h:33
#define bool
Definition: stdbool.h:13
__UINT64_TYPE__ uint64_t
Definition: stdint.h:91
__UINT16_TYPE__ uint16_t
Definition: stdint.h:89
Message Queue Structure.
Definition: kernel.h:4306
Definition: kernel.h:2822
Kernel timeout type.
Definition: sys_clock.h:65
Type used to represent a channel.
Definition: zbus.h:31
bool(*const validator)(const void *msg, size_t msg_size)
Definition: zbus.h:53
sys_slist_t * runtime_observers
Definition: zbus.h:63
const uint16_t message_size
Definition: zbus.h:37
const struct zbus_observer *const * observers
Definition: zbus.h:69
void *const message
Definition: zbus.h:47
const char *const name
Definition: zbus.h:34
void *const user_data
Definition: zbus.h:42
struct k_mutex * mutex
Definition: zbus.h:58
Type used to represent an observer.
Definition: zbus.h:87
void(*const callback)(const struct zbus_channel *chan)
Definition: zbus.h:98
struct k_msgq *const queue
Definition: zbus.h:95
bool enabled
Definition: zbus.h:93
const char *const name
Definition: zbus.h:90
static void msg(uint64_t c64)
Definition: main.c:17