Added support for conversion from a standard package which contains pointers to read only strings to fully self-contained (fsc) package. Fsc package contains all strings associated with the package thus access to read only strings is not needed to format a string. In order to allow conversion to fsc package, standard package must contain locations of all string pointers within the package. Appending that information is optional and is controlled by flags parameter which was added to packaging API. If option flag is set then package contains header, arguments, locations of read only strings and transient strings (each prefixed with string argument location). Package header has been extended with field which contains number of read only string locations. A function for conversion to fsc package has been added (cbprintf_fsc_package()). Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
644 lines
18 KiB
C
644 lines
18 KiB
C
/*
|
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_
|
|
#define ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_
|
|
|
|
#include <logging/log_instance.h>
|
|
#include <sys/mpsc_packet.h>
|
|
#include <sys/cbprintf.h>
|
|
#include <sys/atomic.h>
|
|
#include <sys/util.h>
|
|
#include <string.h>
|
|
|
|
#ifdef __GNUC__
|
|
#ifndef alloca
|
|
#define alloca __builtin_alloca
|
|
#endif
|
|
#else
|
|
#include <alloca.h>
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define LOG_MSG2_DEBUG 0
|
|
#define LOG_MSG2_DBG(...) IF_ENABLED(LOG_MSG2_DEBUG, (printk(__VA_ARGS__)))
|
|
|
|
#if CONFIG_LOG_TIMESTAMP_64BIT
|
|
typedef uint64_t log_timestamp_t;
|
|
#else
|
|
typedef uint32_t log_timestamp_t;
|
|
#endif
|
|
|
|
/**
|
|
* @brief Log message API
|
|
* @defgroup log_msg2 Log message v2 API
|
|
* @ingroup logger
|
|
* @{
|
|
*/
|
|
|
|
#define Z_LOG_MSG2_LOG 0
|
|
#define Z_LOG_MSG2_TRACE 1
|
|
|
|
#define LOG_MSG2_GENERIC_HDR \
|
|
MPSC_PBUF_HDR;\
|
|
uint32_t type:1
|
|
|
|
struct log_msg2_desc {
|
|
LOG_MSG2_GENERIC_HDR;
|
|
uint32_t domain:3;
|
|
uint32_t level:3;
|
|
uint32_t package_len:10;
|
|
uint32_t data_len:12;
|
|
uint32_t reserved:1;
|
|
};
|
|
|
|
struct log_msg2_trace_hdr {
|
|
LOG_MSG2_GENERIC_HDR;
|
|
uint32_t evt_id:5;
|
|
#if CONFIG_LOG_TRACE_SHORT_TIMESTAMP
|
|
uint32_t timestamp:24;
|
|
#else
|
|
log_timestamp_t timestamp;
|
|
#endif
|
|
};
|
|
|
|
union log_msg2_source {
|
|
const struct log_source_const_data *fixed;
|
|
struct log_source_dynamic_data *dynamic;
|
|
void *raw;
|
|
};
|
|
|
|
struct log_msg2_hdr {
|
|
struct log_msg2_desc desc;
|
|
/* Attempting to keep best alignment. When address is 64 bit and timestamp 32
|
|
* swap the order to have 16 byte header instead of 24 byte.
|
|
*/
|
|
#if (INTPTR_MAX > INT32_MAX) && !CONFIG_LOG_TIMESTAMP_64BIT
|
|
log_timestamp_t timestamp;
|
|
const void *source;
|
|
#else
|
|
const void *source;
|
|
log_timestamp_t timestamp;
|
|
#endif
|
|
#if defined(__xtensa__) && !defined(CONFIG_LOG_TIMESTAMP_64BIT)
|
|
/* xtensa requires that cbprintf package that follows the header is
|
|
* aligned to 16 bytes. Adding padding when necessary.
|
|
*/
|
|
uint32_t padding;
|
|
#endif
|
|
};
|
|
|
|
struct log_msg2_trace {
|
|
struct log_msg2_trace_hdr hdr;
|
|
};
|
|
|
|
struct log_msg2_trace_ptr {
|
|
struct log_msg2_trace_hdr hdr;
|
|
void *ptr;
|
|
};
|
|
|
|
struct log_msg2 {
|
|
struct log_msg2_hdr hdr;
|
|
uint8_t data[];
|
|
};
|
|
|
|
struct log_msg2_generic_hdr {
|
|
LOG_MSG2_GENERIC_HDR;
|
|
};
|
|
|
|
union log_msg2_generic {
|
|
union mpsc_pbuf_generic buf;
|
|
struct log_msg2_generic_hdr generic;
|
|
struct log_msg2_trace trace;
|
|
struct log_msg2_trace_ptr trace_ptr;
|
|
struct log_msg2 log;
|
|
};
|
|
|
|
/** @brief Method used for creating a log message.
|
|
*
|
|
* It is used for testing purposes to validate that expected mode was used.
|
|
*/
|
|
enum z_log_msg2_mode {
|
|
/* Runtime mode is least efficient but supports all cases thus it is
|
|
* threated as a fallback method when others cannot be used.
|
|
*/
|
|
Z_LOG_MSG2_MODE_RUNTIME,
|
|
/* Mode creates statically a string package on stack and calls a
|
|
* function for creating a message. It takes code size than
|
|
* Z_LOG_MSG2_MODE_ZERO_COPY but is a bit slower.
|
|
*/
|
|
Z_LOG_MSG2_MODE_FROM_STACK,
|
|
|
|
/* Mode calculates size of the message and allocates it and writes
|
|
* directly to the message space. It is the fastest method but requires
|
|
* more code size.
|
|
*/
|
|
Z_LOG_MSG2_MODE_ZERO_COPY,
|
|
|
|
/* Mode used when synchronous logging is enabled. */
|
|
Z_LOG_MSG2_MODE_SYNC
|
|
};
|
|
|
|
#define Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, _plen, _dlen) \
|
|
{ \
|
|
.valid = 0, \
|
|
.busy = 0, \
|
|
.type = Z_LOG_MSG2_LOG, \
|
|
.domain = _domain_id, \
|
|
.level = _level, \
|
|
.package_len = _plen, \
|
|
.data_len = _dlen, \
|
|
.reserved = 0, \
|
|
}
|
|
|
|
/* Messages are aligned to alignment required by cbprintf package. */
|
|
#define Z_LOG_MSG2_ALIGNMENT CBPRINTF_PACKAGE_ALIGNMENT
|
|
|
|
#if CONFIG_LOG2_USE_VLA
|
|
#define Z_LOG_MSG2_ON_STACK_ALLOC(ptr, len) \
|
|
long long _ll_buf[ceiling_fraction(len, sizeof(long long))]; \
|
|
long double _ld_buf[ceiling_fraction(len, sizeof(long double))]; \
|
|
ptr = (sizeof(long double) == Z_LOG_MSG2_ALIGNMENT) ? \
|
|
(struct log_msg2 *)_ld_buf : (struct log_msg2 *)_ll_buf; \
|
|
if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
|
|
/* During test fill with 0's to simplify message comparison */ \
|
|
memset(ptr, 0, len); \
|
|
}
|
|
#else /* Z_LOG_MSG2_USE_VLA */
|
|
/* When VLA cannot be used we need to trick compiler a bit and create multiple
|
|
* fixed size arrays and take the smallest one that will fit the message.
|
|
* Compiler will remove unused arrays and stack usage will be kept similar
|
|
* to vla case, rounded to the size of the used buffer.
|
|
*/
|
|
#define Z_LOG_MSG2_ON_STACK_ALLOC(ptr, len) \
|
|
long long _ll_buf32[32 / sizeof(long long)]; \
|
|
long long _ll_buf48[48 / sizeof(long long)]; \
|
|
long long _ll_buf64[64 / sizeof(long long)]; \
|
|
long long _ll_buf128[128 / sizeof(long long)]; \
|
|
long long _ll_buf256[256 / sizeof(long long)]; \
|
|
long double _ld_buf32[32 / sizeof(long double)]; \
|
|
long double _ld_buf48[48 / sizeof(long double)]; \
|
|
long double _ld_buf64[64 / sizeof(long double)]; \
|
|
long double _ld_buf128[128 / sizeof(long double)]; \
|
|
long double _ld_buf256[256 / sizeof(long double)]; \
|
|
if (sizeof(long double) == Z_LOG_MSG2_ALIGNMENT) { \
|
|
ptr = (len > 128) ? (struct log_msg2 *)_ld_buf256 : \
|
|
((len > 64) ? (struct log_msg2 *)_ld_buf128 : \
|
|
((len > 48) ? (struct log_msg2 *)_ld_buf64 : \
|
|
((len > 32) ? (struct log_msg2 *)_ld_buf48 : \
|
|
(struct log_msg2 *)_ld_buf32)));\
|
|
} else { \
|
|
ptr = (len > 128) ? (struct log_msg2 *)_ll_buf256 : \
|
|
((len > 64) ? (struct log_msg2 *)_ll_buf128 : \
|
|
((len > 48) ? (struct log_msg2 *)_ll_buf64 : \
|
|
((len > 32) ? (struct log_msg2 *)_ll_buf48 : \
|
|
(struct log_msg2 *)_ll_buf32)));\
|
|
} \
|
|
if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
|
|
/* During test fill with 0's to simplify message comparison */ \
|
|
memset(ptr, 0, len); \
|
|
}
|
|
#endif /* Z_LOG_MSG2_USE_VLA */
|
|
|
|
#define Z_LOG_MSG2_ALIGN_OFFSET \
|
|
sizeof(struct log_msg2_hdr)
|
|
|
|
#define Z_LOG_MSG2_LEN(pkg_len, data_len) \
|
|
(sizeof(struct log_msg2_hdr) + pkg_len + (data_len))
|
|
|
|
#define Z_LOG_MSG2_ALIGNED_WLEN(pkg_len, data_len) \
|
|
ceiling_fraction(ROUND_UP(Z_LOG_MSG2_LEN(pkg_len, data_len), \
|
|
Z_LOG_MSG2_ALIGNMENT), \
|
|
sizeof(uint32_t))
|
|
|
|
#define Z_LOG_MSG2_SYNC(_domain_id, _source, _level, _data, _dlen, ...) do { \
|
|
int _plen; \
|
|
CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
struct log_msg2 *_msg; \
|
|
Z_LOG_MSG2_ON_STACK_ALLOC(_msg, Z_LOG_MSG2_LEN(_plen, _dlen)); \
|
|
if (_plen) {\
|
|
CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
|
|
Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
} \
|
|
struct log_msg2_desc _desc = \
|
|
Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
|
|
(uint32_t)_plen, _dlen); \
|
|
z_log_msg2_finalize(_msg, _source, _desc, _data); \
|
|
} while (0)
|
|
|
|
#define Z_LOG_MSG2_STACK_CREATE(_domain_id, _source, _level, _data, _dlen, ...)\
|
|
do { \
|
|
int _plen; \
|
|
if (GET_ARG_N(1, __VA_ARGS__) == NULL) { \
|
|
_plen = 0; \
|
|
} else { \
|
|
CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
} \
|
|
struct log_msg2 *_msg; \
|
|
Z_LOG_MSG2_ON_STACK_ALLOC(_msg, Z_LOG_MSG2_LEN(_plen, 0)); \
|
|
if (_plen) { \
|
|
CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, \
|
|
_plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__);\
|
|
} \
|
|
struct log_msg2_desc _desc = \
|
|
Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
|
|
(uint32_t)_plen, _dlen); \
|
|
LOG_MSG2_DBG("creating message on stack: package len: %d, data len: %d\n", \
|
|
_plen, (int)(_dlen)); \
|
|
z_log_msg2_static_create((void *)_source, _desc, _msg->data, _data); \
|
|
} while (0)
|
|
|
|
#if CONFIG_LOG_SPEED
|
|
#define Z_LOG_MSG2_SIMPLE_CREATE(_domain_id, _source, _level, ...) do { \
|
|
int _plen; \
|
|
CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
size_t _msg_wlen = Z_LOG_MSG2_ALIGNED_WLEN(_plen, 0); \
|
|
struct log_msg2 *_msg = z_log_msg2_alloc(_msg_wlen); \
|
|
struct log_msg2_desc _desc = \
|
|
Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, (uint32_t)_plen, 0); \
|
|
LOG_MSG2_DBG("creating message zero copy: package len: %d, msg: %p\n", \
|
|
_plen, _msg); \
|
|
if (_msg) { \
|
|
CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
|
|
Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
} \
|
|
z_log_msg2_finalize(_msg, (void *)_source, _desc, NULL); \
|
|
} while (0)
|
|
#else
|
|
/* Alternative empty macro created to speed up compilation when LOG_SPEED is
|
|
* disabled (default).
|
|
*/
|
|
#define Z_LOG_MSG2_SIMPLE_CREATE(...)
|
|
#endif
|
|
|
|
/* Macro handles case when local variable with log message string is created.It
|
|
* replaces origing string literal with that variable.
|
|
*/
|
|
#define Z_LOG_FMT_ARGS_2(_name, ...) \
|
|
COND_CODE_1(CONFIG_LOG2_FMT_SECTION, \
|
|
(COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
|
|
(_name), (_name, GET_ARGS_LESS_N(1, __VA_ARGS__)))), \
|
|
(__VA_ARGS__))
|
|
|
|
/** @brief Wrapper for log message string with arguments.
|
|
*
|
|
* Wrapper is replacing first argument with a variable from a dedicated memory
|
|
* section if option is enabled. Macro handles the case when there is no
|
|
* log message provided.
|
|
*
|
|
* @param _name Name of the variable with log message string. It is optionally used.
|
|
* @param ... Optional log message with arguments (may be empty).
|
|
*/
|
|
#define Z_LOG_FMT_ARGS(_name, ...) \
|
|
COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
|
|
(NULL), \
|
|
(Z_LOG_FMT_ARGS_2(_name, ##__VA_ARGS__)))
|
|
|
|
/* Macro handles case when there is no string provided, in that case variable
|
|
* is not created.
|
|
*/
|
|
#define Z_LOG_MSG2_STR_VAR_IN_SECTION(_name, ...) \
|
|
COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
|
|
(/* No args provided, no variable */), \
|
|
(static const char _name[] \
|
|
__attribute__((__section__(".log_strings"))) = \
|
|
GET_ARG_N(1, __VA_ARGS__);))
|
|
|
|
/** @brief Create variable in the dedicated memory section (if enabled).
|
|
*
|
|
* Variable is initialized with a format string from the log message.
|
|
*
|
|
* @param _name Variable name.
|
|
* @param ... Optional log message with arguments (may be empty).
|
|
*/
|
|
#define Z_LOG_MSG2_STR_VAR(_name, ...) \
|
|
IF_ENABLED(CONFIG_LOG2_FMT_SECTION, \
|
|
(Z_LOG_MSG2_STR_VAR_IN_SECTION(_name, ##__VA_ARGS__)))
|
|
|
|
/** @brief Create log message and write it into the logger buffer.
|
|
*
|
|
* Macro handles creation of log message which includes storing log message
|
|
* description, timestamp, arguments, copying string arguments into message and
|
|
* copying user data into the message space. The are 3 modes of message
|
|
* creation:
|
|
* - at compile time message size is determined, message is allocated and
|
|
* content is written directly to the message. It is the fastest but cannot
|
|
* be used in user mode. Message size cannot be determined at compile time if
|
|
* it contains data or string arguments which are string pointers.
|
|
* - at compile time message size is determined, string package is created on
|
|
* stack, message is created in function call. String package can only be
|
|
* created on stack if it does not contain unexpected pointers to strings.
|
|
* - string package is created at runtime. This mode has no limitations but
|
|
* it is significantly slower.
|
|
*
|
|
* @param _try_0cpy If positive then, if possible, message content is written
|
|
* directly to message. If 0 then, if possible, string package is created on
|
|
* the stack and message is created in the function call.
|
|
*
|
|
* @param _mode Used for testing. It is set according to message creation mode
|
|
* used.
|
|
*
|
|
* @param _cstr_cnt Number of constant strings present in the string. It is
|
|
* used to help detect messages which must be runtime processed, compared to
|
|
* message which can be prebuilt at compile time.
|
|
*
|
|
* @param _domain_id Domain ID.
|
|
*
|
|
* @param _source Pointer to the constant descriptor of the log message source.
|
|
*
|
|
* @param _level Log message level.
|
|
*
|
|
* @param _data Pointer to the data. Can be null.
|
|
*
|
|
* @param _dlen Number of data bytes. 0 if data is not provided.
|
|
*
|
|
* @param ... Optional string with arguments (fmt, ...). It may be empty.
|
|
*/
|
|
#if CONFIG_LOG2_ALWAYS_RUNTIME
|
|
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
|
|
_level, _data, _dlen, ...) \
|
|
do {\
|
|
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__) \
|
|
z_log_msg2_runtime_create(_domain_id, (void *)_source, \
|
|
_level, (uint8_t *)_data, _dlen,\
|
|
Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
|
|
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
|
|
} while (0)
|
|
#elif CONFIG_LOG2_MODE_IMMEDIATE /* CONFIG_LOG2_ALWAYS_RUNTIME */
|
|
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
|
|
_level, _data, _dlen, ...) \
|
|
do { \
|
|
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
|
|
if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, __VA_ARGS__)) { \
|
|
LOG_MSG2_DBG("create runtime message\n");\
|
|
z_log_msg2_runtime_create(_domain_id, (void *)_source, \
|
|
_level, (uint8_t *)_data, _dlen,\
|
|
Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
|
|
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
|
|
} else {\
|
|
Z_LOG_MSG2_SYNC(_domain_id, _source, _level, \
|
|
_data, _dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
|
|
_mode = Z_LOG_MSG2_MODE_SYNC; \
|
|
} \
|
|
} while (0)
|
|
#else /* CONFIG_LOG2_ALWAYS_RUNTIME */
|
|
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
|
|
_level, _data, _dlen, ...) \
|
|
do { \
|
|
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
|
|
if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, __VA_ARGS__)) { \
|
|
LOG_MSG2_DBG("create runtime message\n");\
|
|
z_log_msg2_runtime_create(_domain_id, (void *)_source, \
|
|
_level, (uint8_t *)_data, _dlen,\
|
|
Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
|
|
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
|
|
} else if (IS_ENABLED(CONFIG_LOG_SPEED) && _try_0cpy && ((_dlen) == 0)) {\
|
|
LOG_MSG2_DBG("create zero-copy message\n");\
|
|
Z_LOG_MSG2_SIMPLE_CREATE(_domain_id, _source, \
|
|
_level, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
|
|
_mode = Z_LOG_MSG2_MODE_ZERO_COPY; \
|
|
} else { \
|
|
LOG_MSG2_DBG("create on stack message\n");\
|
|
Z_LOG_MSG2_STACK_CREATE(_domain_id, _source, _level, _data, \
|
|
_dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
|
|
_mode = Z_LOG_MSG2_MODE_FROM_STACK; \
|
|
} \
|
|
(void)_mode; \
|
|
} while (0)
|
|
#endif /* CONFIG_LOG2_ALWAYS_RUNTIME */
|
|
|
|
#define Z_LOG_MSG2_CREATE(_try_0cpy, _mode, _domain_id, _source,\
|
|
_level, _data, _dlen, ...) \
|
|
Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
|
|
_domain_id, _source, _level, _data, _dlen, \
|
|
Z_LOG_STR(_level, __VA_ARGS__))
|
|
|
|
#define Z_TRACING_LOG_HDR_INIT(name, id) \
|
|
struct log_msg2_trace name = { \
|
|
.hdr = { \
|
|
.type = Z_LOG_MSG2_TRACE, \
|
|
.valid = 1, \
|
|
.busy = 0, \
|
|
.evt_id = id, \
|
|
} \
|
|
}
|
|
|
|
/** @brief Finalize message.
|
|
*
|
|
* Finalization includes setting source, copying data and timestamp in the
|
|
* message followed by committing the message.
|
|
*
|
|
* @param msg Message.
|
|
*
|
|
* @param source Address of the source descriptor.
|
|
*
|
|
* @param desc Message descriptor.
|
|
*
|
|
* @param data Data.
|
|
*/
|
|
void z_log_msg2_finalize(struct log_msg2 *msg, const void *source,
|
|
const struct log_msg2_desc desc, const void *data);
|
|
|
|
/** @brief Create simple message from message details and string package.
|
|
*
|
|
* @param source Source.
|
|
*
|
|
* @param desc Message descriptor.
|
|
*
|
|
* @param package Package.
|
|
*
|
|
* @oaram data Data.
|
|
*/
|
|
__syscall void z_log_msg2_static_create(const void *source,
|
|
const struct log_msg2_desc desc,
|
|
uint8_t *package, const void *data);
|
|
|
|
/** @brief Create message at runtime.
|
|
*
|
|
* Function allows to build any log message based on input data. Processing
|
|
* time is significantly higher than statically message creating.
|
|
*
|
|
* @param domain_id Domain ID.
|
|
*
|
|
* @param source Source.
|
|
*
|
|
* @param level Log level.
|
|
*
|
|
* @param data Data.
|
|
*
|
|
* @param dlen Data length.
|
|
*
|
|
* @param fmt String.
|
|
*
|
|
* @param ap Variable list of string arguments.
|
|
*/
|
|
__syscall void z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
|
|
uint8_t level, const void *data,
|
|
size_t dlen, const char *fmt,
|
|
va_list ap);
|
|
|
|
/** @brief Create message at runtime.
|
|
*
|
|
* Function allows to build any log message based on input data. Processing
|
|
* time is significantly higher than statically message creating.
|
|
*
|
|
* @param domain_id Domain ID.
|
|
*
|
|
* @param source Source.
|
|
*
|
|
* @param level Log level.
|
|
*
|
|
* @param data Data.
|
|
*
|
|
* @param dlen Data length.
|
|
*
|
|
* @param fmt String.
|
|
*
|
|
* @param ... String arguments.
|
|
*/
|
|
static inline void z_log_msg2_runtime_create(uint8_t domain_id,
|
|
const void *source,
|
|
uint8_t level, const void *data,
|
|
size_t dlen, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
z_log_msg2_runtime_vcreate(domain_id, source, level,
|
|
data, dlen, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
static inline bool z_log_item_is_msg(union log_msg2_generic *msg)
|
|
{
|
|
return msg->generic.type == Z_LOG_MSG2_LOG;
|
|
}
|
|
|
|
/** @brief Get total length (in 32 bit words) of a log message.
|
|
*
|
|
* @param desc Log message descriptor.
|
|
*
|
|
* @return Length.
|
|
*/
|
|
static inline uint32_t log_msg2_get_total_wlen(const struct log_msg2_desc desc)
|
|
{
|
|
return Z_LOG_MSG2_ALIGNED_WLEN(desc.package_len, desc.data_len);
|
|
}
|
|
|
|
/** @brief Get length of the log item.
|
|
*
|
|
* @param item Item.
|
|
*
|
|
* @return Length in 32 bit words.
|
|
*/
|
|
static inline uint32_t log_msg2_generic_get_wlen(union mpsc_pbuf_generic *item)
|
|
{
|
|
union log_msg2_generic *generic_msg = (union log_msg2_generic *)item;
|
|
|
|
if (z_log_item_is_msg(generic_msg)) {
|
|
struct log_msg2 *msg = (struct log_msg2 *)generic_msg;
|
|
|
|
return log_msg2_get_total_wlen(msg->hdr.desc);
|
|
}
|
|
|
|
/* trace TODO */
|
|
return 0;
|
|
}
|
|
|
|
/** @brief Get log message domain ID.
|
|
*
|
|
* @param msg Log message.
|
|
*
|
|
* @return Domain ID
|
|
*/
|
|
static inline uint8_t log_msg2_get_domain(struct log_msg2 *msg)
|
|
{
|
|
return msg->hdr.desc.domain;
|
|
}
|
|
|
|
/** @brief Get log message level.
|
|
*
|
|
* @param msg Log message.
|
|
*
|
|
* @return Log level.
|
|
*/
|
|
static inline uint8_t log_msg2_get_level(struct log_msg2 *msg)
|
|
{
|
|
return msg->hdr.desc.level;
|
|
}
|
|
|
|
/** @brief Get message source data.
|
|
*
|
|
* @param msg Log message.
|
|
*
|
|
* @return Pointer to the source data.
|
|
*/
|
|
static inline const void *log_msg2_get_source(struct log_msg2 *msg)
|
|
{
|
|
return msg->hdr.source;
|
|
}
|
|
|
|
/** @brief Get timestamp.
|
|
*
|
|
* @param msg Log message.
|
|
*
|
|
* @return Timestamp.
|
|
*/
|
|
static inline log_timestamp_t log_msg2_get_timestamp(struct log_msg2 *msg)
|
|
{
|
|
return msg->hdr.timestamp;
|
|
}
|
|
|
|
/** @brief Get data buffer.
|
|
*
|
|
* @param msg log message.
|
|
*
|
|
* @param len location where data length is written.
|
|
*
|
|
* @return pointer to the data buffer.
|
|
*/
|
|
static inline uint8_t *log_msg2_get_data(struct log_msg2 *msg, size_t *len)
|
|
{
|
|
*len = msg->hdr.desc.data_len;
|
|
|
|
return msg->data + msg->hdr.desc.package_len;
|
|
}
|
|
|
|
/** @brief Get string package.
|
|
*
|
|
* @param msg log message.
|
|
*
|
|
* @param len location where string package length is written.
|
|
*
|
|
* @return pointer to the package.
|
|
*/
|
|
static inline uint8_t *log_msg2_get_package(struct log_msg2 *msg, size_t *len)
|
|
{
|
|
*len = msg->hdr.desc.package_len;
|
|
|
|
return msg->data;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#include <syscalls/log_msg2.h>
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_ */
|