HALFRED  0.4.0
hal_log.h
Go to the documentation of this file.
1 
67 #ifndef HAL_LOG_H_
68 #define HAL_LOG_H_
69 
70 #include "hal_config.h"
71 #include "hal_iodevice.h"
72 #include <stdint.h>
73 #include <stdbool.h>
74 #include <inttypes.h>
75 
76 #if 1 == HAL_ENABLE_OS
77 #include "hal_os.h"
78 typedef OSTime HAL_LOG_Time;
79 #else
80 typedef uint32_t HAL_LOG_Time;
81 #endif
82 
83 #ifndef HAL_ENABLE_LOG
84  #define HAL_ENABLE_LOG 0
85 #endif // #ifndef HAL_ENABLE_LOG
86 
87 #ifndef HAL_LOG_LAST_CHANNEL
88  #define HAL_LOG_LAST_CHANNEL 0 // The default channel count is 1 (DEFAULT) since last channel is 0
89 #endif // #ifndef HAL_LOG_LAST_CHANNEL
90 
91 #ifndef HAL_LOG_CHANNEL
92  #define HAL_LOG_CHANNEL DEFAULT
93 #endif // #ifndef HAL_LOG_CHANNEL
94 
95 #ifndef DEFAULT_LOG_CHANNEL
96  #define DEFAULT_LOG_CHANNEL 0
97 #elif DEFAULT_LOG_CHANNEL != 0
98  #error DEFAULT_LOG_CHANNEL redefined to non-zero value!
99 #endif // #ifndef DEFAULT_LOG_CHANNEL
100 
101 #ifndef HAL_LOG_LEVEL
102  #define HAL_LOG_LEVEL HAL_LOG_LEVEL_NOTICE // The default log verbosity
103 #endif // #ifndef HAL_LOG_LEVEL
104 
105 // Definitions of valid log levels (according to syslog)
106 #define HAL_LOG_LEVEL_EMERGENCY 0
107 #define HAL_LOG_LEVEL_ALERT 1
108 #define HAL_LOG_LEVEL_CRITICAL 2
109 #define HAL_LOG_LEVEL_ERROR 3
110 #define HAL_LOG_LEVEL_WARNING 4
111 #define HAL_LOG_LEVEL_NOTICE 5
112 #define HAL_LOG_LEVEL_INFO 6
113 #define HAL_LOG_LEVEL_DEBUG 7
114 
115 // The usage of the macros below is similar to csdio's printf function:
116 // The first argument is the format string, the latter arguments should be variables that will be substituted in the format string
117 #define HAL_LOG_EMERGENCY(...) HAL_LOG(HAL_LOG_LEVEL_EMERGENCY, __VA_ARGS__)
118 #define HAL_LOG_ALERT(...) HAL_LOG(HAL_LOG_LEVEL_ALERT, __VA_ARGS__)
119 #define HAL_LOG_CRITICAL(...) HAL_LOG(HAL_LOG_LEVEL_CRITICAL, __VA_ARGS__)
120 #define HAL_LOG_ERROR(...) HAL_LOG(HAL_LOG_LEVEL_ERROR, __VA_ARGS__)
121 #define HAL_LOG_WARNING(...) HAL_LOG(HAL_LOG_LEVEL_WARNING, __VA_ARGS__)
122 #define HAL_LOG_NOTICE(...) HAL_LOG(HAL_LOG_LEVEL_NOTICE, __VA_ARGS__)
123 #define HAL_LOG_INFO(...) HAL_LOG(HAL_LOG_LEVEL_INFO, __VA_ARGS__)
124 #define HAL_LOG_DEBUG(...) HAL_LOG(HAL_LOG_LEVEL_DEBUG, __VA_ARGS__)
125 
126 #define HAL_ASSERT(condition) if(!(condition)) do { HAL_LOG_CRITICAL("Assertion failed in " __FILE__ ":%u\n", __LINE__); } while(0)
127 #define HAL_ASSERT_AND_EXECUTE(condition) HAL_ASSERT(condition); else
128 
129 
130 
131 
132 
133 
141 bool HAL_LOG_SetChannelOutput(const uint8_t channel, IODevice const iodev);
142 
143 
151 bool HAL_LOG_SetChannelTimeSource(const uint8_t channel, HAL_LOG_Time (*timeSourceFunction)(void));
152 
153 
160 bool HAL_LOG_EnableChannel(const uint8_t channel);
161 
162 
169 bool HAL_LOG_DisableChannel(const uint8_t channel);
170 
171 
178 bool HAL_LOG_IsChannelEnabled(const uint8_t channel);
179 
180 
181 // The content below must NOT be altered (unless you are a developer or the almighty guinea pig)
182 
183 #if 1 == HAL_ENABLE_LOG
184  // Sanity checks
185  #if (HAL_LOG_LAST_CHANNEL < UINT16_MIN) || (HAL_LOG_LAST_CHANNEL > (UINT16_MAX - 1))
186  #error HAL_LOG_MAX_CHANNEL_NUMBER is outside of bounds
187  #endif // #if (HAL_LOG_LAST_CHANNEL < UINT16_MIN) || (HAL_LOG_LAST_CHANNEL > (UINT16_MAX - 1))
188 
189  #if (HAL_LOG_LEVEL < HAL_LOG_LEVEL_EMERGENCY) || (HAL_LOG_LEVEL > HAL_LOG_LEVEL_DEBUG)
190  #error HAL_LOG_LEVEL is outside of bounds
191  #endif // #if (HAL_LOG_LEVEL < HAL_LOG_LEVEL_EMERGENCY) || (HAL_LOG_LEVEL > HAL_LOG_LEVEL_DEBUG)
192 
193  // Define helper macros
194  #define HALI_STR(x) HALI_STR1(x) // Stringifies macro (first level of indirection)
195  #define HALI_STR1(x) #x // Stringifies macro (second level of indirection)
196  #define CAT(x, y) CAT1(x, y) // Concatenates two macro (first level of indirection)
197  #define CAT1(a, b) a ## b // Concatenates two macro (second level of indirection)
198  #define SECOND(a1, a2, ...) a2 // Returns second argument
199  #define IS_PROBE(...) SECOND(__VA_ARGS__, 0)
200  #define PROBE() ~, 1
201  #define NOT(x) IS_PROBE(CAT(NOT_, x)) // Logic negation of macro
202  #define NOT_0 PROBE()
203  #define BOOL(x) NOT(NOT(x)) // Returns logical value of the macro
204  #define IF_ELSE(x) IF_ELSE1(BOOL(x)) // Compile time if statement. usage: IF_ELSE(x)(if_true)(else)
205  #define IF_ELSE1(x) CAT1(IF_, x)
206  #define IF_1(...) __VA_ARGS__ IF_1_ELSE
207  #define IF_0(...) IF_0_ELSE
208  #define IF_1_ELSE(...)
209  #define IF_0_ELSE(...) __VA_ARGS__
210 
211 
212  // Verify if the log channel is enabled by macro ($HAL_LOG_CHANNEL)_LOG_CHANNEL_ENABLED (i.e. APP_LOG_CHANNEL_ENABLED)
213  // When the macro was defined and set to 1 (i.e. #define APP_LOG_CHANNEL_ENABLED 1) the value is 1
214  // When the macro was defined and set to 0 (i.e. #define APP_LOG_CHANNEL_ENABLED 0) the value is 0
215  // When the macro was NOT defined the value is 1
216  // Notice that HAL_LOG_CHANNEL is always defined either explicitly, or by default to DEFAULT.
217  #if 1 == IF_ELSE(CAT(HAL_LOG_CHANNEL, _LOG_CHANNEL_ENABLED))(1)(0)
218  // Look for descriptor number for this channel (i.e. #define APP_LOG_CHANNEL 1)
219  #define HALI_CHANNEL CAT(HAL_LOG_CHANNEL, _LOG_CHANNEL)
220  // Check if using default channel - if not, perform sanity check on channel number
221  // There is no need to check Default channel, as it is already verified
222  #define HALI_IF_LOG_CHANNEL_DEFAULT 1
223  #if (1 == CAT(HALI_IF_LOG_CHANNEL_, HAL_LOG_CHANNEL)) || (HALI_CHANNEL > 0)
224  #if (HALI_CHANNEL <= HAL_LOG_LAST_CHANNEL)
225  // Adjust the maximum log level at user's discretion (i.e #define APP_LOG_CHANNEL_LEVEL HAL_LOG_LEVEL_NOTICE)
226  #define HALI_LOG_CHANNEL_LEVEL CAT(HAL_LOG_CHANNEL, _LOG_CHANNEL_LEVEL)
227  #define HALI_LOG_IF_CHANNEL_LEVEL_0 1
228  #if (1 == CAT(HALI_LOG_IF_CHANNEL_LEVEL_, HALI_LOG_CHANNEL_LEVEL)) || (HALI_LOG_CHANNEL_LEVEL > 0)
229  #if HALI_LOG_CHANNEL_LEVEL <= HAL_LOG_LEVEL
230  #undef HAL_LOG_LEVEL
231  #define HAL_LOG_LEVEL HALI_LOG_CHANNEL_LEVEL
232  #else
233  #warning ($HAL_LOG_CHANNEL)_LOG_CHANNEL_LEVEL is bigger than HAL_LOG_LEVEL - defaults to HAL_LOG_LEVEL
234  #endif // #if HALI_LOG_CHANNEL_LEVEL <= HAL_LOG_LEVEL
235  #endif // #if (1 == CAT(HALI_LOG_IF_CHANNEL_LEVEL_, HALI_LOG_CHANNEL_LEVEL)) || (HALI_LOG_CHANNEL_LEVEL > 0)
236  #undef HALI_LOG_IF_CHANNEL_LEVEL_0
237 
238  // At this point, all requisitions to enable log CHANNEL have been met
239 
240  // Check if HAL_LOG_SUBCHANNEL macro was defined, that would indicate that this is a subchannel log
241  #ifdef HAL_LOG_SUBCHANNEL
242  // Verify if the log channel is enabled by macro ($HAL_LOG_CHANNEL)_($HAL_LOG_SUBCHANNEL)_LOG_SUBCHANNEL_ENABLED (i.e. APP_FOO_LOG_SUBCHANNEL_ENABLED)
243  // When the macro was defined and set to 1 (i.e. #define APP_FOO_LOG_CHANNEL_ENABLED 1) the value is 1
244  // When the macro was defined and set to 0 (i.e. #define APP_FOO_LOG_CHANNEL_ENABLED 0) the value is 0
245  // When the macro was NOT defined the value is 1
246  #if 1 == IF_ELSE(CAT(CAT(CAT(HAL_LOG_CHANNEL, _), HAL_LOG_SUBCHANNEL), _LOG_SUBCHANNEL_ENABLED))(1)(0)
247  #define HALI_LOG_SUBCHANNEL_LEVEL CAT(CAT(CAT(HAL_LOG_CHANNEL, _), HAL_LOG_SUBCHANNEL), _LOG_SUBCHANNEL_LEVEL)
248  #define HALI_LOG_IF_SUBCHANNEL_LEVEL_0 1
249  #if (1 == CAT(HALI_LOG_IF_SUBCHANNEL_LEVEL_, HALI_LOG_SUBCHANNEL_LEVEL)) || (HALI_LOG_SUBCHANNEL_LEVEL > 0)
250  #if (HALI_LOG_SUBCHANNEL_LEVEL <= HAL_LOG_LEVEL)
251  #undef HAL_LOG_LEVEL
252  #define HAL_LOG_LEVEL HALI_LOG_SUBCHANNEL_LEVEL
253  #else
254  #warning ($HAL_LOG_CHANNEL)_($HAL_LOG_SUBCHANNEL)_LOG_SUBCHANNEL_LEVEL is bigger than HAL_LOG_LEVEL - defaults to HAL_LOG_LEVEL
255  #endif // (HALI_LOG_SUBCHANNEL_LEVEL <= HAL_LOG_LEVEL)
256  #endif // #if (1 == CAT(HALI_LOG_IF_SUBCHANNEL_LEVEL_, HALI_LOG_SUBCHANNEL_LEVEL)) || (HALI_LOG_SUBCHANNEL_LEVEL > 0)
257  #undef HALI_LOG_IF_CHANNEL_LEVEL_0
258 
259  #define HALI_LOG_HEADER CAT(CAT(HAL_LOG_CHANNEL, _), HAL_LOG_SUBCHANNEL)
260  #define HALI_LOG_ENABLED 1
261  #endif // #if 1 == IF_ELSE(CAT(CAT(CAT(HAL_LOG_CHANNEL, _), HAL_LOG_SUBCHANNEL), _LOG_SUBCHANNEL_ENABLED))(1)(0)
262  #else
263  #define HALI_LOG_HEADER HAL_LOG_CHANNEL
264  #define HALI_LOG_ENABLED 1
265  #endif // #ifdef HAL_LOG_SUBCHANNEL
266  #else
267  #warning Channel descriptor (($HAL_LOG_CHANNEL)_LOG_CHANNEL) is bigger than HAL_LOG_LAST_CHANNEL - the channel will remain disabled
268  #endif // #if (HALI_CHANNEL <= HAL_LOG_LAST_CHANNEL)
269  #else
270  #warning Channel descriptor ($HAL_LOG_CHANNEL)_LOG_CHANNEL_LEVEL not defined - the channel will remain disabled
271  #endif // #if (1 == CAT(HALI_IF_LOG_CHANNEL_, HAL_LOG_CHANNEL)) || (HALI_CHANNEL > 0)
272  #undef HALI_IF_LOG_CHANNEL_DEFAULT
273  #endif // #if 1 == IF_ELSE(CAT(HAL_LOG_CHANNEL, _LOG_CHANNEL_ENABLED))(1)(0)
274 #endif // #if 1 == HAL_ENABLE_LOG
275 
276 #if 1 == HALI_LOG_ENABLED
277  void HAL_LOG_Log(const uint8_t channel, const uint8_t level, const char* const channelName, const HAL_LOG_Time timeout, const char* format, ...);
278  #define HAL_LOG(level, ...) if(level <= HAL_LOG_LEVEL) HAL_LOG_Log(HALI_CHANNEL, UINT8_C(level), HALI_STR(HALI_LOG_HEADER), 0, __VA_ARGS__);
279 #else
280  #define HAL_LOG(level, ...)
281 #endif // #if 1 == HALI_LOG_ENABLED
282 
283 #endif // #ifndef HAL_LOG_H_
bool HAL_LOG_SetChannelOutput(const uint8_t channel, IODevice const iodev)
IODevice API.
Definition: hali_iodevice.h:44
bool HAL_LOG_DisableChannel(const uint8_t channel)
bool HAL_LOG_EnableChannel(const uint8_t channel)
uint32_t HAL_LOG_Time
Definition: hal_log.h:80
bool HAL_LOG_SetChannelTimeSource(const uint8_t channel, HAL_LOG_Time(*timeSourceFunction)(void))
Operating system (OS) API.
bool HAL_LOG_IsChannelEnabled(const uint8_t channel)