Line data Source code
1 0 : /*
2 : * Copyright (c) 2022 Nordic Semiconductor ASA
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 : #ifndef ZEPHYR_INCLUDE_LOGGING_LOG_LINK_H_
7 : #define ZEPHYR_INCLUDE_LOGGING_LOG_LINK_H_
8 :
9 : #include <zephyr/types.h>
10 : #include <zephyr/sys/__assert.h>
11 : #include <zephyr/logging/log_msg.h>
12 : #include <zephyr/logging/log_internal.h>
13 : #include <zephyr/sys/iterable_sections.h>
14 :
15 : #ifdef __cplusplus
16 : extern "C" {
17 : #endif
18 :
19 : /**
20 : * @brief Log link API
21 : * @defgroup log_link Log link API
22 : * @ingroup logger
23 : * @{
24 : */
25 :
26 : struct log_link;
27 :
28 0 : typedef void (*log_link_callback_t)(const struct log_link *link,
29 : union log_msg_generic *msg);
30 :
31 0 : typedef void (*log_link_dropped_cb_t)(const struct log_link *link,
32 : uint32_t dropped);
33 :
34 0 : struct log_link_config {
35 0 : log_link_callback_t msg_cb;
36 0 : log_link_dropped_cb_t dropped_cb;
37 : };
38 :
39 0 : struct log_link_api {
40 0 : int (*initiate)(const struct log_link *link, struct log_link_config *config);
41 0 : int (*activate)(const struct log_link *link);
42 0 : int (*get_domain_name)(const struct log_link *link, uint32_t domain_id,
43 : char *buf, size_t *length);
44 0 : int (*get_source_name)(const struct log_link *link, uint32_t domain_id,
45 : uint16_t source_id, char *buf, size_t *length);
46 0 : int (*get_levels)(const struct log_link *link, uint32_t domain_id,
47 : uint16_t source_id, uint8_t *level,
48 : uint8_t *runtime_level);
49 0 : int (*set_runtime_level)(const struct log_link *link, uint32_t domain_id,
50 : uint16_t source_id, uint8_t level);
51 : };
52 :
53 0 : struct log_link_ctrl_blk {
54 0 : uint32_t domain_cnt;
55 0 : uint16_t source_cnt[1 + COND_CODE_1(CONFIG_LOG_MULTIDOMAIN,
56 : (CONFIG_LOG_REMOTE_DOMAIN_MAX_COUNT),
57 : (0))];
58 0 : uint32_t domain_offset;
59 0 : uint32_t *filters;
60 : };
61 :
62 0 : struct log_link {
63 0 : const struct log_link_api *api;
64 0 : const char *name;
65 0 : struct log_link_ctrl_blk *ctrl_blk;
66 0 : void *ctx;
67 0 : struct mpsc_pbuf_buffer *mpsc_pbuf;
68 0 : const struct mpsc_pbuf_buffer_config *mpsc_pbuf_config;
69 : };
70 :
71 : /** @brief Create instance of a log link.
72 : *
73 : * Link can have dedicated buffer for messages if @p _buf_len is positive. In
74 : * that case messages will be processed in an order since logging core will
75 : * attempt to fetch message from all available buffers (default and links) and
76 : * process the one with the earliest timestamp. If strict ordering is not needed
77 : * then dedicated buffer may be omitted (@p _buf_len set to 0). That results in
78 : * better memory utilization but unordered messages passed to backends.
79 : *
80 : * @param _name Instance name.
81 : * @param _api API list. See @ref log_link_api.
82 : * @param _buf_wlen Size (in words) of dedicated buffer for messages from this buffer.
83 : * If 0 default buffer is used.
84 : * @param _ctx Context (void *) associated with the link.
85 : */
86 1 : #define LOG_LINK_DEF(_name, _api, _buf_wlen, _ctx) \
87 : static uint32_t __aligned(Z_LOG_MSG_ALIGNMENT) _name##_buf32[_buf_wlen]; \
88 : static const struct mpsc_pbuf_buffer_config _name##_mpsc_pbuf_config = { \
89 : .buf = (uint32_t *)_name##_buf32, \
90 : .size = _buf_wlen, \
91 : .notify_drop = z_log_notify_drop, \
92 : .get_wlen = log_msg_generic_get_wlen, \
93 : .flags = IS_ENABLED(CONFIG_LOG_MODE_OVERFLOW) ? \
94 : MPSC_PBUF_MODE_OVERWRITE : 0 \
95 : }; \
96 : COND_CODE_0(_buf_wlen, (), (static STRUCT_SECTION_ITERABLE(log_msg_ptr, \
97 : _name##_log_msg_ptr);)) \
98 : static STRUCT_SECTION_ITERABLE_ALTERNATE(log_mpsc_pbuf, \
99 : mpsc_pbuf_buffer, \
100 : _name##_log_mpsc_pbuf); \
101 : static struct log_link_ctrl_blk _name##_ctrl_blk; \
102 : static const STRUCT_SECTION_ITERABLE(log_link, _name) = \
103 : { \
104 : .api = &_api, \
105 : .name = STRINGIFY(_name), \
106 : .ctrl_blk = &_name##_ctrl_blk, \
107 : .ctx = _ctx, \
108 : .mpsc_pbuf = _buf_wlen ? &_name##_log_mpsc_pbuf : NULL, \
109 : .mpsc_pbuf_config = _buf_wlen ? &_name##_mpsc_pbuf_config : NULL \
110 : }
111 :
112 : /** @brief Initiate log link.
113 : *
114 : * Function initiates the link. Since initialization procedure may be time
115 : * consuming, function returns before link is ready to not block logging
116 : * initialization. @ref log_link_activate is called to complete link initialization.
117 : *
118 : * @param link Log link instance.
119 : * @param config Configuration.
120 : *
121 : * @return 0 on success or error code.
122 : */
123 1 : static inline int log_link_initiate(const struct log_link *link,
124 : struct log_link_config *config)
125 : {
126 : __ASSERT_NO_MSG(link);
127 :
128 : return link->api->initiate(link, config);
129 : }
130 :
131 : /** @brief Activate log link.
132 : *
133 : * Function checks if link is initialized and completes initialization process.
134 : * When successfully returns, link is ready with domain and sources count fetched
135 : * and timestamp details updated.
136 : *
137 : * @param link Log link instance.
138 : *
139 : * @retval 0 When successfully activated.
140 : * @retval -EINPROGRESS Activation in progress.
141 : */
142 1 : static inline int log_link_activate(const struct log_link *link)
143 : {
144 : __ASSERT_NO_MSG(link);
145 :
146 : return link->api->activate(link);
147 : }
148 :
149 : /** @brief Check if link is activated.
150 : *
151 : * @param link Log link instance.
152 : *
153 : * @retval 0 When successfully activated.
154 : * @retval -EINPROGRESS Activation in progress.
155 : */
156 1 : static inline int log_link_is_active(const struct log_link *link)
157 : {
158 : return link->ctrl_blk->domain_offset > 0 ? 0 : -EINPROGRESS;
159 : }
160 :
161 : /** @brief Get number of domains in the link.
162 : *
163 : * @param[in] link Log link instance.
164 : *
165 : * @return Number of domains.
166 : */
167 1 : static inline uint8_t log_link_domains_count(const struct log_link *link)
168 : {
169 : __ASSERT_NO_MSG(link);
170 :
171 : return link->ctrl_blk->domain_cnt;
172 : }
173 :
174 : /** @brief Get number of sources in the domain.
175 : *
176 : * @param[in] link Log link instance.
177 : * @param[in] domain_id Relative domain ID.
178 : *
179 : * @return Source count.
180 : */
181 1 : static inline uint16_t log_link_sources_count(const struct log_link *link,
182 : uint32_t domain_id)
183 : {
184 : __ASSERT_NO_MSG(link);
185 :
186 : return link->ctrl_blk->source_cnt[domain_id];
187 : }
188 :
189 : /** @brief Get domain name.
190 : *
191 : * @param[in] link Log link instance.
192 : * @param[in] domain_id Relative domain ID.
193 : * @param[out] buf Output buffer filled with domain name. If NULL
194 : * then name length is returned.
195 : * @param[in,out] length Buffer size. Name is trimmed if it does not fit
196 : * in the buffer and field is set to actual name
197 : * length.
198 : *
199 : * @return 0 on success or error code.
200 : */
201 1 : static inline int log_link_get_domain_name(const struct log_link *link,
202 : uint32_t domain_id, char *buf,
203 : size_t *length)
204 : {
205 : __ASSERT_NO_MSG(link);
206 :
207 : return link->api->get_domain_name(link, domain_id, buf, length);
208 : }
209 :
210 : /** @brief Get source name.
211 : *
212 : * @param[in] link Log link instance.
213 : * @param[in] domain_id Relative domain ID.
214 : * @param[in] source_id Source ID.
215 : * @param[out] buf Output buffer filled with source name.
216 : * @param[in,out] length Buffer size. Name is trimmed if it does not fit
217 : * in the buffer and field is set to actual name
218 : * length.
219 : *
220 : * @return 0 on success or error code.
221 : */
222 1 : static inline int log_link_get_source_name(const struct log_link *link,
223 : uint32_t domain_id, uint16_t source_id,
224 : char *buf, size_t *length)
225 : {
226 : __ASSERT_NO_MSG(link);
227 : __ASSERT_NO_MSG(buf);
228 :
229 : return link->api->get_source_name(link, domain_id, source_id,
230 : buf, length);
231 : }
232 :
233 : /** @brief Get level settings of the given source.
234 : *
235 : * @param[in] link Log link instance.
236 : * @param[in] domain_id Relative domain ID.
237 : * @param[in] source_id Source ID.
238 : * @param[out] level Location to store requested compile time level.
239 : * @param[out] runtime_level Location to store requested runtime time level.
240 : *
241 : * @return 0 on success or error code.
242 : */
243 1 : static inline int log_link_get_levels(const struct log_link *link,
244 : uint32_t domain_id, uint16_t source_id,
245 : uint8_t *level, uint8_t *runtime_level)
246 : {
247 : __ASSERT_NO_MSG(link);
248 :
249 : return link->api->get_levels(link, domain_id, source_id,
250 : level, runtime_level);
251 : }
252 :
253 : /** @brief Set runtime level of the given source.
254 : *
255 : * @param[in] link Log link instance.
256 : * @param[in] domain_id Relative domain ID.
257 : * @param[in] source_id Source ID.
258 : * @param[out] level Requested level.
259 : *
260 : * @return 0 on success or error code.
261 : */
262 1 : static inline int log_link_set_runtime_level(const struct log_link *link,
263 : uint32_t domain_id, uint16_t source_id,
264 : uint8_t level)
265 : {
266 : __ASSERT_NO_MSG(link);
267 : __ASSERT_NO_MSG(level);
268 :
269 : return link->api->set_runtime_level(link, domain_id, source_id, level);
270 : }
271 :
272 : /**
273 : * @brief Enqueue external log message.
274 : *
275 : * Add log message to processing queue. Log message is created outside local
276 : * core. For example it maybe coming from external domain.
277 : *
278 : * @param link Log link instance.
279 : * @param data Message from remote domain.
280 : * @param len Length in bytes.
281 : */
282 : void z_log_msg_enqueue(const struct log_link *link, const void *data, size_t len);
283 :
284 : /**
285 : * @}
286 : */
287 :
288 : #ifdef __cplusplus
289 : }
290 : #endif
291 :
292 : #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_LINK_H_ */
|