#include "mx_log.h" #include #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); } }