diff --git a/include/HDLog.h b/include/HDLog.h new file mode 100644 index 0000000..125fb2f --- /dev/null +++ b/include/HDLog.h @@ -0,0 +1,138 @@ + + +#ifndef __HD_NEW_LOG_H__ +#define __HD_NEW_LOG_H__ + +#include "sys/_intsup.h" +#include + +// 使用宏开关管理日志 +#ifndef LOG_CLOSE_OUT +#define USE_HD_LOG_DEBUG 1 +#define USE_HD_LOG_ERROR 1 +#define USE_HD_LOG_DATA 1 +#endif +#define USE_HD_TRACE 0 + +// 当前检查栈数量的线程总数 +#define USE_CHECK_STACK_NUM (1) + + +// 标准日志输出 +#define _LogDExtLevel(level, format, ...) HDLogOut(1, level, __FILE__, __func__, __LINE__, format, ##__VA_ARGS__) +#define _LogDLevel(level, format, ...) HDLogOut(0, level, __FILE__, __func__, __LINE__, format, ##__VA_ARGS__) + +#if USE_HD_TRACE +#define LogTrace() LogD() +#else +#define LogTrace() +#endif + +#if USE_HD_LOG_DEBUG +#define LogD(format, ...) _LogDLevel(kLogLevelDebug, format, ##__VA_ARGS__) +#define LogDExt(format, ...) _LogDExtLevel(kLogLevelDebug, format, ##__VA_ARGS__) +#define LogLine() LogDExt("\r\n") +#else +#define LogD(...) +#define LogDExt(...) +#define LogLine() +#endif + +#if USE_HD_LOG_ERROR +#define LogE(format, ...) _LogDLevel(0, kLogLevelError, __FILE__, format, ##__VA_ARGS__) +#else +#define LogE(...) +#endif + +#if USE_HD_LOG_DATA +#define LogData(data, len) HDLogData((const uint8_t *)data, len, 1) +#define LogFpgaData(data, len, isWrite) do { if (HDLogPrintFpgaHeader((const uint8_t *)data, len, isWrite)) { HDLogHex((const uint8_t *)(data) + 17, (len) - 21, 1, NULL); } } while (0) +#define LogHexData(data, len) HDLogHex((const uint8_t *)data, len, 1, NULL) +#else +#define LogData(data, len) +#define LogFpgaData(data, len, isWrite) +#define LogHexData(data, len) +#endif + + +enum eLogLevel { + kLogLevelSwitch = 0, ///< 日志开关 + kLogLevelColor, ///< 彩色日志 + kLogLevelDebug, ///< 常规调试信息 + kLogLevelError, ///< 错误信息 + kLogLevelHex, ///< 十六进制日志 + kLogLevelStack, ///< 打印栈大小信息 + kLogLevelMax, +}; + +/** + * @brief 日志初始化 + */ +void HDLogInit(uint32_t (*getTime)()); + +/** + * @brief 格式打印 + **/ +void HDLogOut(uint8_t ext, uint8_t level, const char *fileName, const char *funcName, int line, const char *format, ...); + +/** + * @brief 打印FPGA头 + * @param data FPGA头数据 + * @param len 数据长度 + * @param isWrite 是否是写 + * @return 是fpga数据或者需要打印返回1 否则返回0 + */ +uint8_t HDLogPrintFpgaHeader(const uint8_t *data, int len, uint8_t isWrite); + +/** + * @brief 十六进制格式打印数据 + * @param data 数据 + * @param len 数据长度 + * @param checkPrint 是否检查打印开关是否打开 + * @param offset 打印偏移, 一般传递 NULL 即可 + **/ +void HDLogHex(const uint8_t *data, int len, uint8_t checkPrint, uint32_t *offset); + +/** + * @brief 无格式以16进制打印数据, 打印16个换行 + * @param data 数据 + * @param len 数据长度 + * @param checkPrint 是否检查打印开关是否打开 + */ +void HDLogData(const uint8_t *data, int len, uint8_t checkPrint); + + +typedef unsigned long(*HDLogGetTaskType_t)(); +/** + * @brief 设置获取当前任务的方法 + * @param getTask 获取当前任务, 如果非RTOS, 传递 NULL + */ +void HDLogDebugSetGetTask(HDLogGetTaskType_t getTask); + +/** + * @brief 设置当前任务的栈大小 + * @param currTask 当前任务, 如果非RTOS, 传递 NULL + * @param size 栈大小 + */ +void HDLogDebugInitStackAddr(unsigned long currTask, uint32_t size); + +/** + * @brief 删除当前任务的栈大小记录 + * @param currTask 当前任务 + */ +void HDLogDebugDeleteStackAddr(unsigned long currTask); + +/** + * @brief 获取当前任务的栈大小 + * @return 当前栈使用大小 + */ +uint32_t HDLogDebugGetCurrStackSize(); + +typedef uint32_t(*HDLogGetStackSizeType_t)(unsigned long currTask); +/** + * @brief 设置获取当前任务的栈大小方法 + * @param getStackSize 获取当前任务的栈大小 + */ +void HDLogSetGetCurrStackSizeCall(HDLogGetStackSizeType_t getStackSize); + +#endif // __HD_NEW_LOG_H__ diff --git a/src/HDLog.c b/src/HDLog.c new file mode 100644 index 0000000..e162107 --- /dev/null +++ b/src/HDLog.c @@ -0,0 +1,349 @@ + + +#include "HDLog.h" +#include "HBit.h" +#include "HShellLex.h" +#include +#include +#include +#include +#include + +typedef struct HDLogStackCheckInfo +{ + uint32_t enable : 1; ///< 是否使用 + uint32_t stackSize : 31; ///< 栈大小 + unsigned long stackAddr; ///< 栈开始地址, 可能误差多字节 + unsigned long taskID; ///< 任务ID +} HDLogStackCheckInfo; + +static HShellMatch sLogMatch[] = { + HSHELL_MATCH_ITEM(kLogLevelSwitch, "log"), + HSHELL_MATCH_ITEM(kLogLevelColor, "logColor"), + HSHELL_MATCH_ITEM(kLogLevelDebug, "logDebug"), + HSHELL_MATCH_ITEM(kLogLevelError, "logError"), + HSHELL_MATCH_ITEM(kLogLevelHex, "logHex"), + HSHELL_MATCH_ITEM(kLogLevelStack, "logStack"), +}; + +static HBIT_DEFINE(sLogItem, kLogLevelMax); +static uint32_t (*sGetTime)() = NULL; +static HDLogGetTaskType_t sGetCurrTask = NULL; +static HDLogGetStackSizeType_t sGetCurrStackSize = NULL; +static HDLogStackCheckInfo sStackCheckInfo[USE_CHECK_STACK_NUM]; + + +static void LogShell(HSHELL_FUNC_ARGS) +{ + uint32_t arg1 = 0; + // 可以不用检查参数, 如果未输入就默认关闭 + HSHellToUint32(tokens, tokensLen, 1, &arg1); + uint8_t lastStatus = HBitGet(sLogItem, key); + HBitSet(sLogItem, key, arg1); + HSHELL_PRINTFL("logStatus[%d]->[%d]", lastStatus, HBitGet(sLogItem, key)); +} + +void HDLogInit(uint32_t (*getTime)()) +{ + sGetTime = getTime; + HSHellRegister(sLogMatch, sizeof(sLogMatch) / sizeof(HShellMatch), LogShell, 1); + HBitSet(sLogItem, kLogLevelSwitch, 1); + HBitSet(sLogItem, kLogLevelDebug, 1); + HBitSet(sLogItem, kLogLevelError, 1); + HBitSet(sLogItem, kLogLevelStack, 1); +} + +void HDLogOut(uint8_t ext, uint8_t level, const char *fileName, const char *funcName, int line, const char *format, ...) +{ + if (HBitGet(sLogItem, kLogLevelSwitch) == 0) + { + return; + } + + if (HBitGet(sLogItem, level) == 0) + { + return; + } + + { + const char *name = strrchr(fileName, '/'); + if (name) + { + fileName = name + 1; + } + } + + // 日志颜色 +#define _LOG_COLOR_RED "\033[1;31m" +#define _LOG_COLOR_GREEN "\033[1;32m" +#define _LOG_COLOR_YELLOW "\033[1;33m" +#define _LOG_COLOR_BLUE "\033[1;34m" +#define _LOG_COLOR_PURPLE "\033[1;35m" +#define _LOG_COLOR_CYAN "\033[1;36m" +#define _LOG_COLOR_END "\033[0m" + + // 日志前缀基础信息, 文件名, 函数名, 行号 +#define _LOG_BASE_ARGS _BASENAME(__FILE__), __func__, __LINE__ +#define _LOG_BASE_INFO "[%s:%s:%d]" +#define _LOG_BASE_INFO_COLOR "[" _LOG_COLOR_BLUE \ + "%s:%s:" _LOG_COLOR_PURPLE \ + "%d" _LOG_COLOR_END \ + "]" + + uint8_t color = HBitGet(sLogItem, kLogLevelColor); + if (ext == 0) + { + if (sGetTime) + { + uint32_t ms = sGetTime(); + printf("[%d:%02d:%02d.%03d]", ms / 1000 / 60 / 60, ms / 1000 / 60 % 60, ms / 1000 % 60, ms % 1000); + } + + if (color) + { + printf(_LOG_BASE_INFO_COLOR, fileName, funcName, line); + printf(_LOG_COLOR_CYAN); + } + else + { + printf(_LOG_BASE_INFO, fileName, funcName, line); + } + } + else + { + if (color) + { + printf(_LOG_COLOR_CYAN); + } + } + + if (HBitGet(sLogItem, kLogLevelStack)) + { + printf("[0x%04X]", HDLogDebugGetCurrStackSize()); + } + + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + + if (color) + { + printf(_LOG_COLOR_END); + } + + if (ext == 0) + { + printf("\r\n"); + } +} + +uint8_t HDLogPrintFpgaHeader(const uint8_t *data, int len, uint8_t isWrite) +{ + if (HBitGet(sLogItem, kLogLevelHex) == 0) + { + return 0; + } + + if (len <= 21) + { + return 0; + } + + for (uint8_t i = 0; i < 7; ++i) + { + if (0x55 != data[i]) + { + return 0; + } + } + + if (0xd5 != data[7]) + { + return 0; + } + + uint8_t type = data[8]; + uint8_t phy = (data[9] >> 3) & 0x1F; + uint8_t port = data[9]; + uint8_t recvCardNumber = data[10]; + uint16_t subFunc = (uint16_t)((data[11] << 8) | data[12]); + uint16_t group = (uint16_t)((data[13] << 8) | data[14]); + uint16_t effectLen = (uint16_t)((data[15] << 8) | data[16]); + if (effectLen < 16) + { + return 0; + } + + if (len < 21 + effectLen) + { + return 0; + } + + const char *opt = isWrite ? "write" : "read"; + printf("%s - type[%02X], phy[%d], port[%d], cardNumber[%d], subFunc[%04X], group[%04X], effectLen[%d]\r\n", opt, type, phy, port, recvCardNumber, subFunc, group, effectLen); + + return 1; +} + +void HDLogHex(const uint8_t *data, int len, uint8_t checkPrint, uint32_t *offset) +{ + if (checkPrint && HBitGet(sLogItem, kLogLevelHex) == 0) + { + return; + } + + if (len <= 0) + { + return; + } + +#define PRINT_HEX(...) printf(__VA_ARGS__); + + if (offset == NULL || *offset == 0) + { + PRINT_HEX(" "); + // 16进制打印, 打印15个换行, 开头打印0A-0F 开头样式, 数据列每行00-FF + for (int i = 0; i < 16; ++i) + { + PRINT_HEX("0%X ", i); + } + + PRINT_HEX("\r\n"); + for (int i = 0; i < 17; ++i) + { + PRINT_HEX("---"); + ; + } + + PRINT_HEX("\r\n"); + } + + int index = offset ? *offset : 0; + for (int i = 0; i < len; ++i, ++index) + { + if (index % 16 == 0) + { + PRINT_HEX("%X%X| ", index / 256, index / 16 % 16); + } + + PRINT_HEX("%02X ", data[i]); + if (index % 16 == 15) + { + PRINT_HEX("\r\n"); + } + } + + if (offset) + { + *offset = index; + } + else + { + PRINT_HEX("\r\n"); + } +#undef PRINT_HEX +} + +void HDLogData(const uint8_t *data, int len, uint8_t checkPrint) +{ + if (checkPrint && HBitGet(sLogItem, kLogLevelHex) == 0) + { + return; + } + + for (int i = 0; i < len; ++i) + { + printf("%02X ", data[i]); + if (i % 16 == 15) + { + printf("\r\n"); + } + } +} + +static int16_t HDLogGetIndex(unsigned long id) +{ + unsigned taskId = id; + if (taskId == 0 && sGetCurrTask) + { + taskId = sGetCurrTask(); + } + + int16_t index = -1; + for (int16_t i = 0; i < USE_CHECK_STACK_NUM; ++i) + { + if (index == -1 && sStackCheckInfo[i].enable) + { + index = i; + } + + if (sStackCheckInfo[i].enable && sStackCheckInfo[i].taskID == taskId) + { + return i; + } + } + + return index; +} + +void HDLogDebugSetGetTask(HDLogGetTaskType_t getTask) +{ + sGetCurrTask = getTask; +} + +void HDLogDebugInitStackAddr(unsigned long currTask, uint32_t size) +{ + void *start = 0; + for (int i = 0; i < USE_CHECK_STACK_NUM; ++i) + { + if (sStackCheckInfo[i].enable) + { + continue; + } + + sStackCheckInfo[i].enable = 1; + sStackCheckInfo[i].stackAddr = (unsigned long)&start - sizeof(void *); + sStackCheckInfo[i].stackSize = size; + sStackCheckInfo[i].taskID = currTask; + break; + } +} + +void HDLogDebugDeleteStackAddr(unsigned long currTask) +{ + int16_t index = HDLogGetIndex(currTask); + if (index != -1) + { + memset(&sStackCheckInfo[index], 0, sizeof(HDLogStackCheckInfo)); + } +} + + +uint32_t HDLogDebugGetCurrStackSize() +{ + void *curr = NULL; + int16_t index = HDLogGetIndex(NULL); + if (index == -1) + { + return 0; + } + + uint32_t currSize = abs(sStackCheckInfo[index].stackAddr - (unsigned long)&curr); + if (sGetCurrStackSize) + { + currSize = sGetCurrStackSize(sStackCheckInfo[index].taskID); + } + + if (sStackCheckInfo[index].stackSize < currSize + 0x100) + { + printf("The current stack[%d] is insufficient, size[%d], taskId[%lx]\r\n", currSize, sStackCheckInfo[index].stackSize, sStackCheckInfo[index].taskID); + } + + return currSize; +} + +void HDLogSetGetCurrStackSizeCall(HDLogGetStackSizeType_t getStackSize) +{ + sGetCurrStackSize = getStackSize; +}