R-DIAG

概述

../../../_images/diag_overview.svg

R-DIAG 通过 预定义事件类型结构化数据体 统一管理各模块事件,并提供两种接口供上位机获取事件数据:

  • 本地接口:基于物理接口(如 LOGUART),适用于现场调试和快速数据获取。

  • 网络接口:基于网络协议(如 TCP/UDP),适用于远程诊断、多设备并发访问和云端集成。

工作流程

通过 R-DIAG 记录和解析事件的流程如下:

../../../_images/diag_steps.svg
  1. 事件结构定义和记录:在 SDK 中定义事件类型和数据结构,并在代码中调用 API 记录事件。

  2. 生成配置文件:编译时自动生成 JSON 格式的结构体描述文件和版本校验信息。

  3. 记录事件:设备烧录固件后,在运行时按定义记录事件数据。

  4. 获取事件:上位机通过接口读取事件数据。

  5. 解析事件:上位机通过 JSON 文件解析并展示事件详情。

能力与扩展

功能启用

要启用或禁用 R-DIAG 功能,请按以下步骤操作:

  1. 导航至 {SDK}/amebaxxx_gcc_project 目录

  2. 执行指令 ./menuconfig.py 进入 menuconfig 界面

  3. 修改 CONFIG APPLICATION > Enable diagnose 选项

备注

R-DIAG 功能默认为启用状态。

本地故障诊断

SDK 默认支持使用 Realtek 串口调试工具 Trace Tool (v2.1.38+) 通过 LOGUART 获取与解析事件。 工具说明见 日志工具 ,针对 R-DIAG 功能的使用步骤如下:

  • DIAG 选项卡中配置参数

    • Time Period:获取时间范围,默认 “In a week”

    • Start Date / End Date:当 Time Period 选择 "Custom options" 时需手动设置起止时间

    • Buffer Size:单次获取缓冲区大小,默认 500 bytes

  • 点击 Start Diagnose 开始获取事件,解析结果显示在页面左侧

  • 点击 Export 将记录导出到 /TraceTool/DiagnoseInfoExport 的 Excel 文件

../../../_images/trace_tool_diag_feature.png

自定义事件添加

component/soc/common/diagnose/ameba_diag_customer.h 中新增自定义事件步骤如下:

定义事件 ID

DIAG_EVT_CUSTOMER_事件名 格式命名,使用 RTK_EVENT_TYPE_CUSTOMER 作为基址。示例:

enum diag_evt_customer {
    DIAG_EVT_CUSTOMER_DEMO = RTK_EVENT_TYPE_CUSTOMER + 0x01,
    ...
};

定义事件结构

命名规则: 事件 ID 枚举名的小写形式。示例: DIAG_EVT_CUSTOMER_DEMO 对应结构体 diag_evt_customer_demo

内存对齐: 使用 __PACKED 属性

变量定义规则:

  1. 注释要求

    • 面向事件解析的注释必须使用 /* <!-- DIAG: --> xxxxx*/ 并置于变量定义行末,且不可跨行。

    • 示例:

      struct diag_evt_customer_demo {
          u16 reason;     /* <!-- DIAG: --> enum customer_demo_reason in customer_demo_types.h */
          u32 timestamp;  /* <!-- DIAG: --> UNIX time in seconds */ // os tick value
      } __PACKED;
      

      生成 JSON 效果:

      "diag_evt_customer_demo": {
        "reason": {
          "type": "u16",
          "enum_ref": "customer_demo_reason",
          "comment": "enum customer_demo_reason in customer_demo_types.h"
        },
        "timestamp": {
          "type": "u32",
          "comment": "UNIX time in seconds"
        }
      },
      
  2. 不直接使用枚举类型:

    • 根据枚举值范围选择基础整型

    • 在注释标明枚举类型及其定义文件,以便工具解析枚举注释

    • 示例:上述结构体 diag_evt_customer_demo 中变量 reason 实际使用的枚举定义如下:

      // file:customer_demo_types.h (just for example)
      enum customer_demo_reason {
          CUSTOMER_DEMO_RSN_UNKNOWN   = 10001, /* <!-- DIAG: --> unknown */
          CUSTOMER_DEMO_RSN_TIMEOUT   = 10002, /* <!-- DIAG: --> timeout occurred */
          CUSTOMER_DEMO_RSN_THRESHOLD = 10003, /* <!-- DIAG: --> threshold exceeded */
      };
      

      生成的 JSON 文件会映射枚举值与注释:

      "customer_demo_reason": {
          "unknown": 10001,
          "timeout occurred": 10002,
          "threshold exceeded": 10003
      },
      
  3. 结构体嵌套不超过 3 层

  4. 字符串字段使用 char

  5. 位域仅支持 u8u16u32,不足 1 byte 需填充。

记录事件

  • 事件等级如下:

    enum rtk_event_level {
        RTK_EVENT_LEVEL_ALWAYS = 0,
        RTK_EVENT_LEVEL_ERROR,
        RTK_EVENT_LEVEL_WARNING,
        RTK_EVENT_LEVEL_INFO,
        RTK_EVENT_LEVEL_DEBUG,
    };
    
  • 按等级调用 API ,传入三参数: 事件类型 ID 、结构体地址与长度。

    RTK_EVENT_A(_type, _info, _len)
    RTK_EVENT_E(_type, _info, _len)
    RTK_EVENT_W(_type, _info, _len)
    RTK_EVENT_I(_type, _info, _len)
    RTK_EVENT_D(_type, _info, _len)
    
  • 示例(在“客户示例触发”处理函数中,记录 INFO 级事件):

    void customer_demo_trigger_handler(void)
    {
        struct diag_evt_customer_demo event_data = {
            .reason    = 10002,   /* triggered by timeout */
            .timestamp = 1731580000U
        };
    
        RTK_EVENT_I(DIAG_EVT_CUSTOMER_DEMO, (u8 *)&event_data, sizeof(event_data));
     }
    

更新 JSON

请将上位机工具的配置文件更新为编译生成的 ameba_diagnose_format_full.json,避免解析错误。

若使用 本地故障诊断 ,请更新至 /TraceTool/DiagnoseProfiles

事件解析效果

添加上述 DIAG_EVT_CUSTOMER_DEMO 示例事件后,使用 本地故障诊断 解析效果如下:

../../../_images/trace_tool_add_event_example.png

远程故障诊断示例

本示例演示通过 MQTT,在 PC 与 Ameba 设备之间收集并解析诊断事件。

  • SDK 示例路径: {SDK}/component/example/wifi/wifi_diagnose_mqtt

  • PC 端工具路径: diagnose_tool_wrapper

环境与网络拓扑

../../../_images/diag_network_tool_topology.svg
  • 树莓派(安装 Mosquitto 服务器与客户端)作为 MQTT Broker

  • PC 作为上位机,运行事件采集与解析工具

  • Ameba 运行示例固件,产生并通过 MQTT 发送事件

  • 所有设备需连接到同一 AP

  • 使用前确认树莓派的 IPv4 地址(供下文 Ameba 与 PC 配置使用)

  • 主题约定

    • request_diag_events: PC 发布请求; Ameba 订阅

    • response_diag_events: Ameba 发布响应; PC 订阅

备注

树莓派仅为示例 MQTT Broker 运行环境,可替换为:云端服务器(公有云或私有云)、虚拟机(如 VMware、VirtualBox 等)、或 Linux 系统的 PC。

替换时请确保:

  • 已安装并启动 MQTT Broker,监听地址与端口对外可达

  • Ameba 与 PC 能路由访问该 Broker;若不在同一 AP/子网,需要满足跨网段或公网可达,并配置端口转发、防火墙规则、DNS 解析等

快速上手

  1. 获取树莓派在当前 AP 下的 IPv4 地址,如 192.168.1.106

  2. 设备端配置( Ameba 示例)

    • 在文件 {SDK}/component/example/wifi/wifi_diagnose_mqtt/example_wifi_diagnose_mqtt.c 中,将 MQTT Broker 地址改为树莓派 IP :

      static const char *address = "192.168.1.106";
      
  3. 编译与烧录

    • {SDK}/amebaxxx_gcc_project 目录下执行:

      ./build.py -a wifi_diagnose_mqtt
      
    • 完成编译后,按设备平台常规流程烧录固件至 Ameba 设备

  4. PC 端配置

    • diagnose_tool_wrapper/diagnose_defines.py 中,将 Broker 地址更新为树莓派 IP :

      MQTT_BROKER = "192.168.1.106"
      
  5. 运行 PC 端工具

    • 进入 diagnose_tool_wrapper 目录,执行:

      python diagnose_main.py
      
    • 工具将通过 WiFiDiagnoseServer.diag_read_events() 组织流程:

      内部调用 DiagController.diag_read_backgroud_worker() 完成读取前配置(版本哈希校验、时间对齐、发送缓冲区设定、时间范围设定), 随后调用 DiagController.get_diag_event() 获取并解析 Ameba 当天事件,并将结果保存至 diagnose_tool_wrapper/DiagnoseInfoExport 下的 JSON 文件。

  6. 调整获取时间范围(可选)

    • diagnose_main.py 修改 WiFiDiagnoseServer.diag_read_events() 的输入参数,以限定需要拉取的设备时间戳区间。

备注

  • 若版本哈希校验失败,请更新上位机 JSON 与设备一致

  • 若 PC 无法获取事件,请检查:

    • MQTT Broker 是否已启动(树莓派 mosquitto 服务状态)

    • MQTT Broker 所在设备防火墙是否放行 入站 的 MQTT 默认端口(1883)

    • PC 防火墙或安全软件是否允许 出站 连接到 Broker 的 MQTT 端口

    • 客户端连接参数(IP/端口等)与 Broker 配置是否一致

结果可视化

diagnose_tool_wrapper/DiagnoseInfoExport 下生成的 JSON 文件进行简单可视化,效果示意如下:

../../../_images/network_tool_result_example.png

远程故障诊断开发

设备端接口配置

上位机如需通过网络接口获取事件,设备端需在 SDK 代码中注册事件数据发送接口,告诉 Diagnose 组件如何交付事件数据:

int rtk_diag_config_transform(rtk_diag_sender_t sender, u8 *sender_buffer, u16 sender_buffer_size);

项目

描述

功能

配置事件数据的发送接口

参数

sender: 用户实现的事件数据发送函数,原型如下

typedef int (*rtk_diag_sender_t)(const u8 *data, u16 len);

sender_buffer: Diagnose组件用于拷贝事件数据的固定发送缓冲区

sender_buffer_size: 发送缓冲区大小(字节)

返回值

0表示成功,非零为错误码

说明

  • sender 负责将 sender_buffer 中的数据发送到上位机

  • 可在 sender 中实现必要的协议封装(如MQTT发布)

示例

{SDK}/component/example/wifi/wifi_diagnose_mqtt 为例:

u8  diag_send_buf[1024] = {0};
int rtk_diag_mqtt_send(const u8 *data, u16 len);

static void prvMQTTTask(void *pvParameters)
{
    ...
    rtk_diag_config_transform(rtk_diag_mqtt_send, diag_send_buf, 1024);
}

上位机交互协议

上位机工具以请求-响应模式与 Ameba 交互,Ameba 始终被动响应指令;完整流程如下:

../../../_images/diag_get_events_flow.svg
  • 获取事件前配置

    • Hash 检查:验证设备与上位机 JSON 版本一致,避免结构体定义变更导致解析错误

    • OS 时间戳获取:建立上位机真实时间与设备时间戳映射,以解析事件发生的真实时间

    • 发送缓冲设置:限制单次传输最大长度,避免影响系统调度

  • 获取事件交互

    • 上位机将按 Ameba 响应动态更新请求的时间与偏移量参数,直到设备没有更多事件可发送或达到上位机设定的时间范围