NRF52832的日志输出解析( C中可变参数宏使用)

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

可变参数宏

问题起源

在阅读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
#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值