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