/** * @file sys_log.h * @author LokLiang (lokliang@163.com) * @brief * @version 0.1 * @date 2023-05-01 * * @copyright Copyright (c) 2023 * */ #ifndef __SYS_LOG_H__ #define __SYS_LOG_H__ #include "sys_types.h" #include #include #ifdef __cplusplus extern "C" { #endif #ifndef SYS_LOG_DOMAIN #define SYS_LOG_DOMAIN "general" #endif #ifndef CONFIG_SYS_LOG_LEVEL #define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF /* 配置日志打印的等级 */ #endif #define SYS_LOG_LEVEL_OFF 0 #define SYS_LOG_LEVEL_ERR 1 #define SYS_LOG_LEVEL_WRN 2 #define SYS_LOG_LEVEL_INF 3 #define SYS_LOG_LEVEL_DBG 4 #ifndef CONFIG_SYS_LOG_COLOR_ON #define CONFIG_SYS_LOG_COLOR_ON 1 /* 使能打印颜色 */ #endif #ifndef CONFIG_SYS_LOG_LOCAL_ON #define CONFIG_SYS_LOG_LOCAL_ON 1 /* 强制使能打印所在文件位置 */ #endif #define SYS_PRINT printf #define SYS_VPRINT vprintf #define SYS_SPRINT sprintf #define SYS_SNPRINT snprintf #define SYS_VSNPRINT vsnprintf #ifndef CONFIG_SYS_LOG_CONS_ON extern const int *g_sys_log_on; #define CONFIG_SYS_LOG_CONS_ON ((CONFIG_SYS_LOG_LEVEL > SYS_LOG_LEVEL_OFF) && (*g_sys_log_on != 0)) /* 打印控制总开关 */ #endif #ifndef CONFIG_SYS_LOG_DUMP_ON #define CONFIG_SYS_LOG_DUMP_ON CONFIG_SYS_LOG_DBG_ON /* 使能打印二进制和十六进制类型 */ #endif #ifndef CONFIG_SYS_LOG_DBG_ON #define CONFIG_SYS_LOG_DBG_ON (CONFIG_SYS_LOG_LEVEL >= SYS_LOG_LEVEL_DBG) /* 使能打印调试类型*/ #endif #ifndef CONFIG_SYS_LOG_INF_ON #define CONFIG_SYS_LOG_INF_ON (CONFIG_SYS_LOG_LEVEL >= SYS_LOG_LEVEL_INF) /* 使能打印信息类型 */ #endif #ifndef CONFIG_SYS_LOG_WRN_ON #define CONFIG_SYS_LOG_WRN_ON (CONFIG_SYS_LOG_LEVEL >= SYS_LOG_LEVEL_WRN) /* 使能打印警告类型 */ #endif #ifndef CONFIG_SYS_LOG_ERR_ON #define CONFIG_SYS_LOG_ERR_ON (CONFIG_SYS_LOG_LEVEL >= SYS_LOG_LEVEL_ERR) /* 使能打印错误类型 */ #endif #ifndef CONFIG_SYS_LOG_ASS_ON #define CONFIG_SYS_LOG_ASS_ON (CONFIG_SYS_LOG_LEVEL >= SYS_LOG_LEVEL_INF) /* 使能有效性检测 */ #endif #define CONS_PRINT(FMT, ...) \ do \ { \ if (CONFIG_SYS_LOG_CONS_ON) \ { \ SYS_PRINT(FMT, ##__VA_ARGS__); \ } \ } while (0) #ifndef CONS_ABORT #define CONS_ABORT() \ do \ { \ volatile int FLAG = 0; \ do \ { \ } while (FLAG == 0); \ } while (0) #endif #if (CONFIG_SYS_LOG_COLOR_ON == 1) #define _COLOR_R "\033[31m" /* 红 RED */ #define _COLOR_G "\033[32m" /* 绿 GREEN */ #define _COLOR_Y "\033[33m" /* 黄 YELLOW */ #define _COLOR_B "\033[34m" /* 蓝 BLUE */ #define _COLOR_P "\033[35m" /* 紫 PURPLE */ #define _COLOR_C "\033[36m" /* 青 CYAN */ #define _COLOR_RY "\033[41;33m" /* 红底黄字 */ #define _COLOR_END "\033[0m" /* 结束 */ #else #define _COLOR_R "" /* 红 */ #define _COLOR_G "" /* 绿 */ #define _COLOR_Y "" /* 黄 */ #define _COLOR_B "" /* 蓝 */ #define _COLOR_P "" /* 紫 */ #define _COLOR_C "" /* 青 */ #define _COLOR_RY "" /* 红底黄字 */ #define _COLOR_END "" /* 结束 */ #endif #define _DO_SYS_LOG(FLAG, FMT, ARG...) \ do \ { \ if (FLAG) \ { \ CONS_PRINT(FMT, ##ARG); \ } \ } while (0) #define _FILENAME(FILE) (strrchr(FILE, '/') ? (strrchr(FILE, '/') + 1) : (strrchr(FILE, '\\') ? (strrchr(FILE, '\\') + 1) : FILE)) #define _GEN_DOMAIN "[" SYS_LOG_DOMAIN "] " #define _SYS_LOG(FLAG, INFO, FMT, ...) _DO_SYS_LOG(FLAG, INFO "%s:%u \t%s =>\t" FMT "\r\n", \ _FILENAME(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__) #if (CONFIG_SYS_LOG_LOCAL_ON == 1 || CONFIG_SYS_LOG_DBG_ON == 1) #define _SYS_LOG_COLOR(FLAG, INFO, COLOR, FMT, ...) _DO_SYS_LOG(FLAG, INFO "%s:%u \t%s =>\t" COLOR FMT _COLOR_END "\r\n", \ _FILENAME(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__) #else #define _SYS_LOG_COLOR(FLAG, INFO, COLOR, FMT, ...) _DO_SYS_LOG(FLAG, INFO "%s =>\t" COLOR FMT _COLOR_END "\r\n", \ __FUNCTION__, ##__VA_ARGS__) #endif #define SYS_LOG_DBG(FMT, ...) _SYS_LOG(CONFIG_SYS_LOG_DBG_ON, "[DBG] " _GEN_DOMAIN, FMT, ##__VA_ARGS__) #define SYS_LOG_INF(FMT, ...) _SYS_LOG_COLOR(CONFIG_SYS_LOG_INF_ON, "[INF] | " _GEN_DOMAIN, _COLOR_G, FMT, ##__VA_ARGS__) #define SYS_LOG_WRN(FMT, ...) _SYS_LOG_COLOR(CONFIG_SYS_LOG_WRN_ON, "[WRN] * " _GEN_DOMAIN, _COLOR_Y, FMT, ##__VA_ARGS__) #define SYS_LOG_ERR(FMT, ...) \ do \ { \ if (CONFIG_SYS_LOG_ERR_ON) \ { \ _SYS_LOG_COLOR(1, "[ERR] - " _GEN_DOMAIN, _COLOR_R, FMT, ##__VA_ARGS__); \ CONS_ABORT(); \ } \ } while (0) #define SYS_LOG(FMT, ...) \ do \ { \ if (CONFIG_SYS_LOG_CONS_ON) \ { \ CONS_PRINT(_GEN_DOMAIN "- %s:%u, %s =>\t" _COLOR_B FMT _COLOR_END "\r\n", \ _FILENAME(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__); \ } \ } while (0) #define SYS_ASSERT_FALSE(EXP, FMT, ...) \ do \ { \ if (CONFIG_SYS_LOG_ASS_ON && (EXP)) \ { \ CONS_PRINT("[ASS] # " _GEN_DOMAIN "%s:%u \t%s =>\t" _COLOR_RY "%s" _COLOR_END "; ## " FMT "\r\n", \ _FILENAME(__FILE__), __LINE__, __FUNCTION__, #EXP, ##__VA_ARGS__); \ CONS_ABORT(); \ } \ } while (0) #define SYS_ASSERT(EXP, FMT, ...) \ do \ { \ if (CONFIG_SYS_LOG_ASS_ON && !(EXP)) \ { \ CONS_PRINT("[ASS] # " _GEN_DOMAIN "%s:%u \t%s =>\t" _COLOR_RY "!(%s)" _COLOR_END "; ## " FMT "\r\n", \ _FILENAME(__FILE__), __LINE__, __FUNCTION__, #EXP, ##__VA_ARGS__); \ CONS_ABORT(); \ } \ } while (0) /** * @brief Print data in hexadecima * * @param P point to data base * @param SIZE data size (bytes) * @param ALIGN word length, 1, 2, 4, 8 * @param ENDIAN 0 -- little-endian, 1 -- big-endian */ #define SYS_LOG_DUMP(P, SIZE, ALIGN, ENDIAN) \ do \ { \ if (CONFIG_SYS_LOG_CONS_ON && CONFIG_SYS_LOG_DUMP_ON) \ { \ _SYS_LOG_COLOR(1, "[HEX]: " _GEN_DOMAIN, _COLOR_C, #P ": %d bytes%s", \ SIZE, \ ALIGN <= 1 ? "" : ENDIAN ? ", big-endian" \ : ", little-endian"); \ _sys_log_dump((unsigned)P, P, SIZE, ALIGN, ENDIAN); \ } \ } while (0) /** * @brief Print data in binary * * @param P point to data base * @param SIZE data size (bytes) * @param ALIGN word length, 1, 2, 4, 8 * @param ENDIAN 0 -- little-endian, 1 -- big-endian */ #define SYS_LOG_BIN(P, SIZE, ALIGN, ENDIAN) \ do \ { \ if (CONFIG_SYS_LOG_CONS_ON && CONFIG_SYS_LOG_DUMP_ON) \ { \ _SYS_LOG_COLOR(1, "[BIN]: " _GEN_DOMAIN, _COLOR_C, #P ": %d bytes%s", \ SIZE, \ ALIGN <= 1 ? "" : ENDIAN ? ", big-endian" \ : ", little-endian"); \ _sys_log_bin((unsigned)P, P, SIZE, ALIGN, ENDIAN); \ } \ } while (0) __static_inline void _sys_log_dump(unsigned addr, const void *p, int size, int width, int endian) { #define BYTES_PRE_LINE 16 if (size) { int i, ii, j; char buf[4 + 4 * BYTES_PRE_LINE]; char *ascii; int len1; int len2; int lenmax; width = (width <= 1 ? 1 : (width <= 2 ? 2 : (width <= 4 ? 4 : 8))); size = (size + width - 1) / width; len1 = (1 + width * 2) * ((BYTES_PRE_LINE + width - 1) / width) - 1; len2 = 3 + (BYTES_PRE_LINE + width - 1) / width * width; lenmax = len1 + len2; ascii = &buf[len1 + 2]; for (i = 0; i < 6 + sizeof(void *) * 2; i++) { SYS_PRINT("-"); } for (i = 0; i < lenmax; i++) { buf[i] = '-'; } buf[i] = '\0'; SYS_PRINT("%s\r\n", buf); ii = (BYTES_PRE_LINE + width - 1) / width; while (size) { int index1 = 0; int index2 = 0; SYS_PRINT(_COLOR_Y "[" _COLOR_END "0x%08X" _COLOR_Y "]" _COLOR_END ": ", (unsigned)addr); for (i = 0; i < ii;) { for (j = 0; j < width; j++) { if (endian) { index1 += SYS_SPRINT(&buf[index1], "%02x", ((uint8_t *)p)[j]); } else { index1 += SYS_SPRINT(&buf[index1], "%02x", ((uint8_t *)p)[width - j - 1]); } if (((uint8_t *)p)[j] >= ' ' && ((uint8_t *)p)[j] < 0x7f) { index2 += SYS_SPRINT(&ascii[index2], "%c", ((uint8_t *)p)[j]); } else { index2 += SYS_SPRINT(&ascii[index2], "."); } } addr += width; p = &((uint8_t *)p)[width]; if (--size > 0 && ++i < ii) { index1 += SYS_SPRINT(&buf[index1], " "); } else { while (index1 < len1) { buf[index1++] = ' '; } buf[index1++] = ' '; buf[index1++] = '|'; index1 += index2; while (index1 < lenmax - 1) { buf[index1++] = ' '; } buf[index1++] = '\0'; SYS_PRINT("%s|\r\n", buf); } if (size == 0) { for (i = 0; i < 6 + sizeof(void *) * 2; i++) { SYS_PRINT("="); } for (i = 0; i < lenmax; i++) { buf[i] = '='; } buf[i] = '\0'; SYS_PRINT("%s\r\n", buf); break; } } } } #undef BYTES_PRE_LINE } __static_inline void _sys_log_bin(unsigned addr, const void *p, int size, int width, int endian) { #define BITS_PRE_LINE 64 if (size) { uint8_t value[8]; int i, j; int lenmax; width = (width <= 1 ? 1 : (width <= 2 ? 2 : (width <= 4 ? 4 : 8))); width = width < BITS_PRE_LINE ? width : BITS_PRE_LINE; size = (size + width - 1) / width * width; lenmax = (1 + 3 * 8) * width; for (i = 0; i < 9 + sizeof(void *) * 2 + width * 2 + width * 8 / 4 + lenmax; i++) { SYS_PRINT("-"); } SYS_PRINT("\r\n"); for (i = 0; i < 8 + sizeof(void *) * 2 + width * 2; i++) { SYS_PRINT(" "); } for (i = 0; i < 8 * width; i++) { if (i % 4 == 0) { if (i % 8 == 0) { SYS_PRINT(" "); } SYS_PRINT(" "); } SYS_PRINT("%3d", 8 * width - 1 - i); } SYS_PRINT("\r\n"); for (i = 0; i < 9 + sizeof(void *) * 2 + width * 2 + width * 8 / 4 + lenmax; i++) { SYS_PRINT("~"); } SYS_PRINT("\r\n"); while (size) { SYS_PRINT(_COLOR_Y "[" _COLOR_END "0x%08X" _COLOR_Y "]" _COLOR_END ": 0x", (unsigned)addr); if (endian) { for (i = 0; i < width; i++) { value[i] = ((uint8_t *)p)[i]; SYS_PRINT("%02X", value[i]); } } else { for (i = 0; i < width; i++) { value[i] = ((uint8_t *)p)[width - 1 - i]; SYS_PRINT("%02X", value[i]); } } for (i = 0; i < width; i++) { for (j = 0; j < 8; j++) { if (j % 4 == 0) { SYS_PRINT(" "); if (j % 8 == 0) { SYS_PRINT(" "); } } if (value[i] >> (7 - j) & 1) { SYS_PRINT(" 1"); } else { SYS_PRINT(" 0"); } } } SYS_PRINT("\n"); addr += width; p = &((uint8_t *)p)[width]; size -= width; if (size == 0) { for (i = 0; i < 9 + sizeof(void *) * 2 + width * 2 + width * 8 / 4 + lenmax; i++) { SYS_PRINT("="); } SYS_PRINT("\r\n"); } } } #undef BITS_PRE_LINE } #ifdef __cplusplus } #endif #endif