我正在开发嵌入式系统,我使用 printf 在 UART 上创建日志。
我想创建一个调试源文件,我可以在其中设置所需的调试类型。
我定义了这个常量:
- DEBUG_LOG_0 用于系统日志
- DEBUG_LOG_1 用于系统调试
- DEBUG_LOG_2 用于系统高级调试
从这个常量开始,我定义了这个宏来包装标准 printf:
/* Define for debugging level 0 - System Logs */
#ifdef DEBUG_LEVEL_0
#define edi_Print_L0(...) printf(__VA_ARGS__)
#endif
#ifndef DEBUG_LEVEL_0
#define edi_Print_L0(...) printf(...)
#endif
/* Define for debugging level 1 - Debug */
#ifdef DEBUG_LEVEL_1
#define edi_Print_L0(...) printf(__VA_ARGS__)
#define edi_Print_L1(...) printf(__VA_ARGS__)
#endif
#ifndef DEBUG_LEVEL_1
#define edi_Print_L0(...) printf(...)
#define edi_Print_L1(...) printf(...)
#endif
/* Define for debugging level 2 - Advanced Debug */
#ifdef DEBUG_LEVEL_2
#define edi_Print_L0(...) printf(__VA_ARGS__)
#define edi_Print_L1(...) printf(__VA_ARGS__)
#define edi_Print_L2(...) printf(__VA_ARGS__)
#endif
#ifndef DEBUG_LEVEL_2
#define edi_Print_L0(...) printf(...)
#define edi_Print_L1(...) printf(...)
#define edi_Print_L2(...) printf(...)
#endif
接下来,我将从头文件导入调试常量,以启用选定的调试级别。
关于宏定义有什么建议吗?有没有一种聪明的方法来实现我的目标?
谢谢!
最佳答案
在整个代码中传递日志级别/源,然后简单地在一个位置禁用/启用各个级别或源会更有意义。
即在您的代码中,您将使用:
Log(Log_Comm, LevelDebug, "Some minor stuff");
Log(Log_Comm, LevelWarn, "Something strange");
Log(Log_Comm, LevelError, "Something seriously wrong");
Log(Log_System, LevelDebug, "Some minor stuff");
Log(Log_System, LevelWarn, "Something strange");
Log(Log_System, LevelError, "Something seriously wrong");
然后你只需:
// log levels
#define LevelDebug 0x01
#define LevelInfo 0x02
#define LevelWarn 0x04
#define LevelError 0x08
#define LevelAll 0x0F
// enabled levels for individual log sources
#define Log_Comm (LevelWarn | LevelError)
#define Log_System (LevelAll)
#define Log(source, level, message) do { \
if (source & level) { \
sendToPort(message); \
} \
} while (0)
(编辑)
正如 @Clifford 在评论中指出的,可能还需要全局禁用某个级别,而不必遍历所有源定义。这可以通过指定附加掩码来完成:
// if LevelDebug is omitted from this mask,
// debug message will not be logged regardless
// of individual source settings
#define Global_Level_Mask (LevelWarn | LevelError)
#define Log(source, level, message) do { \
if (source & level & Global_Level_Mask) { \
sendToPort(message); \
} \
} while (0)
另一个问题可能是这将在您的代码周围产生许多“无法访问的代码”警告。我不确定如何在其他编译器中修复此问题,但是,例如在 Visual Studio 中,可以通过在 if
语句周围添加编译指示来解决此问题:
// visual studio will show a warning
// C4127: "conditional expression is constant"
// when compiling with all warnings enabled (-w4)
// these pragmas will disable the warning around if's
#define Log(source, level, message) do { \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
if (source & level & Global_Level_Mask) { \
__pragma(warning(pop)) \
sendToPort(message); \
} \
} while (0)
并不是它看起来有点难看,但恕我直言,它允许轻松使用和更多控制。
当然,没有什么可以阻止您为每个日志级别使用单独的宏(也许更简单,因为您少了一个参数),即:
#define LogDebug(source, message) Log(source, LevelDebug, message)
#define LogInfo(source, message) Log(source, LevelInfo, message)
#define LogWarn(source, message) Log(source, LevelWarn, message)
// usage example:
LogDebug(Log_Comm, "Some minor stuff");
LogWarn(Log_System, "Something strange");
关于c - 在嵌入式 C 中使用 printf 进行多级调试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37837904/