Files
2026-04-09 10:14:20 +08:00

193 lines
3.8 KiB
C

#include "mx_log.h"
#include <stdio.h>
#if MX_LOG_BACKEND_RTT
#include "SEGGER_RTT.h"
#endif
#ifndef MX_LOG_LINE_BUF_SIZE
#define MX_LOG_LINE_BUF_SIZE 256U
#endif
#ifndef MX_LOG_DEFAULT_LEVEL
#define MX_LOG_DEFAULT_LEVEL MX_LOG_LEVEL_DEBUG
#endif
static volatile mx_log_level_t s_log_level = MX_LOG_DEFAULT_LEVEL;
static mx_log_writer_t s_log_writer = 0;
static uint8_t s_log_inited = 0U;
static const char *mx_log_level_to_str(mx_log_level_t level)
{
switch (level) {
case MX_LOG_LEVEL_ERROR:
return "E";
case MX_LOG_LEVEL_WARN:
return "W";
case MX_LOG_LEVEL_INFO:
return "I";
case MX_LOG_LEVEL_DEBUG:
default:
return "D";
}
}
static size_t mx_log_strnlen(const char *s, size_t maxlen)
{
size_t len = 0U;
if (s == 0) {
return 0U;
}
while ((len < maxlen) && (s[len] != '\0')) {
len++;
}
return len;
}
static void mx_log_output_line(const char *line)
{
if (line == 0) {
return;
}
if (s_log_writer != 0) {
s_log_writer(line);
return;
}
#if MX_LOG_BACKEND_RTT
SEGGER_RTT_WriteString(0, line);
#elif MX_LOG_BACKEND_STDIO
(void)fputs(line, stdout);
#else
(void)line;
#endif
}
void mx_log_init(void)
{
if (s_log_inited) {
return;
}
#if MX_LOG_BACKEND_RTT
SEGGER_RTT_Init();
SEGGER_RTT_SetTerminal(0);
#endif
s_log_inited = 1U;
}
void mx_log_set_level(mx_log_level_t level)
{
s_log_level = level;
}
mx_log_level_t mx_log_get_level(void)
{
return s_log_level;
}
void mx_log_set_writer(mx_log_writer_t writer)
{
s_log_writer = writer;
}
void mx_log_vprintf(mx_log_level_t level, const char *tag, const char *fmt, va_list ap)
{
char line[MX_LOG_LINE_BUF_SIZE];
int prefix_len;
int payload_len;
size_t line_len;
if ((fmt == 0) || (level > s_log_level)) {
return;
}
if (!MX_LOG_ENABLE) {
return;
}
if (!s_log_inited) {
mx_log_init();
}
prefix_len = snprintf(line,
sizeof(line),
"[%s][%s] ",
mx_log_level_to_str(level),
(tag != 0) ? tag : "");
if (prefix_len < 0) {
return;
}
if ((size_t)prefix_len >= sizeof(line)) {
line[sizeof(line) - 1U] = '\0';
mx_log_output_line(line);
return;
}
payload_len = vsnprintf(line + prefix_len, sizeof(line) - (size_t)prefix_len, fmt, ap);
(void)payload_len;
line_len = mx_log_strnlen(line, sizeof(line));
if ((line_len + 2U) < sizeof(line)) {
line[line_len++] = '\r';
line[line_len++] = '\n';
line[line_len] = '\0';
} else {
line[sizeof(line) - 1U] = '\0';
}
mx_log_output_line(line);
}
void mx_log_printf(mx_log_level_t level, const char *tag, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
mx_log_vprintf(level, tag, fmt, ap);
va_end(ap);
}
void mx_log_hex_frame(const char *tag, const uint8_t *data, uint16_t len)
{
static const char hex[] = "0123456789ABCDEF";
char line[(32U * 3U) + 1U];
uint16_t i = 0U;
if ((data == 0) || (len == 0U)) {
return;
}
while (i < len) {
uint16_t chunk = (uint16_t)(len - i);
uint16_t pos = 0U;
uint16_t j;
if (chunk > 32U) {
chunk = 32U;
}
for (j = 0U; j < chunk; j++) {
uint8_t v = data[(uint16_t)(i + j)];
line[pos++] = hex[(v >> 4) & 0x0FU];
line[pos++] = hex[v & 0x0FU];
line[pos++] = ' ';
}
if (pos > 0U) {
line[pos - 1U] = '\0';
} else {
line[0] = '\0';
}
MX_LOGD((tag != 0) ? tag : "HEX", "%s", line);
i = (uint16_t)(i + chunk);
}
}