664 lines
19 KiB
C
664 lines
19 KiB
C
/*
|
|
* Copyright 2020 NXP
|
|
* All rights reserved.
|
|
*
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "fsl_common.h"
|
|
#include "fsl_str.h"
|
|
#include "fsl_component_log.h"
|
|
|
|
#ifdef SDK_OS_FREE_RTOS
|
|
#include "FreeRTOS.h"
|
|
#include "semphr.h"
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
/* MAX argument count is fixed count + user's count */
|
|
#define LOG_MAX_ACTUAL_ARGUMENT_COUNT (LOG_MAX_ARGUMENT_COUNT + 2)
|
|
|
|
#define LOG_GEN_ARG(n, i) (busy->argv[n - (i)])
|
|
#define LOG_GEN_ARGUMENT_GET_N(n) n
|
|
|
|
#define LOG_GEN_ARGUMENT_1(n, i) LOG_GEN_ARG(n, i)
|
|
#define LOG_GEN_ARGUMENT_2(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_1(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_3(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_2(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_4(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_3(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_5(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_4(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_6(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_5(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_7(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_6(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_8(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_7(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_9(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_8(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_10(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_9(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_11(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_10(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_12(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_11(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_13(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_12(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_14(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_13(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_15(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_14(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_16(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_15(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_17(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_16(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
#define LOG_GEN_ARGUMENT_18(n, i) LOG_GEN_ARG(n, i), LOG_GEN_ARGUMENT_17(n, LOG_GEN_ARGUMENT_GET_N(i - 1))
|
|
|
|
#define _LOG_GEN_ARGUMENT_CAT(macro, sub) macro##sub
|
|
#define LOG_GEN_ARGUMENT_CAT(macro, sub) _LOG_GEN_ARGUMENT_CAT(macro, sub)
|
|
#define LOG_GEN_ARGUMENT(n) LOG_GEN_ARGUMENT_CAT(LOG_GEN_ARGUMENT_, LOG_GEN_ARGUMENT_GET_N(n))((n - 1), (n - 1))
|
|
#endif
|
|
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
typedef struct log_string_node
|
|
{
|
|
struct log_string_node *next;
|
|
LOG_ARGUMENT_TYPE argv[LOG_MAX_ACTUAL_ARGUMENT_COUNT];
|
|
char const *formatString;
|
|
unsigned int timeStamp;
|
|
log_level_t level;
|
|
uint32_t argc;
|
|
} log_string_node_t;
|
|
#endif
|
|
|
|
typedef struct log_print_buffer
|
|
{
|
|
uint8_t *buffer;
|
|
size_t length;
|
|
size_t sofar;
|
|
} log_print_buffer_t;
|
|
|
|
typedef struct log_context
|
|
{
|
|
log_backend_t *backend;
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
log_print_buffer_t printBuffer;
|
|
#endif
|
|
#if LOG_ENABLE_TIMESTAMP
|
|
log_get_timestamp_callback_t getTimeStamp;
|
|
#endif
|
|
#ifdef SDK_OS_FREE_RTOS
|
|
SemaphoreHandle_t mutex;
|
|
#endif
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
log_string_node_t stringNode[LOG_MAX_BUFF_LOG_COUNT];
|
|
log_string_node_t *idle;
|
|
log_string_node_t *pend;
|
|
#if !(LOG_ENABLE_OVERWRITE > 0)
|
|
SemaphoreHandle_t idleCount;
|
|
#endif
|
|
#endif
|
|
uint8_t initialized;
|
|
} log_context_t;
|
|
|
|
#if LOG_ENABLE_COLOR
|
|
#define LOG_COLOR_CODE_DEFAULT \
|
|
"\x1B" \
|
|
"[0m"
|
|
#define LOG_COLOR_CODE_MAGENTA \
|
|
"\x1B" \
|
|
"[1;35m"
|
|
#define LOG_COLOR_CODE_MAGENTA_BG \
|
|
"\x1B" \
|
|
"[0;35m"
|
|
#define LOG_COLOR_CODE_RED \
|
|
"\x1B" \
|
|
"[1;31m"
|
|
#define LOG_COLOR_CODE_RED_BG \
|
|
"\x1B" \
|
|
"[0;31m"
|
|
#define LOG_COLOR_CODE_YELLOW \
|
|
"\x1B" \
|
|
"[1;33m"
|
|
#define LOG_COLOR_CODE_YELLOW_BG \
|
|
"\x1B" \
|
|
"[0;33m"
|
|
#define LOG_COLOR_CODE_GREEN \
|
|
"\x1B" \
|
|
"[1;32m"
|
|
#define LOG_COLOR_CODE_GREEN_BG \
|
|
"\x1B" \
|
|
"[0;32m"
|
|
#define LOG_COLOR_CODE_CYAN \
|
|
"\x1b" \
|
|
"[1;36m"
|
|
#define LOG_COLOR_CODE_CYAN_BG \
|
|
"\x1b" \
|
|
"[0;36m"
|
|
#define LOG_COLOR_CODE_BLUE \
|
|
"\x1B" \
|
|
"[1;34m"
|
|
#define LOG_COLOR_CODE_BLUE_BG \
|
|
"\x1B" \
|
|
"[0;34m"
|
|
|
|
#define LOG_COLOR_PRINT " %s%s%s "
|
|
#define LOG_COLOR_PRINT_PARAMETER(level) log_get_color(level), log_get_level_name(level), log_get_color(kLOG_LevelNone)
|
|
#else
|
|
#define LOG_COLOR_PRINT " %s "
|
|
#define LOG_COLOR_PRINT_PARAMETER(level) log_get_level_name(level)
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
static log_context_t s_logContext;
|
|
#if LOG_ENABLE_COLOR
|
|
static const char *s_logColor[] = {
|
|
LOG_COLOR_CODE_DEFAULT, LOG_COLOR_CODE_MAGENTA, LOG_COLOR_CODE_RED, LOG_COLOR_CODE_YELLOW,
|
|
LOG_COLOR_CODE_GREEN, LOG_COLOR_CODE_CYAN, LOG_COLOR_CODE_BLUE,
|
|
};
|
|
#endif
|
|
static const char *s_logLevelName[] = {
|
|
"None", "FATAL", "ERROR", "WARN ", "INFO ", "DEBUG", "TRACE",
|
|
};
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
static void log_output_low_level(uint8_t *buffer, size_t length)
|
|
{
|
|
log_backend_t *backend = s_logContext.backend;
|
|
|
|
while (NULL != backend)
|
|
{
|
|
if (NULL != backend->putStr)
|
|
{
|
|
backend->putStr(buffer, length);
|
|
}
|
|
backend = backend->next;
|
|
}
|
|
}
|
|
|
|
static void log_print_to_buffer(char *buf, int32_t *indicator, char val, int len)
|
|
{
|
|
log_print_buffer_t *buffer = (log_print_buffer_t *)((void *)(buf));
|
|
int i = 0;
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
if ((((size_t)(*indicator)) + buffer->sofar + ((size_t)1)) >= buffer->length)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ((val == '\n') &&
|
|
((0 == (*indicator)) ||
|
|
(((uint8_t)'\r') != buffer->buffer[((size_t)(*indicator)) + buffer->sofar - ((size_t)1)])))
|
|
{
|
|
buffer->buffer[((size_t)(*indicator)) + buffer->sofar] = (uint8_t)'\r';
|
|
(*indicator)++;
|
|
}
|
|
|
|
buffer->buffer[((size_t)(*indicator)) + buffer->sofar] = (uint8_t)val;
|
|
(*indicator)++;
|
|
}
|
|
}
|
|
|
|
static int log_sprintf_internal(log_print_buffer_t *printBuf, char const *format, ...)
|
|
{
|
|
va_list ap;
|
|
int ret;
|
|
|
|
va_start(ap, format);
|
|
/* format print log first */
|
|
ret = StrFormatPrintf(format, ap, (char *)printBuf, log_print_to_buffer);
|
|
va_end(ap);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static char const *log_get_level_name(log_level_t level)
|
|
{
|
|
assert(((uint8_t)level < ARRAY_SIZE(s_logLevelName)));
|
|
return s_logLevelName[(int)level];
|
|
}
|
|
|
|
#if LOG_ENABLE_COLOR
|
|
static char const *log_get_color(log_level_t level)
|
|
{
|
|
assert(((uint8_t)level < ARRAY_SIZE(s_logColor)));
|
|
return s_logColor[(int)level];
|
|
}
|
|
#endif
|
|
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
static int LOG_DumpInternal(void)
|
|
{
|
|
log_string_node_t *busy;
|
|
uint32_t primask;
|
|
int length = -1;
|
|
|
|
primask = DisableGlobalIRQ();
|
|
busy = s_logContext.pend;
|
|
if (NULL != s_logContext.pend)
|
|
{
|
|
s_logContext.pend = s_logContext.pend->next;
|
|
}
|
|
EnableGlobalIRQ(primask);
|
|
|
|
if (NULL != busy)
|
|
{
|
|
switch (busy->argc)
|
|
{
|
|
case 2:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(2));
|
|
break;
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 2
|
|
case 3:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(3));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 3
|
|
case 4:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(4));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 4
|
|
case 5:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(5));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 5
|
|
case 6:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(6));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 6
|
|
case 7:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(7));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 7
|
|
case 8:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(8));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 8
|
|
case 9:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(9));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 9
|
|
case 10:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(10));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 10
|
|
case 11:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(11));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 11
|
|
case 12:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(12));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 12
|
|
case 13:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(13));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 13
|
|
case 14:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(14));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 14
|
|
case 15:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(15));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 15
|
|
case 16:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(16));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 16
|
|
case 17:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(17));
|
|
break;
|
|
#endif
|
|
#if LOG_MAX_ACTUAL_ARGUMENT_COUNT > 17
|
|
case 18:
|
|
LOG_Printf(NULL, busy->level, busy->timeStamp, (const char *)busy->formatString, LOG_GEN_ARGUMENT(18));
|
|
break;
|
|
#endif
|
|
default:
|
|
/* Fix MISRA C-2012 Rule 16.4 */
|
|
break;
|
|
}
|
|
|
|
primask = DisableGlobalIRQ();
|
|
busy->next = s_logContext.idle;
|
|
s_logContext.idle = busy;
|
|
#if !(LOG_ENABLE_OVERWRITE > 0)
|
|
(void)xSemaphoreGive(s_logContext.idleCount);
|
|
#endif
|
|
EnableGlobalIRQ(primask);
|
|
}
|
|
return length;
|
|
}
|
|
#endif
|
|
|
|
log_status_t LOG_Init(void)
|
|
{
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
uint8_t i;
|
|
#endif
|
|
|
|
if (0U != s_logContext.initialized)
|
|
{
|
|
return kStatus_LOG_Initialized;
|
|
}
|
|
|
|
(void)memset(&s_logContext, 0, sizeof(s_logContext));
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
s_logContext.idle = &s_logContext.stringNode[0];
|
|
for (i = 1U; i < ((uint8_t)LOG_MAX_BUFF_LOG_COUNT); i++)
|
|
{
|
|
s_logContext.stringNode[i].next = s_logContext.idle;
|
|
s_logContext.idle = &s_logContext.stringNode[i];
|
|
}
|
|
#if !(LOG_ENABLE_OVERWRITE > 0)
|
|
s_logContext.idleCount = xSemaphoreCreateCounting(LOG_MAX_BUFF_LOG_COUNT, LOG_MAX_BUFF_LOG_COUNT);
|
|
if (NULL == s_logContext.idleCount)
|
|
{
|
|
return kStatus_LOG_LackResource;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef SDK_OS_FREE_RTOS
|
|
s_logContext.mutex = xSemaphoreCreateRecursiveMutex();
|
|
if (NULL == s_logContext.mutex)
|
|
{
|
|
return kStatus_LOG_LackResource;
|
|
}
|
|
#endif
|
|
s_logContext.initialized = 1U;
|
|
|
|
return kStatus_LOG_Success;
|
|
}
|
|
|
|
log_status_t LOG_Deinit(void)
|
|
{
|
|
if (0U == s_logContext.initialized)
|
|
{
|
|
return kStatus_LOG_Uninitialized;
|
|
}
|
|
#ifdef SDK_OS_FREE_RTOS
|
|
if (NULL != s_logContext.mutex)
|
|
{
|
|
vSemaphoreDelete(s_logContext.mutex);
|
|
s_logContext.mutex = NULL;
|
|
}
|
|
#endif
|
|
s_logContext.initialized = 0U;
|
|
return kStatus_LOG_Success;
|
|
}
|
|
|
|
#if LOG_ENABLE_TIMESTAMP
|
|
log_status_t LOG_SetTimestamp(log_get_timestamp_callback_t getTimeStamp)
|
|
{
|
|
if (0U == s_logContext.initialized)
|
|
{
|
|
return kStatus_LOG_Uninitialized;
|
|
}
|
|
|
|
s_logContext.getTimeStamp = getTimeStamp;
|
|
|
|
return kStatus_LOG_Success;
|
|
}
|
|
|
|
unsigned int LOG_GetTimestamp(void)
|
|
{
|
|
if (0U == s_logContext.initialized)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (NULL != s_logContext.getTimeStamp)
|
|
{
|
|
return s_logContext.getTimeStamp();
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
void LOG_AsyncPrintf(log_module_t const *module,
|
|
log_level_t level,
|
|
unsigned int timeStamp,
|
|
char const *format,
|
|
uint32_t argc,
|
|
LOG_ARGUMENT_TYPE argv[])
|
|
{
|
|
log_string_node_t *node = NULL;
|
|
log_string_node_t *p = NULL;
|
|
uint32_t primask;
|
|
|
|
assert((((uint32_t)LOG_MAX_ACTUAL_ARGUMENT_COUNT) >= argc));
|
|
|
|
do
|
|
{
|
|
primask = DisableGlobalIRQ();
|
|
if (NULL != s_logContext.idle)
|
|
{
|
|
node = s_logContext.idle;
|
|
s_logContext.idle = s_logContext.idle->next;
|
|
}
|
|
EnableGlobalIRQ(primask);
|
|
|
|
if (NULL == node)
|
|
{
|
|
#if (LOG_ENABLE_OVERWRITE > 0)
|
|
primask = DisableGlobalIRQ();
|
|
node = s_logContext.pend;
|
|
if (NULL != s_logContext.pend)
|
|
{
|
|
s_logContext.pend = s_logContext.pend->next;
|
|
}
|
|
EnableGlobalIRQ(primask);
|
|
if (NULL == node)
|
|
{
|
|
break;
|
|
}
|
|
#else
|
|
(void)xSemaphoreTake(s_logContext.idleCount, (TickType_t)10);
|
|
primask = DisableGlobalIRQ();
|
|
if (NULL != s_logContext.idle)
|
|
{
|
|
node = s_logContext.idle;
|
|
s_logContext.idle = s_logContext.idle->next;
|
|
}
|
|
EnableGlobalIRQ(primask);
|
|
#endif
|
|
}
|
|
}
|
|
#if (LOG_ENABLE_OVERWRITE > 0)
|
|
while (false);
|
|
#else
|
|
while (NULL == node);
|
|
#endif
|
|
|
|
#if (LOG_ENABLE_OVERWRITE > 0)
|
|
if (NULL != node)
|
|
#endif
|
|
{
|
|
node->formatString = format;
|
|
node->timeStamp = timeStamp;
|
|
node->level = level;
|
|
node->argc = argc;
|
|
node->next = NULL;
|
|
(void)memcpy(node->argv, argv, sizeof(argv[0]) * argc);
|
|
|
|
if (NULL != s_logContext.pend)
|
|
{
|
|
p = s_logContext.pend;
|
|
while (NULL != p->next)
|
|
{
|
|
p = p->next;
|
|
}
|
|
p->next = node;
|
|
}
|
|
else
|
|
{
|
|
s_logContext.pend = node;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void LOG_Printf(log_module_t const *module, log_level_t level, unsigned int timeStamp, char const *format, ...)
|
|
{
|
|
va_list ap;
|
|
log_print_buffer_t buffer;
|
|
uint8_t printBuf[LOG_MAX_MEESSAGE_LENGTH];
|
|
|
|
(void)module;
|
|
|
|
if (0U == s_logContext.initialized)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef SDK_OS_FREE_RTOS
|
|
if (((BaseType_t)0) == (BaseType_t)xSemaphoreTakeRecursive(s_logContext.mutex, portMAX_DELAY))
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
if (NULL != s_logContext.printBuffer.buffer)
|
|
{
|
|
(void)memcpy(&buffer, &s_logContext.printBuffer, sizeof(buffer));
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
buffer.buffer = printBuf;
|
|
buffer.length = LOG_MAX_MEESSAGE_LENGTH;
|
|
buffer.sofar = 0;
|
|
}
|
|
|
|
/* print timestamp */
|
|
#if LOG_ENABLE_TIMESTAMP
|
|
buffer.sofar += (size_t)log_sprintf_internal(&buffer, "%12d:", timeStamp);
|
|
#endif
|
|
/* print level name */
|
|
buffer.sofar += (size_t)log_sprintf_internal(&buffer, LOG_COLOR_PRINT, LOG_COLOR_PRINT_PARAMETER(level));
|
|
|
|
va_start(ap, format);
|
|
/* format print log first */
|
|
buffer.sofar += (size_t)StrFormatPrintf(format, ap, (char *)&buffer, log_print_to_buffer);
|
|
|
|
va_end(ap);
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
s_logContext.printBuffer.sofar = buffer.sofar;
|
|
#endif
|
|
log_output_low_level(buffer.buffer, buffer.sofar);
|
|
|
|
#ifdef SDK_OS_FREE_RTOS
|
|
if (((BaseType_t)0) == (BaseType_t)xSemaphoreGiveRecursive(s_logContext.mutex))
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
log_status_t LOG_BackendRegister(log_backend_t *backend)
|
|
{
|
|
log_backend_t *p = s_logContext.backend;
|
|
log_status_t ret = kStatus_LOG_BackendExist;
|
|
uint32_t regPrimask;
|
|
|
|
assert(NULL != backend);
|
|
|
|
if (0U == s_logContext.initialized)
|
|
{
|
|
return kStatus_LOG_Uninitialized;
|
|
}
|
|
|
|
regPrimask = DisableGlobalIRQ();
|
|
while (NULL != p)
|
|
{
|
|
if (p == backend)
|
|
{
|
|
break;
|
|
}
|
|
p = p->next;
|
|
}
|
|
if (NULL == p)
|
|
{
|
|
backend->next = s_logContext.backend;
|
|
s_logContext.backend = backend;
|
|
ret = kStatus_LOG_Success;
|
|
}
|
|
EnableGlobalIRQ(regPrimask);
|
|
return ret;
|
|
}
|
|
|
|
log_status_t LOG_BackendUnregister(log_backend_t *backend)
|
|
{
|
|
log_backend_t *p = s_logContext.backend;
|
|
log_backend_t *q = s_logContext.backend;
|
|
log_status_t ret = kStatus_LOG_BackendNotFound;
|
|
uint32_t regPrimask;
|
|
|
|
assert(NULL != backend);
|
|
|
|
if (0U == s_logContext.initialized)
|
|
{
|
|
return kStatus_LOG_Uninitialized;
|
|
}
|
|
|
|
regPrimask = DisableGlobalIRQ();
|
|
while (NULL != p)
|
|
{
|
|
if (p == backend)
|
|
{
|
|
if (q == p)
|
|
{
|
|
s_logContext.backend = p->next;
|
|
}
|
|
else
|
|
{
|
|
q->next = p->next;
|
|
}
|
|
p->next = NULL;
|
|
ret = kStatus_LOG_Success;
|
|
}
|
|
q = p;
|
|
p = p->next;
|
|
}
|
|
EnableGlobalIRQ(regPrimask);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#if (LOG_ENABLE_ASYNC_MODE > 0)
|
|
void LOG_Dump(uint8_t *buffer, size_t length, size_t *outLength)
|
|
{
|
|
s_logContext.printBuffer.buffer = buffer;
|
|
s_logContext.printBuffer.length = length;
|
|
s_logContext.printBuffer.sofar = (size_t)0;
|
|
(void)LOG_DumpInternal();
|
|
if ((NULL != buffer) && (((size_t)0) != length) && (NULL != outLength))
|
|
{
|
|
*outLength = s_logContext.printBuffer.sofar;
|
|
}
|
|
}
|
|
#endif
|