嵌入式 DEBUG 方法
嵌入式开发中,调试手段相对有限,因此通过合适的代码结构和日志系统,可以帮助开发者快速定位问题。以下介绍两种常用的 DEBUG 方法:断言机制 和 彩色日志系统。
一、断言机制(Assertion)
断言是一种调试时用于验证程序运行时状态的工具。当条件不满时,程序会打印错信息并停在错误位置,便于开发者定位问题。
示例代码:
#include <stdio.h>
#ifndef assert_printf
#error need define assert_printf
#else
#ifndef NDEBUG
#if __STDC_VERSION__ < 199901L && !defined(__func__)
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
#endif
#define vassert(condition, format, ...) do { \
if(!(condition)) { \
assert_printf("WARNING: %s:%d: %s:" \
" Assertion \"%s\" failed.\r\n", \
__FILE__, __LINE__, __func__, #condition); \
while(1){}; \
} else { \
assert_printf(format, ##__VA_ARGS__); \
} \
} while(0)
#else
#define vassert(condition, format, ...) do {} while(0)
#endif
#endif
使用说明:
- 使用
vassert(cond, fmt, ...)代替传统assert。 - 如果
cond不满足,会输出断言失败信息(包括文件名、函数名、行号和条件)。 - 如枟满足条件,可选择输出调试信息。
- 需用在项目中定义
assert_printf实现,如使用printf。
二、彩色日志系统(带级别)
彩色日志系统通过串口输出不同级别、不同颜色的日志信息,便于区分信息、警告、错误等内容。
示例代码:
#include <stdio.h>
#define DBG_UART printf
#ifdef CONFIG_DEBUG
extern int log_num;
#ifdef CONFIG_DEBUG_COLOR_MODE
#define COLOR_SET(dis_mode, fwd_color, bak_color) DBG_UART("\033[%d;%d;%dm", dis_mode, fwd_color, bak_color)
#else
#define COLOR_SET(dis_mode, fwd_color, bak_color) (NULL)
#endif
#define DBG_LOG(x, y, z, str, ...) \
{ \
COLOR_SET(x, y, z); \
DBG_UART(str, ##__VA_ARGS__); \
COLOR_SET(0, 0, 0); \
}
/*
* I:INFO W:WARN E:ERR F:FLAG
* log_num: 每条日志的编号
* DBG_NAME: 当前模块名(需要在使用前定义)
*/
#if CONFIG_DEBUG_LEVEL >= 0x01
#define DBG_E(str, ...) \
{ \
COLOR_SET(31, 31, 1); \
DBG_UART("[%05d] E/%-4s: ", log_num++, DBG_NAME); \
DBG_UART(str, ##__VA_ARGS__); \
COLOR_SET(0, 0, 0); \
}
#else
#define DBG_E(str, ...) while(0)
#endif
#if CONFIG_DEBUG_LEVEL >= 0x02
#define DBG_W(str, ...) \
{ \
COLOR_SET(33, 33, 1); \
DBG_UART("[%05d] W/%-4s: ", log_num++, DBG_NAME); \
DBG_UART(str, ##__VA_ARGS__); \
COLOR_SET(0, 0, 0); \
}
#else
#define DBG_W(str, ...) while(0)
#endif
#if CONFIG_DEBUG_LEVEL >= 0x03
#define DBG_F(str, ...) \
{ \
COLOR_SET(36, 36, 1); \
DBG_UART("[%05d] F/%-4s: ", log_num++, DBG_NAME); \
DBG_UART(str, ##__VA_ARGS__); \
COLOR_SET(0, 0, 0); \
}
#else
#define DBG_F(str, ...) while(0)
#endif
#if CONFIG_DEBUG_LEVEL >= 0x04
#define DBG_I(str, ...) \
{ \
DBG_UART("[%05d] I/%-4s: ", log_num++, DBG_NAME); \
DBG_UART(str, ##__VA_ARGS__); \
}
#else
#define DBG_I(str, ...) while(0)
#endif
#else
#define DBG_I(str, ...) while(0)
#define DBG_W(str, ...) while(0)
#define DBG_E(str, ...) while(0)
#define DBG_F(str, ...) while(0)
#endif
使用说明:
- 在不同模块中定义
DBG_NAME作为模块标识。 - 日志级别由
CONFIG_DEBUG_LEVEL控制(例如:0x01 只输出错误,0x04 全部输出)。 CONFIG_DEBUG_COLOR_MODE控制是否启用彩色输出(需终端支持 ANSI 转义)。- 常用颜色:
- 红色:错误 (E)
- 黄色:警告 (W)
- 青色:标志 (F)
- 默认颜色:信息 (I)