| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- /*
- * 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 <rtdbg.h> // 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 <rtconfig.h>
- #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 <ulog.h>
- #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__ */
|