Skip to content

Commit f3e3f87

Browse files
zbus: add multidomain types and proxy agent framework
Add the type definitions and API framework for ZBus multidomain proxy agents. This provides the foundation for backend-agnostic communication between domains. - Define zbus_multidomain_type enum for different backends - Add zbus_proxy_agent_msg structure for inter-domain messages - Create zbus_proxy_agent_api for backend abstraction - Add zbus_proxy_agent_config for agent configuration - Implement core proxy agent functions (init, send, thread) - Add retransmission logic - Add macro system for backend-specific configuration generation The proxy agent framework allows different communication backends (UART, IPC, etc.) to be plugged in using a common API interface. Signed-off-by: Trond F. Christiansen <[email protected]>
1 parent 5610a02 commit f3e3f87

File tree

6 files changed

+845
-0
lines changed

6 files changed

+845
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#ifndef ZEPHYR_INCLUDE_ZBUS_MULTIDOMAIN_H_
8+
#define ZEPHYR_INCLUDE_ZBUS_MULTIDOMAIN_H_
9+
10+
#include <zephyr/kernel.h>
11+
#include <string.h>
12+
#include <zephyr/net_buf.h>
13+
#include <zephyr/sys/slist.h>
14+
#include <zephyr/zbus/zbus.h>
15+
#include <zephyr/zbus/multidomain/zbus_multidomain_types.h>
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
/**
22+
* @brief Zbus Multi-domain API
23+
* @defgroup zbus_multidomain_apis Zbus Multi-domain APIs
24+
* @ingroup zbus_apis
25+
* @since 3.3.0
26+
* @version 1.0.0
27+
* @ingroup os_services
28+
* @{
29+
*/
30+
31+
/**
32+
* @brief Structure for tracking sent messages awaiting acknowledgment.
33+
*
34+
* This structure is used internally by the proxy agent to keep track of messages
35+
* that have been sent but not yet acknowledged. It contains a copy of the message,
36+
* the number of transmit attempts, and a delayed work item for timeout handling.
37+
*/
38+
struct zbus_proxy_agent_tracked_msg {
39+
/** Copy of the sent message */
40+
struct zbus_proxy_agent_msg msg;
41+
42+
/** Pointer to the proxy agent configuration */
43+
struct zbus_proxy_agent_config *config;
44+
45+
/** Number of transmit attempts made for this message */
46+
uint8_t transmit_attempts;
47+
48+
/** Work item for handling acknowledgment timeout */
49+
struct k_work_delayable work;
50+
};
51+
52+
/**
53+
* @brief Configuration structure for the proxy agent.
54+
*
55+
* This structure holds the configuration for a proxy agent, including its name,
56+
* type, backend specific API, and backend specific configuration.
57+
*/
58+
struct zbus_proxy_agent_config {
59+
/* The name of the proxy agent */
60+
const char *name;
61+
62+
/* The type of the proxy agent */
63+
enum zbus_multidomain_type type;
64+
65+
/* Pointer to the backend specific API */
66+
const struct zbus_proxy_agent_api *api;
67+
68+
/* Pointer to the backend specific configuration */
69+
void *backend_config;
70+
71+
/* Pool for tracking sent messages awaiting acknowledgment */
72+
struct net_buf_pool *sent_msg_pool;
73+
74+
/* List of sent messages awaiting acknowledgment */
75+
sys_slist_t sent_msg_list;
76+
};
77+
78+
/**
79+
* @brief Set up a proxy agent using the provided configuration.
80+
*
81+
* Starts the proxy agent thread and initializes the necessary resources.
82+
*
83+
* @note This macro sets up net_buf_pool for tracking sent messages, defines
84+
* a zbus subscriber, and creates a thread for the proxy agent.
85+
*
86+
* @note the ZBUS_MULTIDOMAIN_SENT_MSG_POOL_SIZE configuration option
87+
* must be set to a value greater than or equal to the maximum number of
88+
* unacknowledged messages that can be in flight at any given time.
89+
*
90+
* @note The configuration options ZBUS_MULTIDOMAIN_PROXY_STACK_SIZE and
91+
* ZBUS_MULTIDOMAIN_PROXY_PRIORITY define the stack size and priority of the
92+
* proxy agent thread, respectively.
93+
*
94+
* @param _name The name of the proxy agent.
95+
* @param _type The type of the proxy agent (enum zbus_multidomain_type)
96+
* @param _nodelabel The device node label for the proxy agent.
97+
*/
98+
#define ZBUS_PROXY_AGENT_DEFINE(_name, _type, _nodelabel) \
99+
NET_BUF_POOL_DEFINE(_name##_sent_msg_pool, CONFIG_ZBUS_MULTIDOMAIN_SENT_MSG_POOL_SIZE, \
100+
sizeof(struct zbus_proxy_agent_tracked_msg), sizeof(uint32_t), NULL); \
101+
_ZBUS_GENERATE_BACKEND_CONFIG(_name, _type, _nodelabel); \
102+
struct zbus_proxy_agent_config _name##_config = { \
103+
.name = #_name, \
104+
.type = _type, \
105+
.api = _ZBUS_GET_API(_type), \
106+
.backend_config = _ZBUS_GET_CONFIG(_name, _type), \
107+
.sent_msg_pool = &_name##_sent_msg_pool, \
108+
}; \
109+
ZBUS_MSG_SUBSCRIBER_DEFINE(_name##_subscriber); \
110+
K_THREAD_DEFINE(_name##_thread_id, CONFIG_ZBUS_MULTIDOMAIN_PROXY_STACK_SIZE, \
111+
zbus_proxy_agent_thread, &_name##_config, &_name##_subscriber, NULL, \
112+
CONFIG_ZBUS_MULTIDOMAIN_PROXY_PRIORITY, 0, 0);
113+
114+
/**
115+
* @brief Add a channel to the proxy agent.
116+
*
117+
* @param _name The name of the proxy agent.
118+
* @param _chan The channel to be added.
119+
*/
120+
#define ZBUS_PROXY_ADD_CHANNEL(_name, _chan) ZBUS_CHAN_ADD_OBS(_chan, _name##_subscriber, 0);
121+
122+
/**
123+
* @brief Thread function for the proxy agent.
124+
*
125+
* This function runs in a separate thread and continuously listens for messages
126+
* on the zbus observer. It processes incoming messages and forwards them
127+
* to the appropriate backend for sending.
128+
*
129+
* @param config Pointer to the configuration structure for the proxy agent.
130+
* @param subscriber Pointer to the zbus observer that the proxy agent listens to.
131+
* @return negative error code on failure.
132+
*/
133+
int zbus_proxy_agent_thread(struct zbus_proxy_agent_config *config,
134+
const struct zbus_observer *subscriber);
135+
136+
/** @cond INTERNAL_HIDDEN */
137+
138+
/**
139+
* @brief Macros to generate backend specific configurations for the proxy agent.
140+
*
141+
* This macro generates the backend specific configurations based on the type of
142+
* the proxy agent.
143+
*
144+
* @param _name The name of the proxy agent.
145+
* @param _type The type of the proxy agent (enum zbus_multidomain_type).
146+
* @param _nodelabel The device node label for the proxy agent.
147+
*
148+
* @note This macro finds the matching backend configuration macro from the
149+
* backend specific header files. Requires the backend specific header files to
150+
* define the macros in the format `_ZBUS_GENERATE_BACKEND_CONFIG_<type>(_name, _nodelabel)`.
151+
*/
152+
#define _ZBUS_GENERATE_BACKEND_CONFIG(_name, _type, _nodelabel) \
153+
_ZBUS_GENERATE_BACKEND_CONFIG_##_type(_name, _nodelabel)
154+
155+
/**
156+
* @brief Generic macros to get the API and configuration for the specified type of proxy agent.
157+
*
158+
* These macros are used to retrieve the API and configuration for the specified type of
159+
* proxy agent. The type is specified as an argument to the macro.
160+
*
161+
* @param _type The type of the proxy agent (enum zbus_multidomain_type).
162+
* @param _name The name of the proxy agent.
163+
*
164+
* @note These macros are used to retrieve the API and configuration for the specified type of
165+
* proxy agent. Requires the backend specific header files to define the macros in the format
166+
* `_ZBUS_GET_API_<type>()` and `_ZBUS_GET_CONFIG_<name, type>()`.
167+
*/
168+
#define _ZBUS_GET_API(_type) _ZBUS_GET_API_##_type()
169+
#define _ZBUS_GET_CONFIG(_name, _type) _ZBUS_GET_CONFIG_##_type(_name)
170+
171+
/** @endcond */
172+
173+
/**
174+
* @}
175+
*/
176+
177+
#ifdef __cplusplus
178+
}
179+
#endif
180+
181+
#endif /* ZEPHYR_INCLUDE_ZBUS_MULTIDOMAIN_H_ */
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#ifndef ZEPHYR_INCLUDE_ZBUS_MULTIDOMAIN_TYPES_H_
8+
#define ZEPHYR_INCLUDE_ZBUS_MULTIDOMAIN_TYPES_H_
9+
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/zbus/zbus.h>
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
/**
18+
* @brief Zbus Multi-domain API
19+
* @defgroup zbus_multidomain_apis Zbus Multi-domain APIs
20+
* @ingroup zbus_apis
21+
* @since 3.3.0
22+
* @version 1.0.0
23+
* @ingroup os_services
24+
* @{
25+
*/
26+
27+
/**
28+
* @brief Type of the proxy agent.
29+
*
30+
* This enum defines the types of proxy agents that can be used in a multi-domain
31+
* Zbus setup. Each type corresponds to a different communication backend.
32+
*/
33+
enum zbus_multidomain_type {
34+
};
35+
36+
/**
37+
* @brief Type of the proxy agent message.
38+
*
39+
* This enum defines the types of messages that can be sent or received by the proxy agent.
40+
* A message can either be a data message or an acknowledgment (ACK) message.
41+
*/
42+
enum zbus_proxy_agent_msg_type {
43+
ZBUS_PROXY_AGENT_MSG_TYPE_MSG = 0,
44+
ZBUS_PROXY_AGENT_MSG_TYPE_ACK = 1,
45+
};
46+
47+
/**
48+
* @brief Message structure for the proxy agent.
49+
*
50+
* This structure represents a message that is sent or received by the proxy agent.
51+
* It contains the size of the message, the actual message data, and the channel name
52+
* associated with the message.
53+
*/
54+
struct zbus_proxy_agent_msg {
55+
/* Type of the message: data or acknowledgment */
56+
uint8_t type;
57+
58+
/* Message id. sys_clock_cycle when sent */
59+
uint32_t id;
60+
61+
/* The size of the message */
62+
size_t message_size;
63+
64+
/* The channel associated with the message */
65+
uint8_t message_data[CONFIG_ZBUS_MULTIDOMAIN_MESSAGE_SIZE];
66+
67+
/* The length of the channel name */
68+
size_t channel_name_len;
69+
70+
/* The name of the channel */
71+
char channel_name[CONFIG_ZBUS_MULTIDOMAIN_CHANNEL_NAME_SIZE];
72+
} __packed;
73+
74+
/**
75+
* @brief Proxy agent API structure.
76+
*/
77+
struct zbus_proxy_agent_api {
78+
/**
79+
* @brief Initialize the backend for the proxy agent.
80+
*
81+
* This function is called to initialize the backend specific to the proxy agent.
82+
*
83+
* @param config Pointer to the backend specific configuration.
84+
* @return int 0 on success, negative error code on failure.
85+
*/
86+
int (*backend_init)(void *config);
87+
88+
/**
89+
* @brief Send a message through the proxy agent.
90+
*
91+
* This function is called to send a message through the proxy agent.
92+
*
93+
* @param config Pointer to the backend specific configuration.
94+
* @param msg Pointer to the message to be sent.
95+
* @return int 0 on success, negative error code on failure.
96+
*/
97+
int (*backend_send)(void *config, struct zbus_proxy_agent_msg *msg);
98+
99+
/**
100+
* @brief Set the receive callback for the proxy agent.
101+
*
102+
* This function is called to set the callback function that will be invoked
103+
* when a message is received by the backend.
104+
*
105+
* @param config Pointer to the backend specific configuration.
106+
* @param recv_cb Pointer to the callback function to be set.
107+
* @return int 0 on success, negative error code on failure.
108+
*/
109+
int (*backend_set_recv_cb)(void *config,
110+
int (*recv_cb)(const struct zbus_proxy_agent_msg *msg));
111+
112+
/**
113+
* @brief Set the acknowledgment callback for the proxy agent.
114+
*
115+
* This function is called to set the callback function that will be invoked
116+
* when an acknowledgment is received for a sent message.
117+
*
118+
* @param config Pointer to the backend specific configuration.
119+
* @param ack_cb Pointer to the acknowledgment callback function to be set.
120+
* @param user_data Pointer to user data that will be passed to the acknowledgment callback.
121+
* @return int 0 on success, negative error code on failure.
122+
*/
123+
int (*backend_set_ack_cb)(void *config, int (*ack_cb)(uint32_t msg_id, void *user_data),
124+
void *user_data);
125+
};
126+
127+
/**
128+
* @}
129+
*/
130+
131+
#ifdef __cplusplus
132+
}
133+
#endif
134+
135+
#endif /* ZEPHYR_INCLUDE_ZBUS_MULTIDOMAIN_TYPES_H_ */

subsys/zbus/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ if(CONFIG_ZBUS_RUNTIME_OBSERVERS)
88
zephyr_library_sources(zbus_runtime_observers.c)
99
endif()
1010

11+
if(CONFIG_ZBUS_MULTIDOMAIN)
12+
zephyr_library_sources(multidomain/zbus_multidomain.c)
13+
endif()
14+
1115
zephyr_library_sources(zbus_iterable_sections.c)

subsys/zbus/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ config ZBUS_MULTIDOMAIN
115115
Enables support for ZBus multidomain. This feature allows the ZBus to work with multiple domains,
116116
enabling communication between them.
117117

118+
if ZBUS_MULTIDOMAIN
119+
120+
rsource "multidomain/Kconfig"
121+
122+
endif # ZBUS_MULTIDOMAIN
123+
118124
config HEAP_MEM_POOL_ADD_SIZE_ZBUS
119125
int "ZBus requested heap pool size."
120126
default 2048 if ZBUS_MSG_SUBSCRIBER_BUF_ALLOC_DYNAMIC && !ZBUS_RUNTIME_OBSERVERS_NODE_ALLOC_DYNAMIC

0 commit comments

Comments
 (0)