可变参数宏
问题起源
在阅读NRF52832的官方程序demo时,发现有个自定义的log文件,程序运行时log通过jlink输出至j-link viewr显示。

代码解析
查看NRF_LOG_DEBUG的定义,步步深入依次为多层宏定义,具体如下
//nrf_log.h
#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__)
//nrf_log_internal.h
#define NRF_LOG_INTERNAL_DEBUG(...) \
NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, __VA_ARGS__)
#define NRF_LOG_INTERNAL_MODULE(level, level_id, ...) \
if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
(level <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
if (NRF_LOG_FILTER >= level) \
{ \
LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); \
} \
}
#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \
__VA_ARGS__), type, __VA_ARGS__)
#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__)
//nordic_common.h
#define CONCAT_2(p1, p2) CONCAT_2_(p1, p2)
#define CONCAT_2_(p1, p2) p1##p2
分层查看改定义
1. 第一层
#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__)
上述语句使用了c语言中可变参数宏,前一个括号中三个点**…**缺省号代表一个可以变化的参数表。后一个括号中 VA_ARGS 为保留名,作用是把参数传递给宏。当宏的调用展开时,实际的参数就传递给NRF_LOG_INTERNAL_DEBUG 了。
比如调用
NRF_LOG_DEBUG(“cnt= %d/n”, cnt);
而处理器会把宏的调用替换成:
NRF_LOG_INTERNAL_DEBUG (“cnt= %d/n”, cnt);
可变参数支持在每一次调用中传递不同数目的参数,比如调用一个参数也可以。
NRF_LOG_DEBUG(“helloword”);
1. 第二层
//nrf_log_internal.h
#define NRF_LOG_INTERNAL_DEBUG(...) \
NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, __VA_ARGS__)
与第一层相同,同样使用了可变参数宏,区别是第二层入参多了两个参数
** NRF_LOG_SEVERITY_DEBUG** ,定义为:
typedef enum
{
NRF_LOG_SEVERITY_NONE,
NRF_LOG_SEVERITY_ERROR,
NRF_LOG_SEVERITY_WARNING,
NRF_LOG_SEVERITY_INFO,
NRF_LOG_SEVERITY_DEBUG,
NRF_LOG_SEVERITY_INFO_RAW, /* Artificial level to pass information about skipping string postprocessing.*/
} nrf_log_severity_t;
他是一个枚举变量,按照字面含义应该是定义日志输出级别,用于过滤筛选,从上到下依次变大 0-5。再下一层,利用这个参数进行输出过滤。
#define NRF_LOG_INTERNAL_MODULE(level, level_id, ...) \
if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
(level <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
if (NRF_LOG_FILTER >= level) \
{ \
LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); \
} \
}
NRF_LOG_ENABLED 为日志输出总开关是sdk_config.h文件中一个宏定义,如果关闭,下方的日志都不会输出。
//sdk_config.h
#
NRF52832日志系统揭秘:可变参数宏与自定义输出

本文详细解析了NRF52832中自定义log系统的实现,涉及可变参数宏的运用,从NRF_LOG_DEBUG到nrf_log_frontend_std_x的层层递进,以及参数过滤和输出机制。重点在于理解NUM_VA_ARGS_LESS_1和LOG_INTERNAL_X的作用以及日志函数的实际调用过程。
最低0.47元/天 解锁文章
2429

被折叠的 条评论
为什么被折叠?



