1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 /**
7  * @file
8  * Custom logging
9  */
10 
11 #ifndef SOC_NORDIC_COMMON_ZEPHYR_CUSTOM_LOG_H_
12 #define SOC_NORDIC_COMMON_ZEPHYR_CUSTOM_LOG_H_
13 
14 #include <zephyr/logging/log_frontend_stmesp.h>
15 #include <zephyr/sys/cbprintf_internal.h>
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 /* Undef to override those macros. */
22 #undef LOG_ERR
23 #undef LOG_WRN
24 #undef LOG_INF
25 #undef LOG_DBG
26 #undef LOG_INST_ERR
27 #undef LOG_INST_WRN
28 #undef LOG_INST_INF
29 #undef LOG_INST_DBG
30 
31 /** @brief Optimized macro for log message with no arguments.
32  *
33  * In order to compress information, logging level is stringified and prepended
34  * to the string.
35  *
36  * @param _level Level.
37  * @param _module_const_source Constant module structure.
38  * @param _source Source structure (dynamic or constant).
39  * @param ... String (with no arguments).
40  */
41 #define Z_LOG_STMESP_0(_level, _source, ...)                                                       \
42 	do {                                                                                       \
43 		if (!Z_LOG_LEVEL_ALL_CHECK(_level, __log_current_const_data, _source)) {           \
44 			break;                                                                     \
45 		}                                                                                  \
46 		LOG_FRONTEND_STMESP_LOG0(_source, STRINGIFY(_level) __VA_ARGS__);                  \
47 	} while (0)
48 
49 /** @brief Determine if first argument is a numeric value that fits in 32 bit word.
50  *
51  * @return 1 if yes and 0 if not.
52  */
53 #define Z_LOG_STMESP_1_ARG_CHECK(...)                                                              \
54 	COND_CODE_1(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
55 			(Z_CBPRINTF_IS_WORD_NUM(GET_ARG_N(2, __VA_ARGS__, dummy))), (0))
56 
57 /** @brief Optimized macro for log message with 1 numeric argument.
58  *
59  * In order to compress information, logging level is stringified and prepended
60  * to the string.
61  *
62  * @param _level Level.
63  * @param _module_const_source Constant module structure.
64  * @param _source Source structure (dynamic or constant).
65  * @param ... String (with 1 argument).
66  */
67 #define Z_LOG_STMESP_1(_level, _source, ...)                                                       \
68 	do {                                                                                       \
69 		/* Do turbo logging only if argument fits in 32 bit word. */                       \
70 		if (!Z_LOG_STMESP_1_ARG_CHECK(__VA_ARGS__)) {                                      \
71 			COND_CODE_1(CONFIG_LOG_FRONTEND_STMESP_TURBO_DROP_OTHERS, (),              \
72 				(Z_LOG(_level, __VA_ARGS__)));                                     \
73 			break;                                                                     \
74 		}                                                                                  \
75 		if (!Z_LOG_LEVEL_ALL_CHECK(_level, __log_current_const_data, _source)) {           \
76 			break;                                                                     \
77 		}                                                                                  \
78 		LOG_FRONTEND_STMESP_LOG1(_source, STRINGIFY(_level) __VA_ARGS__, dummy);           \
79 	} while (0)
80 
81 /** @brief Top level logging macro.
82  *
83  * Macro is using special approach for short log message (0 or 1 numeric argument)
84  * and proceeds with standard approach (or optionally drops) for remaining messages.
85  *
86  * @param _level Severity level.
87  * @param _source Pointer to a structure associated with the source.
88  * @param ... String with arguments.
89  */
90 #define Z_LOG_STMESP(_level, _source, ...)                                                         \
91 	COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__),                                     \
92 		(Z_LOG_STMESP_0(_level, _source, __VA_ARGS__)), (                        \
93 		COND_CODE_1(NUM_VA_ARGS_LESS_1(__VA_ARGS__),                             \
94 			(Z_LOG_STMESP_1(_level, _source, __VA_ARGS__)),                  \
95 			(                                                                \
96 			if (!IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_TURBO_DROP_OTHERS)) { \
97 				Z_LOG(_level, __VA_ARGS__);                              \
98 			}))))
99 
100 /* Overridden logging API macros. */
101 #define LOG_ERR(...) Z_LOG_STMESP(LOG_LEVEL_ERR, Z_LOG_CURRENT_DATA(), __VA_ARGS__)
102 #define LOG_WRN(...) Z_LOG_STMESP(LOG_LEVEL_WRN, Z_LOG_CURRENT_DATA(), __VA_ARGS__)
103 #define LOG_INF(...) Z_LOG_STMESP(LOG_LEVEL_INF, Z_LOG_CURRENT_DATA(), __VA_ARGS__)
104 #define LOG_DBG(...) Z_LOG_STMESP(LOG_LEVEL_DBG, Z_LOG_CURRENT_DATA(), __VA_ARGS__)
105 
106 #define LOG_INST_ERR(_inst, ...) Z_LOG_STMESP(LOG_LEVEL_ERR, Z_LOG_INST(_inst), __VA_ARGS__)
107 #define LOG_INST_WRN(_inst, ...) Z_LOG_STMESP(LOG_LEVEL_WRN, Z_LOG_INST(_inst), __VA_ARGS__)
108 #define LOG_INST_INF(_inst, ...) Z_LOG_STMESP(LOG_LEVEL_INF, Z_LOG_INST(_inst), __VA_ARGS__)
109 #define LOG_INST_DBG(_inst, ...) Z_LOG_STMESP(LOG_LEVEL_DBG, Z_LOG_INST(_inst), __VA_ARGS__)
110 
111 #if CONFIG_LOG_FRONTEND_STMESP_TURBO_DROP_OTHERS
112 #undef LOG_RAW
113 #undef LOG_PRINTK
114 #undef LOG_HEXDUMP_ERR
115 #undef LOG_HEXDUMP_WRN
116 #undef LOG_HEXDUMP_INF
117 #undef LOG_HEXDUMP_DBG
118 #undef LOG_INST_HEXDUMP_ERR
119 #undef LOG_INST_HEXDUMP_WRN
120 #undef LOG_INST_HEXDUMP_INF
121 #undef LOG_INST_HEXDUMP_DBG
122 
123 #define LOG_RAW(...)                                                                               \
124 	do {                                                                                       \
125 		if (0) {                                                                           \
126 			Z_LOG_PRINTK(1, __VA_ARGS__);                                              \
127 		}                                                                                  \
128 	} while (0)
129 
130 #define LOG_PRINTK(...)                                                                            \
131 	do {                                                                                       \
132 		if (0) {                                                                           \
133 			Z_LOG_PRINTK(1, __VA_ARGS__);                                              \
134 		}                                                                                  \
135 	} while (0)
136 
137 #define LOG_HEXDUMP_ERR(_data, _length, _str)             (void)_data
138 #define LOG_HEXDUMP_WRN(_data, _length, _str)             (void)_data
139 #define LOG_HEXDUMP_INF(_data, _length, _str)             (void)_data
140 #define LOG_HEXDUMP_DBG(_data, _length, _str)             (void)_data
141 #define LOG_INST_HEXDUMP_ERR(_inst, _data, _length, _str) (void)_data
142 #define LOG_INST_HEXDUMP_WRN(_inst, _data, _length, _str) (void)_data
143 #define LOG_INST_HEXDUMP_INF(_inst, _data, _length, _str) (void)_data
144 #define LOG_INST_HEXDUMP_DBG(_inst, _data, _length, _str) (void)_data
145 #endif
146 
147 #ifdef __cplusplus
148 }
149 #endif
150 
151 #endif /* SOC_NORDIC_COMMON_ZEPHYR_CUSTOM_LOG_H_ */
152