1 /*
2 * Copyright 2020 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 *
8 */
9
10 #include <stdarg.h>
11 #include <stdlib.h>
12
13 #include "fsl_common.h"
14 #include "fsl_str.h"
15 #include "fsl_component_log.h"
16
17 #ifdef SDK_OS_FREE_RTOS
18 #include "FreeRTOS.h"
19 #include "semphr.h"
20 #endif
21
22 /*******************************************************************************
23 * Definitions
24 ******************************************************************************/
25
26 #if (LOG_ENABLE_ASYNC_MODE > 0)
27 /* MAX argument count is fixed count + user's count */
28 #define LOG_MAX_ACTUAL_ARGUMENT_COUNT (LOG_MAX_ARGUMENT_COUNT + 2)
29
30 #define LOG_GEN_ARG(n, i) (busy->argv[n - (i)])
31 #define LOG_GEN_ARGUMENT_GET_N(n) n
32
33 #define LOG_GEN_ARGUMENT_1(n, i) LOG_GEN_ARG(n, i)
34 #define LOG_GEN_ARGUMENT_2(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_1(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
35 #define LOG_GEN_ARGUMENT_3(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_2(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
36 #define LOG_GEN_ARGUMENT_4(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_3(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
37 #define LOG_GEN_ARGUMENT_5(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_4(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
38 #define LOG_GEN_ARGUMENT_6(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_5(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
39 #define LOG_GEN_ARGUMENT_7(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_6(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
40 #define LOG_GEN_ARGUMENT_8(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_7(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
41 #define LOG_GEN_ARGUMENT_9(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_8(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
42 #define LOG_GEN_ARGUMENT_10(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_9(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
43 #define LOG_GEN_ARGUMENT_11(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_10(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
44 #define LOG_GEN_ARGUMENT_12(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_11(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
45 #define LOG_GEN_ARGUMENT_13(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_12(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
46 #define LOG_GEN_ARGUMENT_14(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_13(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
47 #define LOG_GEN_ARGUMENT_15(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_14(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
48 #define LOG_GEN_ARGUMENT_16(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_15(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
49 #define LOG_GEN_ARGUMENT_17(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_16(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
50 #define LOG_GEN_ARGUMENT_18(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_17(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
51
52 #define _LOG_GEN_ARGUMENT_CAT(macro, sub) macro##sub
53 #define LOG_GEN_ARGUMENT_CAT(macro, sub) _LOG_GEN_ARGUMENT_CAT(macro, sub)
54 #define LOG_GEN_ARGUMENT(n) LOG_GEN_ARGUMENT_CAT(LOG_GEN_ARGUMENT_, LOG_GEN_ARGUMENT_GET_N(n))((n - 1), (n - 1))
55 #endif
56
57 #if (LOG_ENABLE_ASYNC_MODE > 0)
58 typedef struct log_string_node
59 {
60 struct log_string_node *next;
61 LOG_ARGUMENT_TYPE argv[LOG_MAX_ACTUAL_ARGUMENT_COUNT];
62 char const *formatString;
63 unsigned int timeStamp;
64 log_level_t level;
65 uint32_t argc;
66 } log_string_node_t;
67 #endif
68
69 typedef struct log_print_buffer
70 {
71 uint8_t *buffer;
72 size_t length;
73 size_t sofar;
74 } log_print_buffer_t;
75
76 typedef struct log_context
77 {
78 log_backend_t *backend;
79 #if (LOG_ENABLE_ASYNC_MODE > 0)
80 log_print_buffer_t printBuffer;
81 #endif
82 #if LOG_ENABLE_TIMESTAMP
83 log_get_timestamp_callback_t getTimeStamp;
84 #endif
85 #ifdef SDK_OS_FREE_RTOS
86 SemaphoreHandle_t mutex;
87 #endif
88 #if (LOG_ENABLE_ASYNC_MODE > 0)
89 log_string_node_t stringNode[LOG_MAX_BUFF_LOG_COUNT];
90 log_string_node_t *idle;
91 log_string_node_t *pend;
92 #if !(LOG_ENABLE_OVERWRITE > 0)
93 SemaphoreHandle_t idleCount;
94 #endif
95 #endif
96 uint8_t initialized;
97 } log_context_t;
98
99 #if LOG_ENABLE_COLOR
100 #define LOG_COLOR_CODE_DEFAULT \
101 "\x1B" \
102 "[0m"
103 #define LOG_COLOR_CODE_MAGENTA \
104 "\x1B" \
105 "[1;35m"
106 #define LOG_COLOR_CODE_MAGENTA_BG \
107 "\x1B" \
108 "[0;35m"
109 #define LOG_COLOR_CODE_RED \
110 "\x1B" \
111 "[1;31m"
112 #define LOG_COLOR_CODE_RED_BG \
113 "\x1B" \
114 "[0;31m"
115 #define LOG_COLOR_CODE_YELLOW \
116 "\x1B" \
117 "[1;33m"
118 #define LOG_COLOR_CODE_YELLOW_BG \
119 "\x1B" \
120 "[0;33m"
121 #define LOG_COLOR_CODE_GREEN \
122 "\x1B" \
123 "[1;32m"
124 #define LOG_COLOR_CODE_GREEN_BG \
125 "\x1B" \
126 "[0;32m"
127 #define LOG_COLOR_CODE_CYAN \
128 "\x1b" \
129 "[1;36m"
130 #define LOG_COLOR_CODE_CYAN_BG \
131 "\x1b" \
132 "[0;36m"
133 #define LOG_COLOR_CODE_BLUE \
134 "\x1B" \
135 "[1;34m"
136 #define LOG_COLOR_CODE_BLUE_BG \
137 "\x1B" \
138 "[0;34m"
139
140 #define LOG_COLOR_PRINT " %s%s%s "
141 #define LOG_COLOR_PRINT_PARAMETER(level) log_get_color(level), log_get_level_name(level), log_get_color(kLOG_LevelNone)
142 #else
143 #define LOG_COLOR_PRINT " %s "
144 #define LOG_COLOR_PRINT_PARAMETER(level) log_get_level_name(level)
145 #endif
146
147 /*******************************************************************************
148 * Prototypes
149 ******************************************************************************/
150
151 /*******************************************************************************
152 * Variables
153 ******************************************************************************/
154
155 static log_context_t s_logContext;
156 #if LOG_ENABLE_COLOR
157 static const char *s_logColor[] = {
158 LOG_COLOR_CODE_DEFAULT, LOG_COLOR_CODE_MAGENTA, LOG_COLOR_CODE_RED, LOG_COLOR_CODE_YELLOW,
159 LOG_COLOR_CODE_GREEN, LOG_COLOR_CODE_CYAN, LOG_COLOR_CODE_BLUE,
160 };
161 #endif
162 static const char *s_logLevelName[] = {
163 "None", "FATAL", "ERROR", "WARN ", "INFO ", "DEBUG", "TRACE",
164 };
165
166 /*******************************************************************************
167 * Code
168 ******************************************************************************/
log_output_low_level(uint8_t * buffer,size_t length)169 static void log_output_low_level(uint8_t *buffer, size_t length)
170 {
171 log_backend_t *backend = s_logContext.backend;
172
173 while (NULL != backend)
174 {
175 if (NULL != backend->putStr)
176 {
177 backend->putStr(buffer, length);
178 }
179 backend = backend->next;
180 }
181 }
182
log_print_to_buffer(char * buf,int32_t * indicator,char val,int len)183 static void log_print_to_buffer(char *buf, int32_t *indicator, char val, int len)
184 {
185 log_print_buffer_t *buffer = (log_print_buffer_t *)((void *)(buf));
186 int i = 0;
187
188 for (i = 0; i < len; i++)
189 {
190 if ((((size_t)(*indicator)) + buffer->sofar + ((size_t)1)) >= buffer->length)
191 {
192 break;
193 }
194
195 if ((val == '\n') &&
196 ((0 == (*indicator)) ||
197 (((uint8_t)'\r') != buffer->buffer[((size_t)(*indicator)) + buffer->sofar - ((size_t)1)])))
198 {
199 buffer->buffer[((size_t)(*indicator)) + buffer->sofar] = (uint8_t)'\r';
200 (*indicator)++;
201 }
202
203 buffer->buffer[((size_t)(*indicator)) + buffer->sofar] = (uint8_t)val;
204 (*indicator)++;
205 }
206 }
207
log_sprintf_internal(log_print_buffer_t * printBuf,char const * format,...)208 static int log_sprintf_internal(log_print_buffer_t *printBuf, char const *format, ...)
209 {
210 va_list ap;
211 int ret;
212
213 va_start(ap, format);
214 /* format print log first */
215 ret = StrFormatPrintf(format, ap, (char *)printBuf, log_print_to_buffer);
216 va_end(ap);
217
218 return ret;
219 }
220
log_get_level_name(log_level_t level)221 static char const *log_get_level_name(log_level_t level)
222 {
223 assert(((uint8_t)level < ARRAY_SIZE(s_logLevelName)));
224 return s_logLevelName[(int)level];
225 }
226
227 #if LOG_ENABLE_COLOR
log_get_color(log_level_t level)228 static char const *log_get_color(log_level_t level)
229 {
230 assert(((uint8_t)level < ARRAY_SIZE(s_logColor)));
231 return s_logColor[(int)level];
232 }
233 #endif
234
235 #if (LOG_ENABLE_ASYNC_MODE > 0)
LOG_DumpInternal(void)236 static int LOG_DumpInternal(void)
237 {
238 log_string_node_t *busy;
239 uint32_t primask;
240 int length = -1;
241
242 primask = DisableGlobalIRQ();
243 busy = s_logContext.pend;
244 if (NULL != s_logContext.pend)
245 {
246 s_logContext.pend = s_logContext.pend->next;
247 }
248 EnableGlobalIRQ(primask);
249
250 if (NULL != busy)
251 {
252 switch (busy->argc)
253 {
254 case 2:
255 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(2));
256 break;
257 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 2
258 case 3:
259 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(3));
260 break;
261 #endif
262 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 3
263 case 4:
264 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(4));
265 break;
266 #endif
267 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 4
268 case 5:
269 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(5));
270 break;
271 #endif
272 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 5
273 case 6:
274 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(6));
275 break;
276 #endif
277 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 6
278 case 7:
279 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(7));
280 break;
281 #endif
282 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 7
283 case 8:
284 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(8));
285 break;
286 #endif
287 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 8
288 case 9:
289 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(9));
290 break;
291 #endif
292 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 9
293 case 10:
294 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(10));
295 break;
296 #endif
297 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 10
298 case 11:
299 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(11));
300 break;
301 #endif
302 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 11
303 case 12:
304 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(12));
305 break;
306 #endif
307 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 12
308 case 13:
309 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(13));
310 break;
311 #endif
312 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 13
313 case 14:
314 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(14));
315 break;
316 #endif
317 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 14
318 case 15:
319 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(15));
320 break;
321 #endif
322 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 15
323 case 16:
324 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(16));
325 break;
326 #endif
327 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 16
328 case 17:
329 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(17));
330 break;
331 #endif
332 #if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 17
333 case 18:
334 LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(18));
335 break;
336 #endif
337 default:
338 /* Fix MISRA C-2012 Rule 16.4 */
339 break;
340 }
341
342 primask = DisableGlobalIRQ();
343 busy->next = s_logContext.idle;
344 s_logContext.idle = busy;
345 #if !(LOG_ENABLE_OVERWRITE > 0)
346 (void)xSemaphoreGive(s_logContext.idleCount);
347 #endif
348 EnableGlobalIRQ(primask);
349 }
350 return length;
351 }
352 #endif
353
LOG_Init(void)354 log_status_t LOG_Init(void)
355 {
356 #if (LOG_ENABLE_ASYNC_MODE > 0)
357 uint8_t i;
358 #endif
359
360 if (0U != s_logContext.initialized)
361 {
362 return kStatus_LOG_Initialized;
363 }
364
365 (void)memset(&s_logContext, 0, sizeof(s_logContext));
366 #if (LOG_ENABLE_ASYNC_MODE > 0)
367 s_logContext.idle = &s_logContext.stringNode[0];
368 for (i = 1U; i < ((uint8_t)LOG_MAX_BUFF_LOG_COUNT); i++)
369 {
370 s_logContext.stringNode[i].next = s_logContext.idle;
371 s_logContext.idle = &s_logContext.stringNode[i];
372 }
373 #if !(LOG_ENABLE_OVERWRITE > 0)
374 s_logContext.idleCount = xSemaphoreCreateCounting(LOG_MAX_BUFF_LOG_COUNT, LOG_MAX_BUFF_LOG_COUNT);
375 if (NULL == s_logContext.idleCount)
376 {
377 return kStatus_LOG_LackResource;
378 }
379 #endif
380 #endif
381
382 #ifdef SDK_OS_FREE_RTOS
383 s_logContext.mutex = xSemaphoreCreateRecursiveMutex();
384 if (NULL == s_logContext.mutex)
385 {
386 return kStatus_LOG_LackResource;
387 }
388 #endif
389 s_logContext.initialized = 1U;
390
391 return kStatus_LOG_Success;
392 }
393
LOG_Deinit(void)394 log_status_t LOG_Deinit(void)
395 {
396 if (0U == s_logContext.initialized)
397 {
398 return kStatus_LOG_Uninitialized;
399 }
400 #ifdef SDK_OS_FREE_RTOS
401 if (NULL != s_logContext.mutex)
402 {
403 vSemaphoreDelete(s_logContext.mutex);
404 s_logContext.mutex = NULL;
405 }
406 #endif
407 s_logContext.initialized = 0U;
408 return kStatus_LOG_Success;
409 }
410
411 #if LOG_ENABLE_TIMESTAMP
LOG_SetTimestamp(log_get_timestamp_callback_t getTimeStamp)412 log_status_t LOG_SetTimestamp(log_get_timestamp_callback_t getTimeStamp)
413 {
414 if (0U == s_logContext.initialized)
415 {
416 return kStatus_LOG_Uninitialized;
417 }
418
419 s_logContext.getTimeStamp = getTimeStamp;
420
421 return kStatus_LOG_Success;
422 }
423
LOG_GetTimestamp(void)424 unsigned int LOG_GetTimestamp(void)
425 {
426 if (0U == s_logContext.initialized)
427 {
428 return 0;
429 }
430
431 if (NULL != s_logContext.getTimeStamp)
432 {
433 return s_logContext.getTimeStamp();
434 }
435 return 0;
436 }
437 #endif
438
439 #if (LOG_ENABLE_ASYNC_MODE > 0)
LOG_AsyncPrintf(log_module_t const * module,log_level_t level,unsigned int timeStamp,char const * format,uint32_t argc,LOG_ARGUMENT_TYPE argv[])440 void LOG_AsyncPrintf(log_module_t const *module,
441 log_level_t level,
442 unsigned int timeStamp,
443 char const *format,
444 uint32_t argc,
445 LOG_ARGUMENT_TYPE argv[])
446 {
447 log_string_node_t *node = NULL;
448 log_string_node_t *p = NULL;
449 uint32_t primask;
450
451 assert((((uint32_t)LOG_MAX_ACTUAL_ARGUMENT_COUNT) >= argc));
452
453 do
454 {
455 primask = DisableGlobalIRQ();
456 if (NULL != s_logContext.idle)
457 {
458 node = s_logContext.idle;
459 s_logContext.idle = s_logContext.idle->next;
460 }
461 EnableGlobalIRQ(primask);
462
463 if (NULL == node)
464 {
465 #if (LOG_ENABLE_OVERWRITE > 0)
466 primask = DisableGlobalIRQ();
467 node = s_logContext.pend;
468 if (NULL != s_logContext.pend)
469 {
470 s_logContext.pend = s_logContext.pend->next;
471 }
472 EnableGlobalIRQ(primask);
473 if (NULL == node)
474 {
475 break;
476 }
477 #else
478 (void)xSemaphoreTake(s_logContext.idleCount, (TickType_t)10);
479 primask = DisableGlobalIRQ();
480 if (NULL != s_logContext.idle)
481 {
482 node = s_logContext.idle;
483 s_logContext.idle = s_logContext.idle->next;
484 }
485 EnableGlobalIRQ(primask);
486 #endif
487 }
488 }
489 #if (LOG_ENABLE_OVERWRITE > 0)
490 while (false);
491 #else
492 while (NULL == node);
493 #endif
494
495 #if (LOG_ENABLE_OVERWRITE > 0)
496 if (NULL != node)
497 #endif
498 {
499 node->formatString = format;
500 node->timeStamp = timeStamp;
501 node->level = level;
502 node->argc = argc;
503 node->next = NULL;
504 (void)memcpy(node->argv, argv, sizeof(argv[0]) * argc);
505
506 if (NULL != s_logContext.pend)
507 {
508 p = s_logContext.pend;
509 while (NULL != p->next)
510 {
511 p = p->next;
512 }
513 p->next = node;
514 }
515 else
516 {
517 s_logContext.pend = node;
518 }
519 }
520 }
521 #endif
522
LOG_Printf(log_module_t const * module,log_level_t level,unsigned int timeStamp,char const * format,...)523 void LOG_Printf(log_module_t const *module, log_level_t level, unsigned int timeStamp, char const *format, ...)
524 {
525 va_list ap;
526 log_print_buffer_t buffer;
527 uint8_t printBuf[LOG_MAX_MEESSAGE_LENGTH];
528
529 (void)module;
530
531 if (0U == s_logContext.initialized)
532 {
533 return;
534 }
535
536 #ifdef SDK_OS_FREE_RTOS
537 if (((BaseType_t)0) == (BaseType_t)xSemaphoreTakeRecursive(s_logContext.mutex, portMAX_DELAY))
538 {
539 return;
540 }
541 #endif
542
543 #if (LOG_ENABLE_ASYNC_MODE > 0)
544 if (NULL != s_logContext.printBuffer.buffer)
545 {
546 (void)memcpy(&buffer, &s_logContext.printBuffer, sizeof(buffer));
547 }
548 else
549 #endif
550 {
551 buffer.buffer = printBuf;
552 buffer.length = LOG_MAX_MEESSAGE_LENGTH;
553 buffer.sofar = 0;
554 }
555
556 /* print timestamp */
557 #if LOG_ENABLE_TIMESTAMP
558 buffer.sofar += (size_t)log_sprintf_internal(&buffer, "%12d:", timeStamp);
559 #endif
560 /* print level name */
561 buffer.sofar += (size_t)log_sprintf_internal(&buffer, LOG_COLOR_PRINT, LOG_COLOR_PRINT_PARAMETER(level));
562
563 va_start(ap, format);
564 /* format print log first */
565 buffer.sofar += (size_t)StrFormatPrintf(format, ap, (char *)&buffer, log_print_to_buffer);
566
567 va_end(ap);
568 #if (LOG_ENABLE_ASYNC_MODE > 0)
569 s_logContext.printBuffer.sofar = buffer.sofar;
570 #endif
571 log_output_low_level(buffer.buffer, buffer.sofar);
572
573 #ifdef SDK_OS_FREE_RTOS
574 if (((BaseType_t)0) == (BaseType_t)xSemaphoreGiveRecursive(s_logContext.mutex))
575 {
576 return;
577 }
578 #endif
579 }
580
LOG_BackendRegister(log_backend_t * backend)581 log_status_t LOG_BackendRegister(log_backend_t *backend)
582 {
583 log_backend_t *p = s_logContext.backend;
584 log_status_t ret = kStatus_LOG_BackendExist;
585 uint32_t regPrimask;
586
587 assert(NULL != backend);
588
589 if (0U == s_logContext.initialized)
590 {
591 return kStatus_LOG_Uninitialized;
592 }
593
594 regPrimask = DisableGlobalIRQ();
595 while (NULL != p)
596 {
597 if (p == backend)
598 {
599 break;
600 }
601 p = p->next;
602 }
603 if (NULL == p)
604 {
605 backend->next = s_logContext.backend;
606 s_logContext.backend = backend;
607 ret = kStatus_LOG_Success;
608 }
609 EnableGlobalIRQ(regPrimask);
610 return ret;
611 }
612
LOG_BackendUnregister(log_backend_t * backend)613 log_status_t LOG_BackendUnregister(log_backend_t *backend)
614 {
615 log_backend_t *p = s_logContext.backend;
616 log_backend_t *q = s_logContext.backend;
617 log_status_t ret = kStatus_LOG_BackendNotFound;
618 uint32_t regPrimask;
619
620 assert(NULL != backend);
621
622 if (0U == s_logContext.initialized)
623 {
624 return kStatus_LOG_Uninitialized;
625 }
626
627 regPrimask = DisableGlobalIRQ();
628 while (NULL != p)
629 {
630 if (p == backend)
631 {
632 if (q == p)
633 {
634 s_logContext.backend = p->next;
635 }
636 else
637 {
638 q->next = p->next;
639 }
640 p->next = NULL;
641 ret = kStatus_LOG_Success;
642 }
643 q = p;
644 p = p->next;
645 }
646 EnableGlobalIRQ(regPrimask);
647
648 return ret;
649 }
650
651 #if (LOG_ENABLE_ASYNC_MODE > 0)
LOG_Dump(uint8_t * buffer,size_t length,size_t * outLength)652 void LOG_Dump(uint8_t *buffer, size_t length, size_t *outLength)
653 {
654 s_logContext.printBuffer.buffer = buffer;
655 s_logContext.printBuffer.length = length;
656 s_logContext.printBuffer.sofar = (size_t)0;
657 (void)LOG_DumpInternal();
658 if ((NULL != buffer) && (((size_t)0) != length) && (NULL != outLength))
659 {
660 *outLength = s_logContext.printBuffer.sofar;
661 }
662 }
663 #endif
664