Mdebug

[English]

Mdebug (Mesh Network debug) 是用于 ESP-MDF 中重要的一种调试方案,目的是将通过无线 espnow 协议、TCP 协议、串口等方式实现 ESP-MDF 设备日志高效的获取,从而更加方便快捷读取设备日志信息,然后可以根据提取出来的日志进行对应的分析等。

Mdebug 指南主要分为以下几个形式:

  1. 介绍
  2. 功能
  3. 调试方法
  4. 命令管理
  5. 日志管理

介绍

传统的调试方法是通过连接串口读取所有的日志信息,其中这些日志信息有部分是不必要信息,浪费了用户大量筛选时间,而且需要通过 PC 端和设备同时在线连接才能采集到日志信息,导致了时间和资源的浪费。

Mdebug 调试方法与传统的调试方法的不同之处在于,在不影响正常设备的运行的同时,Mdebug 调试可以通过无线调试,日志存储,控制命令筛选日志,从而提高了日志的使用效率和方便性,为设备查找问题和读取需要的信息节约时间和资源。

Mdebug_en
Mdebug 主要分为命令管理和日志管理这两种方式
  1. 命令管理可以大致分为 输入源命令/指令用户自定义添加
  2. 日志管理可以大致分为 UARTFlash storageESPNOW

功能

  • mdebug espnow:将设备中日志数据通过 ESPNOW 无线 WiFi 形式传输给其他设备或者服务器等,从而提高了调试的方便和效率。
  • mdebug flash:将设备中日志数据直接写入到 flash 内存中,该 flash 内存中已经创建好内存空间,掉电保护日志信息,可以随时读取该日志信息,提高了数据的可利用性以及客户的方便。
  • mdebug log:将设备中日志数据通过串口监视器读取,同时设置 UARTflashespnow`使能状态,其中日志信息将 `ESP_MDFMDF_LOGI、MDF_LOGD、MDF_LOGW、MDF_LOGE 等日志信息读取出来。
  • mdebug console:将设备中日志数据通过在终端中的输入命令行形式读取,提高了用户的可操作性和实用性。

调试方法

Mdebug_method

调试方法可以概括为两种方法,一种是 UART 串口调试,另一种是无线 WiFi 调试。

  1. 串口调试在 PC 端使用串口调试工具( linux 下用 minicom 更好),直接获得输出的日志信息,还有可以通过控制命令行调试方法输出需要的日志信息。
  2. 无线 WiFi 调试有两种通讯方式分别是 TCP/IP 协议和 ESPNOW 协议,一种是日志信息通过 TCP/IP 协议传输到 Sever 端,另一种是从子节点的日志信息通过 ESPNOW 协议传输到根节点,然后从根节点的串口或者 TCP/IP 形式提取日志信息。也可以通过控制命令行调试方法输出需要的日志信息。

命令管理

1. 输入源

  • 串口
    PC 端的监视器
  • ESPNOW
    无线调试工具 (ESP-WROVER-KIT-V2)

2. 命令/操作

2.1 一般指令

  • help
    打印已注册命令及其说明
  • version
    获取芯片和 SDK 版本
  • heap
    获取当前可用堆内存大小
  • restart
    软重启芯片
  • reset
    清除设备所有配置信息

2.2 日志命令

命令定义 log -or [<tag>] [<level>] [-s <addr(xx:xx:xx:xx:xx:xx)>] [-e <enable_type (‘uart’or’flash’or’espnow’)>] [-d <disable_type(‘uart’or’flash’or’espnow’)>]  
指令 log -o 将获取日志使能状态
  log -r 读取日志信息
  log -s 将日志发送到指定设备
参数 tag 使用 tag 过滤日志
  level 使用 level 过滤日志
  addr 监视设备 MAC 地址
  e ‘uart’ or ‘flash’ or ‘espnow’ 使能 uart,flash,espnow
  d ‘uart’ or ‘flash’ or ‘espnow’ 禁止串口,flash,espnow
示例 log mdebug_cmd INFO 设置 TAG 为 mwifi 的日 志输出等级为 INFO
  log * NONE 设置所有的日志不输出

2.3 coredump 命令

命令定义 coredump [-loe] [-q ] [-s <addr (xx:xx:xx:xx:xx:xx)>]  
指令 coredump -l 获取该设备上的 coredump 数据长度
  coredump -o 读取该设备上的 coredump 数据并打印 到控制台
  coredump -e 擦除该设备上的 coredump 数据
  coredump -s 发送设备上的 coredump 数据到指定设备
参数 addr 监视设备 MAC 地址
  sequence coredump 数据的序号
示例 coredump -s 30:ae:a4:00:4b:90 将 coredump 数据发送到 30:ae:a4:00:4b:90 设备
  coredump -q 110 -s 30:ae:a4:00:4b:90 将序号 110 开始的 coredump 数据发 送到 30:ae:a4:80:16:3c 设备

3. 自定义添加

可以根据 ESP-MDF 中的 example:function_demo/mwifi/console_test,用户可以自定义添加。

日志管理

Mdebug 中根据日志写入方式不同,大致可以分为两种形式:

  1. 设备的日志信息通过打印方式直接从 串口打印 出来或者把 日志信息写入 flash 存储,然后再调用读取。日志信息的存储将设备日志先写入 flash 内存中(这里的 flash 内存中分配了一个分区为 storage,为了存储设备日志,但是这里的分配的内存是有限的,根据用户设置的文件大小而决定),将会以文件的形式暂存起来,然后通过串口或者无线方式将数据以数据包的形式发送给 PC 或者是服务器;
  2. 设备将通过 espnow 形式发送日志信息。将子节点日志信息通过 ESP-MESH 网络将数据发送给根节点,再从根节点的设备读取日志信息。

Mdebug 中根据日志读取方式不同,日志中有三种使能状态,分别是 uartflashespnow 使能。

1. UART 使能

将串口使能,日志信息将会通过 vprintf 打印出来。

  1. 读取日志的 I/O 口是 UART0,该串口的引脚为 TXD0 是 GPIO1, RXD0 是 GPIO3,同时也是下载串口。

    UART0
    TXDO RXD0
    GPIO1 GPIO3
  2. 读取日志信息,诊断设备出现的问题和查找问题;如果在设备正常运行时,可以关闭串口使能,如果不关闭串口打印,将会占用内存,同时串口打印信息过多,还会激活看门狗,使正常设备运行程序 Backtrace

  3. 串口默认状态为使能状态,用户可以根据自己需要进行关闭。

2. Flash 使能

写入 flash 使能,将日志信息存入 flash 中。

2.1 将 log 保存到 flash

分区表中选择出来一定的内存空间为 storage,这里分配的内存为了给 log 写入到 flash 中提供内存空间。文件名为 spiffs,

spiffs 分区:

# Name,   Type, SubType,  Offset,   Size,  Flags
nvs,      data, nvs,      0x9000,   16k
otadata,  data, ota,      0xd000,   8k
phy_init, data, phy,      0xf000,   4k
ota_0,    app,  ota_0,    0x10000,  1920k
ota_1,    app,  ota_1,    ,         1920k
coredump, data, coredump, ,         64K
storage,  data, spiffs,   ,         64K
reserved, data, 0xfe,     ,         64K

注解

  1. 更新分区表前,需要先擦除整个 flash;
  2. 分区表无法通过 OTA 的方式进行修改;
  3. 文件空间大小可以根据用户合理的选择进行内存分配。

2.2 日志信息存取

Mdebug_access.jpg
  1. 日志初始化,创建两个文本 flash 内存空间,并获取文本的状态 stat,判断写入还是读取,使用到主要函数为 esp_vfs_spiffs_registeresp_spiffs_infosprintffopen
  2. 存取中加入一个互斥锁,当读取日志信息时,则会关闭写入功能,主要用到的函数为 xSemaphoreTakexSemaphoreGive
  3. 写入flash中,先写入时间戳,并记下文本数组的地址指针 g_log_info[g_log_index],主要用到的函数为 timelocaltime_rstrftime
  4. 写入日志数据,同时记下写入文本1数组的地址指针 g_log_index,为了下次日志写入 flash 做好地址寻址,使用到主要函数为 fseekfwrite;
  5. 判断,如果文本1数组的地址指针已满,清零文本1的地址指针,地址偏移到文本2的地址指针,开始写入日志数据;如果未满,将会继续在文本1中写入日志数据;
  6. 同理,当文本2数组的地址指针已满,清零文本2的地址指针,地址偏移到文本1的地址指针,开始写入日志数据;如果未满,将会继续在文本2中写入日志数据;
  7. 根据写入地址指针 g_log_info 获取读取文本地址指针 log_info ,然后读取文本中日志数据,同时也记下读取文本数据的地址偏移指针 offset,为下次从 flash 读取日志做好地址寻址,使用到主要函数为 fseekfread;
  8. 判断,如果文本未读取,将会继续读取文本日志数据;如果文本读取完成,将会结束读取任务。

注解

  1. 日志数据的头是增加了时间戳,这里只是作为实验,并没有实时校准,用户可以根据自己的需求进行修改;
  2. 日志存储的文件大小为 CONFIG_MDEBUG_FLASH_FILE_MAX_SIZE = 16384,用户可以根据自己需求修改日志文件的存储空间;
  3. 日志重定向 将日志存储信息输出重新进行定义,这是为了对于日志写入 flash 进行调试,当日志输出信息出现问题时,可以更好的调试日志输出信息是否正确,使用到的调试函数为 MDEBUG_PRINTF(fmt, ...)
  4. 增加了数据的擦除,当数据存满,将会清除数据指针,重新开始从文件头指针地址开始写入或者读取,用到的主要函数 rewind

2.3 日志数据的格式

日志数据将来自 ESP_MDFMDF_LOGI、MDF_LOGD、MDF_LOGW、MDF_LOGE 等,这是通过 IDF 的日志库会默认使用类 vprintf 的函数将格式化的字符串输出到专用的 UART 上。提取出来的数据如下图所示:

Mdebug_log_data.jpg

因在 MDF 中的日志信息存在头和尾有不需要的数据,这就需要提取和选择有效的字符串数据信息,因此需要将其进行去除和筛选,然后再进行日志数据提取。Front data 中包含了字体颜色等添加的信息,所以需要将头部部分数据去除,Tail data 中包含了换行等数据,同样是需要去除, 对于 MDF_LOGD 没有这些无用数据,所以不需要进行处理。

3. ESPNOW 使能

3.1 ESP-NOW 特性

  • 收发双方必须在同一个信道上
  • 接收端在非加密通信的情况下可以不添加发送端的 MAC 地址(加密通信时需要添加),但是发送端必须要添加接收端的 MAC 地址
  • ESP-NOW 最多可添加 20 个配对设备,同时支持其中最多 6 个设备进行通信加密
  • 通过注册回调函数的方式接收数据包,以及检查发送情况(成功或失败)
  • 利用 CTR 和 CBC-MAC 协议 (CCMP) 保护数据的安全

3.2 ESP-NOW 使能流程

Mdebug_espnow.jpg

通过使能 espnow,可以将子节点的日志数据通过espnow发送给根节点,使得从根节点读取子节点的日志信息,然后通过串口读取日志信息。

这个可以使用 example:wireless_debug 进行测试,ESP-NOW debug 接收板可以不直接与路由器进行连接,只需与 ESP-MESH 网络在同一信道上即可。若需要与接收其他 ESP-MESH 设备的 log,需要在监听的设备中添加以下代码:

MDF_ERROR_ASSERT(mdebug_console_init());
MDF_ERROR_ASSERT(mdebug_espnow_init());
mdebug_cmd_register_common();

关于更多 espnow 可以参看 example:wireless_debug 以及 官方文档 ESPNOW

注解

由于 ESP-NOW 和 ESP-MESH 一样,都是通过 Wi-Fi 接口进行数据包收发,因此,当 ESP-MESH 设备数据传输量较大时,会对其控制命令接收或数据传输产生一些延时。

经实际测试,在网络环境良好的情况下,以下配置参数导致的 ESP-MESH 设备延时是可以忽略的阈值:

  • 50 个 ESP-MESH 设备(设备数量越多,网络环境越差)
  • ESP-NOW 接收端添加 10 个 ESP-MESH 设备(接收端添加数量越多,网络环境越差)
  • 传输日志级别为 info (日志级别越低,网络环境越差)