rtdbg.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2016-11-12 Bernard The first version
  9. * 2018-05-25 armink Add simple API, such as LOG_D, LOG_E
  10. * 2024-01-28 RTC_Update Add RTC timestamp support
  11. */
  12. /*
  13. * The macro definitions for debug
  14. *
  15. * These macros are defined in static. If you want to use debug macro, you can
  16. * use as following code:
  17. *
  18. * In your C/C++ file, enable/disable DEBUG_ENABLE macro, and then include this
  19. * header file.
  20. *
  21. * #define DBG_TAG "MOD_TAG"
  22. * #define DBG_LVL DBG_INFO
  23. * #include <rtdbg.h> // must after of DBG_LVL, DBG_TAG or other options
  24. *
  25. * Then in your C/C++ file, you can use LOG_X macro to print out logs:
  26. * LOG_D("this is a debug log!");
  27. * LOG_E("this is a error log!");
  28. */
  29. #ifndef RT_DBG_H__
  30. #define RT_DBG_H__
  31. #include <rtconfig.h>
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35. /* the debug log will force enable when RT_DEBUG macro is defined */
  36. #if defined(RT_DEBUG) && !defined(DBG_ENABLE)
  37. #define DBG_ENABLE
  38. #endif
  39. /* it will force output color log when RT_DEBUG_COLOR macro is defined */
  40. #if defined(RT_DEBUG_COLOR) && !defined(DBG_COLOR)
  41. #define DBG_COLOR
  42. #endif
  43. /* RTC timestamp support - define RT_DBG_WITH_RTC to enable RTC timestamp */
  44. #ifndef RT_DBG_WITH_RTC
  45. #define RT_DBG_WITH_RTC 1 /* default enable RTC timestamp */
  46. #endif
  47. #if defined(RT_USING_ULOG)
  48. /* using ulog compatible with rtdbg */
  49. #include <ulog.h>
  50. #else
  51. /* DEBUG level */
  52. #define DBG_ERROR 0
  53. #define DBG_WARNING 1
  54. #define DBG_INFO 2
  55. #define DBG_LOG 3
  56. #ifdef DBG_TAG
  57. #ifndef DBG_SECTION_NAME
  58. #define DBG_SECTION_NAME DBG_TAG
  59. #endif
  60. #else
  61. /* compatible with old version */
  62. #ifndef DBG_SECTION_NAME
  63. #define DBG_SECTION_NAME "DBG"
  64. #endif
  65. #endif /* DBG_TAG */
  66. #ifdef DBG_ENABLE
  67. #ifdef DBG_LVL
  68. #ifndef DBG_LEVEL
  69. #define DBG_LEVEL DBG_LVL
  70. #endif
  71. #else
  72. /* compatible with old version */
  73. #ifndef DBG_LEVEL
  74. #define DBG_LEVEL DBG_WARNING
  75. #endif
  76. #endif /* DBG_LVL */
  77. /*
  78. * The color for terminal (foreground)
  79. * BLACK 30
  80. * RED 31
  81. * GREEN 32
  82. * YELLOW 33
  83. * BLUE 34
  84. * PURPLE 35
  85. * CYAN 36
  86. * WHITE 37
  87. */
  88. #ifdef DBG_COLOR
  89. #define _DBG_COLOR(n) rt_kprintf("\033["#n"m")
  90. #define _DBG_LOG_HDR(lvl_name, color_n) \
  91. rt_kprintf("\033["#color_n"m[" lvl_name "/" DBG_SECTION_NAME "] ")
  92. #define _DBG_LOG_X_END \
  93. rt_kprintf("\033[0m\n")
  94. #else
  95. #define _DBG_COLOR(n)
  96. #define _DBG_LOG_HDR(lvl_name, color_n) \
  97. rt_kprintf("[" lvl_name "/" DBG_SECTION_NAME "] ")
  98. #define _DBG_LOG_X_END \
  99. rt_kprintf("\n")
  100. #endif /* DBG_COLOR */
  101. /*
  102. * RTC Timestamp support
  103. */
  104. #if RT_DBG_WITH_RTC
  105. /* Include your RTC header */
  106. #include "../../applications/peri/rtc/rtc.h" /* Make sure this path is correct */
  107. /* Function to get RTC timestamp string - 带有效性检查 */
  108. static inline const char *_dbg_get_rtc_timestamp(void)
  109. {
  110. static char rtc_time_buf[24];
  111. static rt_tick_t last_update = 0;
  112. static uint8_t first_call = 1;
  113. /* 声明外部全局变量 */
  114. extern struct rtc_time time_now;
  115. /* 第一次调用时检查变量是否已定义 */
  116. if (first_call)
  117. {
  118. first_call = 0;
  119. /* 如果系统太早启动,使用tick回退 */
  120. if (rt_thread_self() == RT_NULL)
  121. {
  122. static char tick_buf[16];
  123. rt_tick_t tick = rt_tick_get();
  124. rt_snprintf(tick_buf, sizeof(tick_buf), "BOOT:%08d", tick);
  125. return tick_buf;
  126. }
  127. }
  128. /* 获取当前tick,每秒更新一次 */
  129. rt_tick_t current_tick = rt_tick_get();
  130. if (current_tick - last_update > 1000 || last_update == 0)
  131. {
  132. /* 检查日期有效性(年份00-99,月份01-12,日期01-31) */
  133. uint8_t month = time_now.month;
  134. uint8_t day = time_now.date;
  135. uint8_t hour = time_now.hour;
  136. uint8_t minute = time_now.minute;
  137. uint8_t second = time_now.second;
  138. /* 验证时间有效性 */
  139. if (month >= 1 && month <= 12 &&
  140. day >= 1 && day <= 31 && hour <= 23 &&
  141. minute <= 59 && second <= 59)
  142. {
  143. /* 有效的RTC时间 */
  144. rt_snprintf(rtc_time_buf, sizeof(rtc_time_buf),
  145. "%02d-%02d %02d:%02d:%02d",
  146. month, day, hour, minute, second);
  147. }
  148. last_update = current_tick;
  149. }
  150. return rtc_time_buf;
  151. }
  152. /* RTC timestamp header macro - 格式: [LEVEL/TAG] [YYYY-MM-DD HH:MM:SS] */
  153. #ifdef DBG_COLOR
  154. #define _DBG_LOG_HDR_WITH_TIME(lvl_name, color_n) \
  155. do { \
  156. rt_kprintf("\033["#color_n"m"); \
  157. rt_kprintf("[" lvl_name "/" DBG_SECTION_NAME "] ");\
  158. rt_kprintf("[%s]", _dbg_get_rtc_timestamp()); \
  159. } while(0)
  160. #else
  161. #define _DBG_LOG_HDR_WITH_TIME(lvl_name, color_n) \
  162. do { \
  163. rt_kprintf("[" lvl_name "/" DBG_SECTION_NAME "] ");\
  164. rt_kprintf("[%s]", _dbg_get_rtc_timestamp()); \
  165. } while(0)
  166. #endif
  167. /* Use RTC timestamp header */
  168. #define _DBG_LOG_HDR_RTC _DBG_LOG_HDR_WITH_TIME
  169. #else
  170. /* Without RTC timestamp */
  171. #define _DBG_LOG_HDR_RTC _DBG_LOG_HDR
  172. #endif /* RT_DBG_WITH_RTC */
  173. /*
  174. * static debug routine
  175. * NOTE: This is a NOT RECOMMENDED API. Please using LOG_X API.
  176. * It will be DISCARDED later. Because it will take up more resources.
  177. */
  178. #define dbg_log(level, fmt, ...) \
  179. if ((level) <= DBG_LEVEL) \
  180. { \
  181. switch(level) \
  182. { \
  183. case DBG_ERROR: _DBG_LOG_HDR_RTC("E", 31); break; \
  184. case DBG_WARNING: _DBG_LOG_HDR_RTC("W", 33); break; \
  185. case DBG_INFO: _DBG_LOG_HDR_RTC("I", 32); break; \
  186. case DBG_LOG: _DBG_LOG_HDR_RTC("D", 0); break; \
  187. default: break; \
  188. } \
  189. rt_kprintf(fmt, ##__VA_ARGS__); \
  190. _DBG_COLOR(0); \
  191. }
  192. #define dbg_here \
  193. if ((DBG_LEVEL) <= DBG_LOG){ \
  194. _DBG_LOG_HDR_RTC("D", 0); \
  195. rt_kprintf("Here %s:%d\n", \
  196. __FUNCTION__, __LINE__); \
  197. }
  198. #define dbg_log_line(lvl, color_n, fmt, ...) \
  199. do \
  200. { \
  201. _DBG_LOG_HDR_RTC(lvl, color_n); \
  202. rt_kprintf(fmt, ##__VA_ARGS__); \
  203. _DBG_LOG_X_END; \
  204. } \
  205. while (0)
  206. #define dbg_raw(...) rt_kprintf(__VA_ARGS__);
  207. #else
  208. #define dbg_log(level, fmt, ...)
  209. #define dbg_here
  210. #define dbg_enter
  211. #define dbg_exit
  212. #define dbg_log_line(lvl, color_n, fmt, ...)
  213. #define dbg_raw(...)
  214. #endif /* DBG_ENABLE */
  215. /*
  216. * Main LOG macros with RTC timestamp
  217. * Format: [LEVEL/TAG] [YYYY-MM-DD HH:MM:SS] message
  218. */
  219. #if (DBG_LEVEL >= DBG_LOG)
  220. #define LOG_D(fmt, ...) dbg_log_line("D", 0, fmt, ##__VA_ARGS__)
  221. #else
  222. #define LOG_D(...)
  223. #endif
  224. #if (DBG_LEVEL >= DBG_INFO)
  225. #define LOG_I(fmt, ...) dbg_log_line("I", 32, fmt, ##__VA_ARGS__)
  226. #else
  227. #define LOG_I(...)
  228. #endif
  229. #if (DBG_LEVEL >= DBG_WARNING)
  230. #define LOG_W(fmt, ...) dbg_log_line("W", 33, fmt, ##__VA_ARGS__)
  231. #else
  232. #define LOG_W(...)
  233. #endif
  234. #if (DBG_LEVEL >= DBG_ERROR)
  235. #define LOG_E(fmt, ...) dbg_log_line("E", 31, fmt, ##__VA_ARGS__)
  236. #else
  237. #define LOG_E(...)
  238. #endif
  239. #define LOG_RAW(...) dbg_raw(__VA_ARGS__)
  240. /*
  241. * Additional macros with explicit timestamp control
  242. */
  243. #if RT_DBG_WITH_RTC
  244. /* LOG with custom timestamp */
  245. #define LOG_T(level_char, color_n, fmt, ...) \
  246. do { \
  247. _DBG_LOG_HDR_RTC(level_char, color_n); \
  248. rt_kprintf(fmt, ##__VA_ARGS__); \
  249. _DBG_LOG_X_END; \
  250. } while(0)
  251. /* LOG without timestamp (original format) */
  252. #define LOG_NT(level_char, color_n, fmt, ...) \
  253. do { \
  254. _DBG_LOG_HDR(level_char, color_n); \
  255. rt_kprintf(fmt, ##__VA_ARGS__); \
  256. _DBG_LOG_X_END; \
  257. } while(0)
  258. #endif
  259. #endif /* defined(RT_USING_ULOG) && define(DBG_ENABLE) */
  260. #ifdef __cplusplus
  261. }
  262. #endif
  263. #endif /* RT_DBG_H__ */