Files
STM32F4-Base/Drivers/BSP/dbg_log.h
T

172 lines
5.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:Unified Debug Logging
* 模块功能:提供统一的调试输出宏,支持 DEBUG / INFO / ERROR 三级日志控制
* 参考 FlashDB FDB_DEBUG/FDB_INFO 设计模式
* 使用方法:
* 1. 在 dbg_cfg.h 中定义 DBG_ENABLE(总开关)和 DBG_DEBUG_ENABLE(DEBUG 级别)
* 2. 每个 .c 文件在包含本文件前定义 DBG_TAG,如:
* #define DBG_TAG "[CH395]"
* #include "dbg_log.h"
* 适用平台:所有 BSP 驱动
* 作者:王建锋
* 创建日期:2026-07-18
* 修改记录:
* 2026-07-18 王建锋 创建初始版本
*/
#ifndef DBG_LOG_H
#define DBG_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include "dbg_cfg.h"
#ifdef APP_TIMESTAMP_ENABLE
#include "sys_clock.h"
#endif
/*
* 单写者控制台 API(实现见 Src/usart.c;与 DBG_ENABLE 无关,任何构建都必须可见):
* dbg_console_write_line - 生产者入口:调用方已格式化好的整行文本一次入环形缓冲
* (刻意**不用**自研可变参数函数——规范 S12 7.6 禁止;格式化在
* DBG_PRINT 宏内用库 snprintf 完成)
* dbg_console_write_raw - 异常/早期路径:有界单次直发(不加锁)
* dbg_console_writer_attach- 写者任务(defaultTask)注册自己为唯一发送者
* dbg_console_drain - 写者任务排空缓冲并发送
* dbg_console_dropped - 因缓冲满丢弃的行数(诊断)
*/
#define DBG_CON_LINE_MAX 192U /* 单行文本上限(与 Src/usart.c 内部口径一致) */
int dbg_console_write_line(const char *line, unsigned len);
void dbg_console_write_raw(const char *buf, unsigned len);
void dbg_console_writer_attach(void);
void dbg_console_drain(void);
uint32_t dbg_console_dropped(void);
/*
* 总开关:DBG_ENABLE
* 定义 → 输出 DBG_ERROR / DBG_INFO;若 DBG_DEBUG_ENABLE 也定义则输出 DBG_DEBUG
* 不定义 → 所有输出宏为空操作(release 版本)
* 在 net_config.h 或编译器预定义中控制
*/
#ifdef DBG_ENABLE
/*
* 可重定向的打印函数,用户可在编译选项或 net_config.h 中预定义
* #define DBG_PRINT(...) my_printf(__VA_ARGS__)
*
* 默认走单写者控制台(Src/usart.c):
* DBG_PRINT 在调用点用库 snprintf 有界格式化整行,再一次性交给 dbg_console_write_line
* 入环形缓冲,由 defaultTask 唯一发送——
* ① 行与行不会字符级交错(旧 printf→fputc 每字符一次 HAL_UART_Transmit 会交错);
* ② 进 UART 的缓冲恒为控制台内部缓冲,调用方脏指针到不了 UART
* (2026-09-24 HardFault:BFAR=CCM 末尾+1 即在 UART 缓冲读取处)。
*/
#ifndef DBG_PRINT
#define DBG_PRINT(...) do { \
char __con_line[DBG_CON_LINE_MAX]; \
int __con_n = snprintf(__con_line, sizeof(__con_line), __VA_ARGS__); \
if (__con_n > 0) { \
unsigned __con_len = (__con_n >= (int)sizeof(__con_line)) \
? (unsigned)(sizeof(__con_line) - 1u) : (unsigned)__con_n; \
(void)dbg_console_write_line(__con_line, __con_len); \
} \
} while (0)
#endif
/*
* 模块标签默认值,每个 .c 文件应在包含本文件前定义 DBG_TAG
* #define DBG_TAG "[CH395]"
*/
#ifndef DBG_TAG
#define DBG_TAG ""
#endif
#ifdef APP_TIMESTAMP_ENABLE
/*
* 时间戳输出宏 — 在日志行首追加 [YYYY-MM-DD HH:MM:SS] 格式的系统墙钟时间
* sys_clock_get_str() 线程安全(内部使用 DWT US 计数,无锁)
*/
#define DBG_TS() sys_clock_get_str((char[32]){0}, 32)
/*
* DBG_ERROR - 错误输出,受 DBG_ENABLE + APP_TIMESTAMP_ENABLE 控制
*/
#define DBG_ERROR(fmt, ...) do { \
char __ts_buf[32]; \
(void)__ts_buf; \
DBG_PRINT("[%s]" "[ERR]" DBG_TAG " " fmt "\r\n", \
sys_clock_get_str(__ts_buf, sizeof(__ts_buf)), ##__VA_ARGS__); \
} while (0)
/*
* DBG_INFO - 信息输出,受 DBG_ENABLE + APP_TIMESTAMP_ENABLE 控制
*/
#define DBG_INFO(fmt, ...) do { \
char __ts_buf[32]; \
(void)__ts_buf; \
DBG_PRINT("[%s]" DBG_TAG " " fmt "\r\n", \
sys_clock_get_str(__ts_buf, sizeof(__ts_buf)), ##__VA_ARGS__); \
} while (0)
/*
* DBG_DEBUG - 调试输出,需 DBG_ENABLE + DBG_DEBUG_ENABLE + APP_TIMESTAMP_ENABLE 同时定义
*/
#ifdef DBG_DEBUG_ENABLE
#define DBG_DEBUG(fmt, ...) do { \
char __ts_buf[32]; \
(void)__ts_buf; \
DBG_PRINT("[%s]" DBG_TAG "(%s:%d) " fmt "\r\n", \
sys_clock_get_str(__ts_buf, sizeof(__ts_buf)), __func__, __LINE__, ##__VA_ARGS__); \
} while (0)
#else
#define DBG_DEBUG(fmt, ...)
#endif
#else /* APP_TIMESTAMP_ENABLE not defined */
/*
* DBG_ERROR - 错误输出,受 DBG_ENABLE 控制(无时间戳)
*/
#define DBG_ERROR(fmt, ...) do { \
DBG_PRINT("[ERR]" DBG_TAG " " fmt "\r\n", ##__VA_ARGS__); \
} while (0)
/*
* DBG_INFO - 信息输出,受 DBG_ENABLE 控制(无时间戳)
*/
#define DBG_INFO(fmt, ...) do { \
DBG_PRINT(DBG_TAG " " fmt "\r\n", ##__VA_ARGS__); \
} while (0)
/*
* DBG_DEBUG - 调试输出,需 DBG_ENABLE + DBG_DEBUG_ENABLE 同时定义(无时间戳)
*/
#ifdef DBG_DEBUG_ENABLE
#define DBG_DEBUG(fmt, ...) do { \
DBG_PRINT(DBG_TAG "(%s:%d) " fmt "\r\n", __func__, __LINE__, ##__VA_ARGS__); \
} while (0)
#else
#define DBG_DEBUG(fmt, ...)
#endif
#endif /* APP_TIMESTAMP_ENABLE */
#else /* DBG_ENABLE not defined — all debug output disabled */
#define DBG_ERROR(fmt, ...)
#define DBG_INFO(fmt, ...)
#define DBG_DEBUG(fmt, ...)
#endif /* DBG_ENABLE */
#ifdef __cplusplus
}
#endif
#endif /* DBG_LOG_H */