NimBLE_LOG移植


本文记录了在 rtthread 上移植 NimBLE 1.5.0 日志系统的过程,包括需要注意的关键点。

NimBLE 日志模块

NimBLE 供移植的日志系统都在下列文件里:

- porting/
  - nimble/
    - include/
      - log/
        - log.h	# 无用文件
      - log_common/
        - ignore.h # 定义了 IGNORE() 宏,用于忽略宏参数
        - log_common.h # 定义了一些日志帮助宏
      - logcfg/
        - logcfg.h # 配置 NimBLE host,mesh,default 模块的日志宏
      - modlog/
        - modlog.h # 基于 printf 的简易日志库

浏览一遍上述文件后,可以知道最重要的就只有两个文件:

  • logcfg.h:协议栈日志配置接口。
  • modlog.h:协议栈自带的基于 printf 的简易日志库。

查看 logcfg.h 文件:

#include "modlog/modlog.h"
#include "log_common/log_common.h"

#define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
#define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__)
#define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__)
#define BLE_HS_LOG_ERROR(...) MODLOG_ERROR(4, __VA_ARGS__)
#define BLE_HS_LOG_CRITICAL(...) MODLOG_CRITICAL(4, __VA_ARGS__)
#define BLE_HS_LOG_DISABLED(...) MODLOG_DISABLED(4, __VA_ARGS__)

#define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__)
#define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__)
#define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__)
#define DFLT_LOG_ERROR(...) MODLOG_ERROR(0, __VA_ARGS__)
#define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__)
#define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__)

该文件内部默认使用协议栈自带的 modlog 日志库,并且提供了 BLE_HS_LOG_*()DFLT_LOG_*(),一个用于 Host 协议栈日志,另一个用于默认模块日志。

nimble/host/include/ble_hs_log.h 文件里包含了 Host 协议栈的日志接口,简化了上述接口:

#include "modlog/modlog.h"
#include "log/log.h"

/* Only include the logcfg header if this version of newt can generate it. */
#if MYNEWT_VAL(NEWT_FEATURE_LOGCFG)
#include "logcfg/logcfg.h"
#endif

#define BLE_HS_LOG(lvl, ...) \
    BLE_HS_LOG_ ## lvl(__VA_ARGS__)

这样协议栈内部的日志才能看懂:BLE_HS_LOG(INFO, "duration=forever");

并且只有在 MYNEWT_VAL(NEWT_FEATURE_LOGCFG) 宏为 1 时才允许发送日志,默认为 1 。

日志模块移植

如果仅仅想使用协议栈自带的日志功能,将 MYNEWT_VAL(NEWT_FEATURE_LOGCFG) 宏配置为 1,并且定义日志级别 MYNEWT_VAL(LOG_LEVEL) 即可,该日志是静态编译生效的。在 modlog.h 文件里定义了相关条件编译宏。

#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_DEBUG
#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
    printf((ml_msg_), ##__VA_ARGS__)
#else
#define MODLOG_DEBUG(ml_mod_, ...) IGNORE(__VA_ARGS__)
#endif

若是想对接其他的日志库,以 rtthread 的 rtdbg 日志模块为例,至少需要将 BLE_HS_LOG_*()MODLOG_DFLT_*() 这两个对接。

porting/npl/rtthread/include/ 目录下创建 logcfg/logcfg.h 文件,并填充日志模块对接内容。

#define DBG_TAG "nimble"
#define DBG_LVL DBG_INFO
#include "rtdbg.h"

#define BLE_HS_LOG_DEBUG(...)       LOG_D(__VA_ARGS__)
#define BLE_HS_LOG_INFO(...)        LOG_I(__VA_ARGS__)
#define BLE_HS_LOG_WARN(...)        LOG_W(__VA_ARGS__)
#define BLE_HS_LOG_ERROR(...)       LOG_E(__VA_ARGS__)
#define BLE_HS_LOG_CRITICAL(...)    LOG_E(__VA_ARGS__)
#define BLE_HS_LOG_DISABLED(...)    IGNORE(__VA_ARGS__)

注意:此时编译系统内有两个 logcfg/logcfg.h 头文件,而 nimble/host/include/ble_hs_log.h 文件里仅仅 #include "logcfg/logcfg.h",怎么确定它包含的是哪个头文件呢?

在编译构建脚本里,我们在导入头文件时需要将移植目录头文件路径 porting/npl/rtthread/include/ 放在系统自带目录之前 /porting/nimble/include

path = [
    cwd + '/porting/npl/rtthread/include',
    cwd + '/porting/nimble/include'
]

完整的移植信息参考:https://github.com/Jackistang/nimble/commit/f03bde795fc05489da007b714070154d554c482e


文章作者: Jackistang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Jackistang !
  目录