/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2016-11-12 Bernard The first version * 2018-05-25 armink Add simple API, such as LOG_D, LOG_E * 2024-01-28 RTC_Update Add RTC timestamp support */ /* * The macro definitions for debug * * These macros are defined in static. If you want to use debug macro, you can * use as following code: * * In your C/C++ file, enable/disable DEBUG_ENABLE macro, and then include this * header file. * * #define DBG_TAG "MOD_TAG" * #define DBG_LVL DBG_INFO * #include // must after of DBG_LVL, DBG_TAG or other options * * Then in your C/C++ file, you can use LOG_X macro to print out logs: * LOG_D("this is a debug log!"); * LOG_E("this is a error log!"); */ #ifndef RT_DBG_H__ #define RT_DBG_H__ #include #ifdef __cplusplus extern "C" { #endif /* the debug log will force enable when RT_DEBUG macro is defined */ #if defined(RT_DEBUG) && !defined(DBG_ENABLE) #define DBG_ENABLE #endif /* it will force output color log when RT_DEBUG_COLOR macro is defined */ #if defined(RT_DEBUG_COLOR) && !defined(DBG_COLOR) #define DBG_COLOR #endif /* RTC timestamp support - define RT_DBG_WITH_RTC to enable RTC timestamp */ #ifndef RT_DBG_WITH_RTC #define RT_DBG_WITH_RTC 1 /* default enable RTC timestamp */ #endif #if defined(RT_USING_ULOG) /* using ulog compatible with rtdbg */ #include #else /* DEBUG level */ #define DBG_ERROR 0 #define DBG_WARNING 1 #define DBG_INFO 2 #define DBG_LOG 3 #ifdef DBG_TAG #ifndef DBG_SECTION_NAME #define DBG_SECTION_NAME DBG_TAG #endif #else /* compatible with old version */ #ifndef DBG_SECTION_NAME #define DBG_SECTION_NAME "DBG" #endif #endif /* DBG_TAG */ #ifdef DBG_ENABLE #ifdef DBG_LVL #ifndef DBG_LEVEL #define DBG_LEVEL DBG_LVL #endif #else /* compatible with old version */ #ifndef DBG_LEVEL #define DBG_LEVEL DBG_WARNING #endif #endif /* DBG_LVL */ /* * The color for terminal (foreground) * BLACK 30 * RED 31 * GREEN 32 * YELLOW 33 * BLUE 34 * PURPLE 35 * CYAN 36 * WHITE 37 */ #ifdef DBG_COLOR #define _DBG_COLOR(n) rt_kprintf("\033["#n"m") #define _DBG_LOG_HDR(lvl_name, color_n) \ rt_kprintf("\033["#color_n"m[" lvl_name "/" DBG_SECTION_NAME "] ") #define _DBG_LOG_X_END \ rt_kprintf("\033[0m\n") #else #define _DBG_COLOR(n) #define _DBG_LOG_HDR(lvl_name, color_n) \ rt_kprintf("[" lvl_name "/" DBG_SECTION_NAME "] ") #define _DBG_LOG_X_END \ rt_kprintf("\n") #endif /* DBG_COLOR */ /* * RTC Timestamp support */ #if RT_DBG_WITH_RTC /* Include your RTC header */ #include "../../applications/peri/rtc/rtc.h" /* Make sure this path is correct */ /* Function to get RTC timestamp string - 带有效性检查 */ static inline const char *_dbg_get_rtc_timestamp(void) { static char rtc_time_buf[24]; static rt_tick_t last_update = 0; static uint8_t first_call = 1; /* 声明外部全局变量 */ extern struct rtc_time time_now; /* 第一次调用时检查变量是否已定义 */ if (first_call) { first_call = 0; /* 如果系统太早启动,使用tick回退 */ if (rt_thread_self() == RT_NULL) { static char tick_buf[16]; rt_tick_t tick = rt_tick_get(); rt_snprintf(tick_buf, sizeof(tick_buf), "BOOT:%08d", tick); return tick_buf; } } /* 获取当前tick,每秒更新一次 */ rt_tick_t current_tick = rt_tick_get(); if (current_tick - last_update > 1000 || last_update == 0) { /* 检查日期有效性(年份00-99,月份01-12,日期01-31) */ uint8_t month = time_now.month; uint8_t day = time_now.date; uint8_t hour = time_now.hour; uint8_t minute = time_now.minute; uint8_t second = time_now.second; /* 验证时间有效性 */ if (month >= 1 && month <= 12 && day >= 1 && day <= 31 && hour <= 23 && minute <= 59 && second <= 59) { /* 有效的RTC时间 */ rt_snprintf(rtc_time_buf, sizeof(rtc_time_buf), "%02d-%02d %02d:%02d:%02d", month, day, hour, minute, second); } last_update = current_tick; } return rtc_time_buf; } /* RTC timestamp header macro - 格式: [LEVEL/TAG] [YYYY-MM-DD HH:MM:SS] */ #ifdef DBG_COLOR #define _DBG_LOG_HDR_WITH_TIME(lvl_name, color_n) \ do { \ rt_kprintf("\033["#color_n"m"); \ rt_kprintf("[" lvl_name "/" DBG_SECTION_NAME "] ");\ rt_kprintf("[%s]", _dbg_get_rtc_timestamp()); \ } while(0) #else #define _DBG_LOG_HDR_WITH_TIME(lvl_name, color_n) \ do { \ rt_kprintf("[" lvl_name "/" DBG_SECTION_NAME "] ");\ rt_kprintf("[%s]", _dbg_get_rtc_timestamp()); \ } while(0) #endif /* Use RTC timestamp header */ #define _DBG_LOG_HDR_RTC _DBG_LOG_HDR_WITH_TIME #else /* Without RTC timestamp */ #define _DBG_LOG_HDR_RTC _DBG_LOG_HDR #endif /* RT_DBG_WITH_RTC */ /* * static debug routine * NOTE: This is a NOT RECOMMENDED API. Please using LOG_X API. * It will be DISCARDED later. Because it will take up more resources. */ #define dbg_log(level, fmt, ...) \ if ((level) <= DBG_LEVEL) \ { \ switch(level) \ { \ case DBG_ERROR: _DBG_LOG_HDR_RTC("E", 31); break; \ case DBG_WARNING: _DBG_LOG_HDR_RTC("W", 33); break; \ case DBG_INFO: _DBG_LOG_HDR_RTC("I", 32); break; \ case DBG_LOG: _DBG_LOG_HDR_RTC("D", 0); break; \ default: break; \ } \ rt_kprintf(fmt, ##__VA_ARGS__); \ _DBG_COLOR(0); \ } #define dbg_here \ if ((DBG_LEVEL) <= DBG_LOG){ \ _DBG_LOG_HDR_RTC("D", 0); \ rt_kprintf("Here %s:%d\n", \ __FUNCTION__, __LINE__); \ } #define dbg_log_line(lvl, color_n, fmt, ...) \ do \ { \ _DBG_LOG_HDR_RTC(lvl, color_n); \ rt_kprintf(fmt, ##__VA_ARGS__); \ _DBG_LOG_X_END; \ } \ while (0) #define dbg_raw(...) rt_kprintf(__VA_ARGS__); #else #define dbg_log(level, fmt, ...) #define dbg_here #define dbg_enter #define dbg_exit #define dbg_log_line(lvl, color_n, fmt, ...) #define dbg_raw(...) #endif /* DBG_ENABLE */ /* * Main LOG macros with RTC timestamp * Format: [LEVEL/TAG] [YYYY-MM-DD HH:MM:SS] message */ #if (DBG_LEVEL >= DBG_LOG) #define LOG_D(fmt, ...) dbg_log_line("D", 0, fmt, ##__VA_ARGS__) #else #define LOG_D(...) #endif #if (DBG_LEVEL >= DBG_INFO) #define LOG_I(fmt, ...) dbg_log_line("I", 32, fmt, ##__VA_ARGS__) #else #define LOG_I(...) #endif #if (DBG_LEVEL >= DBG_WARNING) #define LOG_W(fmt, ...) dbg_log_line("W", 33, fmt, ##__VA_ARGS__) #else #define LOG_W(...) #endif #if (DBG_LEVEL >= DBG_ERROR) #define LOG_E(fmt, ...) dbg_log_line("E", 31, fmt, ##__VA_ARGS__) #else #define LOG_E(...) #endif #define LOG_RAW(...) dbg_raw(__VA_ARGS__) /* * Additional macros with explicit timestamp control */ #if RT_DBG_WITH_RTC /* LOG with custom timestamp */ #define LOG_T(level_char, color_n, fmt, ...) \ do { \ _DBG_LOG_HDR_RTC(level_char, color_n); \ rt_kprintf(fmt, ##__VA_ARGS__); \ _DBG_LOG_X_END; \ } while(0) /* LOG without timestamp (original format) */ #define LOG_NT(level_char, color_n, fmt, ...) \ do { \ _DBG_LOG_HDR(level_char, color_n); \ rt_kprintf(fmt, ##__VA_ARGS__); \ _DBG_LOG_X_END; \ } while(0) #endif #endif /* defined(RT_USING_ULOG) && define(DBG_ENABLE) */ #ifdef __cplusplus } #endif #endif /* RT_DBG_H__ */