DFX 软件开发指南
概述
本指南介绍 HiDiTingV100 DFX/DIAG 的日志、命令、离线记录、死机诊断、Last Dump、内存维测和 DebugKits 联调能力,以及业务组件的 DFX 接入与验证方法。
工作原理与接口
DFX / DIAG 工作原理
设备侧调用日志或诊断接口后,通过 DIAG 通道向工具侧输出消息。构建过程生成与固件匹配的数据库,DebugKits 依赖该数据库还原日志格式、命令和数据结构。离线日志、死机信息与 Last Dump 用于设备无法持续在线时的故障留存和回溯。
功能与场景选择
| 需求 | 推荐能力 | 文内入口 |
|---|---|---|
| 查看启动和关键状态 | DIAG 日志 | 快速验证 DFX |
| 在工具中触发业务查询 | 命令注册与报文上报 | 命令注册功能 |
| 工具不在线时保留日志 | 日志离线保存 | 日志离线保存功能 |
| 发生异常或复位后定位原因 | 死机诊断、Last Dump | 死机诊断、Last Dump 解析 |
| 查看内存、任务和水线 | 系统维测、内存 DFX | 系统维测接口、内存 DFX 功能 |
| 查看日志或发送命令 | DebugKits | DebugKits 使用说明 |
API 接口列表
接口的参数、返回值和约束以接口参考为准;未提供独立接口页的内容直接链接到声明头文件。
| 用途 | 接口/宏 | 说明 |
|---|---|---|
| 注册 DIAG 命令 | uapi_diag_register_cmd | 注册命令处理表 |
| 注销 DIAG 命令 | uapi_diag_unregister_cmd | 注销命令处理表 |
| 上报单帧数据 | uapi_diag_report_packet | 向工具回传数据 |
| 上报多帧数据 | uapi_diag_report_packets_critical、uapi_diag_report_packets_normal | 分片上报 |
| 注册主动上报 | uapi_diag_register_ind | 注册主动上报处理表 |
| 输出 DIAG 日志 | uapi_diag_info_log、uapi_diag_warning_log、uapi_diag_error_log、uapi_diag_debug_log | 日志等级宏与参数约束 |
| 开关离线日志 | uapi_zdiag_set_offline_log_enable | 控制离线日志保存 |
| 注册运行回调 | app_run | 在应用运行阶段执行初始化函数 |
快速验证 DFX
功能说明
在已经参与目标构建的 Native 业务组件中增加一条 Info 日志和一条 Warning 日志,可以验证日志模块、文件 ID 配置、固件构建、数据库更新以及 DebugKits 解码链路。
工作流程

涉及接口
- app_run:注册应用运行阶段回调。
- uapi_diag_info_log、uapi_diag_warning_log:输出示例日志。
- uapi_diag_register_cmd:添加工具命令时使用;本节的日志验证流程不注册命令。
准备工作
- 按开发环境快速入门准备 SDK 编译环境,建议优先使用一站式 CLI 开发环境,并准备开发板;DebugKits 从海思开发工具下载页的“HiSpark系列工具”获取。
- 选择一个已经参与当前目标构建的 Native 业务组件作为承载组件;如果需要新建组件,先按OpenHarmony Native组件开发用户指南完成组件创建和构建接入。
- 准备与本次构建匹配的
database_evb;首次使用新固件时需要更新该数据库。
最小接入代码
在所选业务组件的源文件中包含 app_init.h 与 diag_log.h,使用 app_run 注册初始化函数。日志参数使用 32 位无符号整数,便于验证编码与 DebugKits 解码结果。
void dfx_log_verify_init(void)
{
uint32_t verify_value = 1;
uapi_diag_info_log(0, "[dfx] boot stage=%u", verify_value);
uapi_diag_warning_log(0, "[dfx] verify value=0x%x", verify_value);
}
app_run(dfx_log_verify_init);
构建与获取固件
环境安装、目标选择、固件构建和产物获取请参见开发环境快速入门。构建完成后,以 CLI 输出的固件包和 database_evb 生成路径为准。
运行与预期结果
- 烧录固件并复位开发板。
- 在 DebugKits 中选择正确芯片和连接通道。
- 通过
Options > Update HDB选择本次构建生成的database_evb,完成后重新连接。 - 打开
Message页面。
启动后应能解码出以下两条消息:
调试方法
- 看不到日志:确认开发板已复位、连接通道正确,并检查日志功能和模块开关。
- 仅显示消息 ID:重新构建、更新匹配的
database_evb,然后重新连接。 - 出现
C未声明:确认文件 ID 已登记到所选模块的log_def.h。 - 需要定位命令、离线日志、死机或 Last Dump 时,使用下面相应功能章节的流程。
DFX 开发与接入
本章先说明业务组件的 DFX 接入方式,再介绍日志、离线保存、命令注册、系统维测和 CHR 等 DFX 能力开发。
业务组件接入流程
- 在承载 DFX 代码的业务组件中加入源文件,并确认该组件已经进入当前目标的组件列表。不要为了验证日志虚构新的 Sample 宏或组件名称。
- 在组件的
CMakeLists.txt中沿用所属日志模块的配置。APP 组件通常使用MODULE_NAME "app"和AUTO_DEF_FILE_ID TRUE;其他组件应保持与同目录现有实现一致。 - 源文件包含 /src/middleware/utils/app_init/app_init.h 和 /src/include/middleware/utils/diag_log.h,在合适的应用阶段通过
app_run注册初始化函数。 - 开启自动文件 ID 后,构建系统会按源文件名生成文件 ID。将对应枚举登记到所属模块的
log_def_*.h;APP 模块的登记位置为 /src/middleware/chips/3322/dfx/include/log_def_app.h。 - 按开发环境快速入门完成当前目标构建,并使用同一次构建生成的固件和
database_evb进行 DebugKits 验证。
初始化函数由 app_run 放入应用运行阶段。日志宏把格式串和 32 位参数编码成 DIAG 消息;构建生成的数据库保存解码信息,因此 DebugKits 必须使用同一次构建生成的数据库。
DIAG维测功能
概述
DIAG维测功能基于单板与DebugKits工具的交互,用于单板诊断和其他维测操作。
功能描述
DIAG维测功能模块提供以下功能:
- 日志打印。用户可以通过日志打印接口将调试信息打印到DebugKits的Message界面。
- 离线日志保存。在没有串口的场景下,DIAG日志可以保存至NandFlash上,需要时导出至PC上进行解析。
- 命令注册。用户可以注册自定义命令,在DebugKits工具的命令行界面输入命令与单板侧进行交互,执行用户自定义的操作。
- 系统维测信息获取。DIAG支持获取系统统计类信息(如内存使用、任务信息),帮助用户定位问题。
日志打印功能
场景说明
用户需要增加调试日志定位问题时,可以通过DIAG提供的日志打印接口,将调试信息打印到DebugKits的Message界面上。
工作流程
以用户在“/src/application/3322/3322_app_standard/main.c”中增加调试日志为例,流程如下:
-
在“/src/application/3322/3322_app_standard/main.c”中调用日志打印接口,输出调试信息。需要包含“diag_log.h”头文件。
表 1 日志打印接口
函数
说明
输出ERROR级别的调试日志(可变参数),最多带10个参数。
输出WARNING级别的调试日志(可变参数),最多带10个参数。
输出INFO级别的调试日志(可变参数),最多带10个参数。
输出DEBUG级别的调试日志(可变参数),最多带10个参数。
-
用户在使用DIAG日志之前,需要先确认使用的模块。在“/src/application/3322/3322_app_standard/main.c”文件中默认使用的是LOG_PFMODULE模块,模块ID的定义详见“/src/middleware/utils/dfx/log/include/log_module_id.h”文件。
如果用户在自定义的目录,自己的代码中使用日志,需要在该目录或者其子目录下的“CMakeLists.txt”文件中增加如下命令:
其中:“app”为模块名称,表示用户在这个组件中使用app模块(模块ID为LOG_APPMODULE)的日志。
-
定义该文件的文件ID,并添加到对应模块的文件ID列表文件中。
如:
- PF 模块的 ID 列表文件:log_def_pf.h
- APP 模块的 ID 列表文件:log_def_app.h
其他模块依次类推。
文件ID的格式:调用日志接口的文件的文件名大写并加“_C”后缀,如:MAIN_C。
-
编译程序,编译过程中将生成“output/3322/database_evb”目录。
- 参照“DebugKits使用说明”中3,将生成的数据库(database_evb)更新至DebugKits的数据库中。打开DebugKits的Message界面查看日志信息(详情请参见“DebugKits使用说明”中的4)。
-
如要更改默认的日志级别以及打开或关闭某些模块的日志,可修改 /src/middleware/chips/3322/dfx/diag_adapt_sdt.c 中的
diag_auto_log_report_enable函数。如图1中的两个数组,分别是默认打开的日志级别和模块。用户可根据实际情况修改。
代码示例
#include "diag_log.h"
int main()
{
uapi_diag_info_log(0, "test out info log. value = %d", 1);
uapi_diag_error_log(0, "test out error log. a = %d, b = %d\r\n", 3, 4);
uapi_diag_warning_log(0, "test out warning log. a = %d, b = %d c= 0x%x\r\n", 3, 4, 5);
}
说明: 请注意,DIAG日志只能支持长度32位及以下的参数,如:"%d"、"%u"、"%x"、"%p",无法支持长度大于32位的参数,如"%ld"、"%s",无法支持浮点参数,如"%f"。
日志离线保存功能
场景说明
如“日志打印功能”中说明,DIAG日志可以通过串口发送至DebugKits工具。在整机或户外等没有串口的场景下,可以打开日志离线存储功能,将DIAG日志以文件的形式保存至文件系统中,需要的时候将日志文件导出到PC上,通过DebugKits工具解析。
工作流程
- 打印日志的方法参见“日志打印功能”。
-
打开/关闭离线日志存储功能特性方法:
示例如下:
/* 特性: 支持日志离线存储到本地 */ #ifndef CONFIG_DFX_SUPPORT_OFFLINE_LOG_FILE #define CONFIG_DFX_SUPPORT_OFFLINE_LOG_FILE DFX_YES #endif在此文件中将“CONFIG_DFX_SUPPORT_OFFLINE_LOG_FILE”的值置为“DFX_YES”离线日志存储功能特性打开;置为“DFX_NO”,功能特性关闭。
-
打开/关闭日志离线存储功能的方法如下:
- 方法一:在代码中调用“uapi_zdiag_set_offline_log_enable”函数。
-
方法二:在DebugKits的命令行界面输入“offline_log_cfg”命令:
offline_log_cfg 1:打开日志离线保存功能。
offline_log_cfg 0:关闭日志离线保存功能。

-
方法三:修改离线日志开关的NV项默认值。
在 NV 的预置值配置文件(如 /src/middleware/chips/3322/nv/nv_config/nv_default/cfg/acore/app.json)中,将离线日志开关 NV 项
offline_enable_flag的值改为 1。
打开日志离线保存功能后,DIAG日志不再输出到串口,而是保存到文件中。
关闭日志离线保存功能后,DIAG日志直接输出到串口。
说明: 使用方法一和方法三,每次启动时,离线日志自动生效。方法二,只是临时生效,复位后会恢复。
-
从“/user/log/”目录导出所有日志文件。其中包含:
- 一个日志索引文件(log_file_diag.bin.idx)
- 若干个日志数据文件(如log_file_diag.bin.0001、log_file_diag.bin.0002等)
-
将日志文件拖入到DebugKits工具,可以查看日志内容(详情请参见《DebugKits工具 使用指南》)。
说明: 保存日志的空间有大小限制,目前总大小为20MB,日志保存空间达到最大值后,会覆盖最早的日志继续保存。
代码示例
#include "diag_log.h"
int main()
{
uapi_zdiag_set_offline_log_enable(true);
uapi_diag_info_log(0, "test out value = %d", 1);
uapi_diag_error_log(0, "test out error a = %d, b = %d\r\n", 3, 4);
}
命令注册功能
场景说明
用户可以注册自定义命令,在DebugKits工具的命令行界面输入命令与单板侧进行交互,执行用户自定义的操作。
工作流程
要想实现通过DIAG命令来控制单板的操作,需要DIAG(单板侧)和DebugKits(工具侧)约定命令和应答的ID,以及命令和应答所发送的数据的数据结构。这些约定需通过预先配置的XML文件来定义。
以增加一条“get_user_info”命令为例,流程如下:
-
在芯片命令 ID 头文件 /src/middleware/chips/3322/dfx/include/soc_diag_cmd_id.h 中定义命令 ID。通用命令及命令 ID 组合方式见 /src/middleware/utils/dfx/diag/include/diag_cmd_id.h。
Hi3322 的芯片自定义命令使用
0xC0~0xEF,其中0xC0~0xCF为系统指标命令段。以下示例选用当前命令 ID 头文件和命令数据库中均未占用的0xD0。代码示例如下:
-
调用“uapi_diag_register_cmd”函数,注册该命令的回调函数。
其中第一个参数“cmd_tbl”表示注册的命令表格,“cmd_num”表示命令表格中命令个数。可参考 /src/middleware/chips/3322/dfx/dfx_system_init.c 中“register_default_diag_cmd”函数的实现。
代码示例如下:
-
在注册 DFX 命令步骤中注册的回调函数“diag_cmd_get_user_info”中,实现收到该命令后的操作,如果需要给DebugKits工具应答,则调用“uapi_diag_report_packet”函数上报应答报文。
代码示例如下:
typedef struct { uint32_t user_value; } user_info_t; static errcode_t diag_cmd_get_user_info(uint16_t cmd_id, void *cmd_param, uint16_t cmd_param_size, diag_option_t *option) { user_info_t info = {0}; (void)cmd_param; (void)cmd_param_size; /* 在这里填充应用实际需要上报的数据。 */ return uapi_diag_report_packet(cmd_id, option, (const uint8_t *)&info, (uint16_t)sizeof(info), true); } -
在 /src/build/config/target_config/3322/hdb_config/database_template/acore/system/hdbcfg/mss_cmd_db.xml 中定义命令。XML 中的命令 ID 按现有数据库格式填写;
diag_cmd_id_comb(0xD0)对应0xD005。代码示例如下(CMD标签部分为需要新增内容):<DebugKits> <GROUP NAME="FIX" DATA_STRUCT_FILE="..\diag\fix_struct_def.txt" MULTIMODE="Firefly" AUTO_STRUCT="YES" PLUGIN="0x111,0x110(1),0x252"> <CMD ID="0xD005" NAME="get_user_info" DESCRIPTION="get_user_info" PLUGIN="0x100" TYPE="REQ_IND"> <REQ STRUCTURE="tool_null_stru" TYPE="Auto" PARAM_VALUE="" /> <IND STRUCTURE="user_info_t" TYPE="Auto" RESULT_CODE="" /> </CMD> </GROUP> </DebugKits> -
参照开发环境快速入门完成构建,将生成的“output/3322/database_evb”数据库更新至DebugKits工具数据库中(参照“DebugKits使用说明”中的更新数据库),打开DebugKits命令行界面,即可输入“get_user_info”命令,实现获取用户数据信息的功能。
Database修改
上述工作流程中配置命令数据库步骤修改的“mss_cmd_db.xml”文件,是DIAG与DebugKits约定数据结构的关键。下面对其详细说明:
- mss_cmd_db.xml中分为两层:GROUP和CMD,每个GROUP可以包含多个CMD命令。
- GROUP中的DATA_STRUCT_FILE字段指向的文件名,表示该GROUP下的命令涉及到的数据结构体都保存在这个文件中。
- CMD中的REQ STRUCTURE字段指向请求命令携带数据对应的结构体,IND STRUCTURE指向应答命令携带的数据对应的结构体。
-
CMD中PLUGIN字段表示该命令在DebugKits生效的界面:
- 0x100:命令行页面
- 0x259:system页面
- 0x110:message页面
-
GROUP中的AUTO_STRUCT字段用来配置结构体是否自动生成,YES表示构建过程中自动生成database的结构体,否则需要自己手动添加到结构体到DATA_STRUCT_FILE字段指向的文件中。例如:
/* mss_cmd_db.xml中添加一条get_user_info命令,CMD ID为0xD005。 */ <CMD ID="0xD005" NAME="get_user_info" DESCRIPTION="get_user_info" PLUGIN="0x100,0x102" TYPE="REQ_IND"> <REQ STRUCTURE="tool_null_stru" TYPE="Auto" PARAM_VALUE="" /> <IND STRUCTURE="user_info_t" TYPE="Auto" RESULT_CODE="" /> </CMD> /*fix_struct_def.txt中添加结构体定义*/ typedef struct { uint32_t user_info1; uint32_t user_info2; uint32_t user_info3; uint32_t user_info4; uint32_t user_info5; uint32_t user_info6; } user_info_t;
系统维测接口
系统维测功能提供了以下接口:
- 内存使用统计接口
- 任务信息统计接口
内存使用统计
概述
内存使用统计提供内存使用信息查询的接口,可实时获取内存使用大小、峰值占用等信息。
功能描述
DIAG提供内存使用统计信息查询接口“diag_cmd_get_mem_info”,调用该接口可获取系统内存池总大小、已用空间、剩余空间、剩余空间节点个数、内存池已经使用的节点个数、内存池剩余空间中最大节点的大小以及内存池使用峰值等信息。以上信息以“mdm_mem_info_t”结构体的格式,发送到DebugKits中显示出来。如图1所示。

命令行代码示例
errcode_t diag_cmd_get_mem_info(uint16_t cmd_id, void * cmd_param, uint16_t cmd_param_size, diag_option *option)
{
errcode_t ret;
mdm_mem_info_t info;
uapi_unused(cmd_param);
uapi_unused(cmd_param_size);
ret = dfx_mem_get_sys_pool_info(&info);
if (ret != ERRCODE_SUCC) {
return ret;
}
uapi_diag_report_packet(cmd_id, option, (uint8_t)&info, (uint16_t)sizeof(mdm_mem_info_t), true);
return ERRCODE_SUCC;
}
任务信息统计
概述
任务信息统计功能可查询任务名、任务状态、当前SP、优先级、栈峰值、栈大小等信息。
功能描述
提供任务统计功能查询接口“diag_cmd_get_task_info”,调用该接口可实时获取当前系统任务ID、任务状态、任务优先级、信号量、栈峰值、栈大小等信息。上述数据以“task_info_t”结构体的格式,发送到DebugKits中显示出来。如图1所示。

命令行代码示例
errcode_t diag_cmd_get_task_info(uint16_t cmd_id, void * cmd_param, uint16_t cmd_param_size, diag_option *option)
{
uint32_t task_cnt;
errcode_t ret;
task_info_t *infs = NULL;
uapi_unused(cmd_param);
uapi_unused(cmd_param_size);
task_cnt = dfx_os_get_task_cnt();
if (task_cnt == 0) {
return ERRCODE_FAIL;
}
infs = dfx_malloc(0, task_cnt * sizeof(ext_task_info));
if (infs == TD_NULL) {
return ERRCODE_FAIL;
}
ret = dfx_os_get_all_task_info(infs, task_cnt);
if (ret != ERRCODE_SUCC) {
dfx_free(0, infs);
return ret;
}
for (unsigned i = 0; i < task_cnt; i++) {
task_info_t *inf = &infs[i];
if (inf->valid) {
uapi_diag_report_packet(cmd_id, option, (uint8_t *)inf, (uint16_t)sizeof(task_info_t), true);
}
}
dfx_free(0, infs);
return ERRCODE_SUCC;
}
CHR打点功能
场景说明
在某些行为需要被记录时,可以通过调用CHR打点接口(支持单核或者多核打点)将打点数据保存到文件系统中,在需要的时候将CHR打点文件导出到PC上,通过DebugKits工具进行解析。
工作流程
以用户在“/src/application/3322/3322_app_standard/thread_init.c”中增加CHR打点日志为例,流程如下:
-
在“/src/application/3322/3322_app_standard/thread_init.c”中调用CHR打点接口添加event_xxx时,输出调试信息。thread_init.c中需要包含“massdata_buffer.h”头文件,需要该头文件中的massdata_event_id中添加event_xxx,并且自定义info1/info2/info3事件。
表 1 CHR打点接口
函数
说明
记录打点事件,最多支持以下四个参数event_id/info1/info2/info3,参数的层级关系如图1所示。
记录打点事件,最多支持以下四个参数event_id/info1/info2/info3,参数的层级关系如图1所示。其中info3支持可变长度的buf,需要在入参中输入info3的长度,最大为128Byte。

-
打开/关闭CHR打点功能特性方法:
示例如下:
/ /* 特性: 支持大数据打点 */ #ifndef CONFIG_DFX_SUPPORT_MASSDATA_DOTTING #define CONFIG_DFX_SUPPORT_MASSDATA_DOTTING DFX_YES #endif在此文件中将“CONFIG_DFX_SUPPORT_MASSDATA_DOTTING”的值置为“DFX_YES”离线日志存储功能特性打开;置为“DFX_NO”,功能特性关闭。
-
打开/关闭CHR打点功能的方法如下:
- 方法一:在代码中调用“uapi_massdata_set_state”函数。
-
方法二:在DebugKits的命令行界面输入“diag_dfx 9,[0,2,0]”命令:
diag_dfx 9,[0,2,0]:打开CHR打点功能。
diag_dfx 9.[0,0,0]:关闭CHR打点功能。
![diag\_dfx 9.\[0,0,0\]:关闭CHR打点功能](figures/diagdfx9.%5B0,0,0%5D%EF%BC%9A%E5%85%B3%E9%97%ADCHR%E6%89%93%E7%82%B9%E5%8A%9F%E8%83%BD.png)
说明: 保存日志的空间有大小限制,目前总大小为96KB,日志保存空间达到最大值后,会覆盖最早的日志继续保存。
代码示例
#include "massdata_buffer.h"
typedef enum {
MT_CASE1 = 0x0,
MT_CASE2 = 0x1,
} massdata_xxx_info1;
typedef enum {
MT_CASE1_STEP1 = 0x0,
MT_CASE1_STEP2 = 0x1,
} massdata_xxx_CASE1_info2;
int main()
{
uapi_massdata_record_system_event(event_xxx, MT_CASE1, MT_CASE1_STEP1, 0);
uapi_massdata_record_system_event(event_xxx, MT_CASE1, MT_CASE1_STEP2, 0);
}
故障诊断与数据分析
本章介绍死机信息、Last Dump 和内存 DFX 数据的获取、解析与定位方法。
死机诊断
简介
死机诊断是指HiDiTingV100在发生异常时能够记录并输出系统异常信息,后统称死机信息。其中包括死机现场的PC地址、返回地址、栈地址、CPU寄存器信息以及部分内存信息等。用户可根据实际使用场景进行获取并通过分析定位根因,解决死机问题。
HiDiTingV100支持以下表1所示几种方式记录并输出死机信息。
类型 |
说明 |
依赖 |
适用场景 |
所在章节 |
|---|---|---|---|---|
串口死机信息 |
死机时在串口直接输出死机信息 |
串口 |
适用于未关闭串口的情况。可以获取死机时异常信息、CPU寄存器信息、函数调用栈信息等。 |
|
Flash死机文件 |
死机时在Flash中保存死机信息 |
Flash |
适用于产品阶段,关闭串口输出的情况。可以获取死机时异常信息、CPU寄存器信息、函数调用栈信息等。 |
|
Last word |
死机时将死机的临终遗言输出到DebugKits工具 |
Debug串口,DebugKits工具 |
适用于未关闭Debug串口的情况。可以获取死机时PC地址、返回地址、栈地址、CPU寄存器值等信息。 |
|
Last dump |
死机时将当时的部分内存和寄存器信息输出到DebugKits工具,并保存到Flash中 |
Debug串口,DebugKits工具 |
适用于未关闭Debug串口的情况。可以获取到死机时的大部分内存的原始数据,以及部分关键寄存器的信息,现场数据比较丰富,适用于定位一些踩内存等比较难定位的问题。 |
|
J-Link调试信息 |
死机时连接J-Link查看现场信息 |
J-Link |
适用于开发初期,单板需要能够连接J-Link调试器。可以获取大量现场数据(如内存、寄存器、flash数据等)。 |
死机信息获取
本节主要介绍“表1”中的几种死机信息的获取方式:
- 通过串口工具获取死机打印信息。
- 通过保存在Flash中的死机文件获取死机信息。
-
通过DebugKits工具获取死机信息。
-
连接J-Link调试器获取死机信息。
适用场景:
- 在研发调测场景下,上述四种方法均适用。
- 在外网场景下适用通过DebugKits工具或者Flash中的死机文件来获取死机信息。
说明: 死机信息通过串口打印,要保证死机时单板已连接串口工具。
串口工具界面输出
单板与PC通过串口连接之后,打开任意串口工具(SSCOM/XSHELL/IPOP/MobaXterm等)界面。选择对应的端口号之后点击打开串口进行连接,波特率选择115200,如图1所示。

当单板与串口工具处于连接状态时,如果单板发生死机,串口工具能够接收到复位前OS打印的死机信息。如图2所示。

Flash中的死机文件获取
在发生死机异常时,系统会同时将死机信息以死机文件的形式保存在Flash文件系统中。
- APP核死机文件路径:/user/exc/app_exc_info.bin
- BT核死机文件路径:/user/exc/bt_exc_info.bin
死机文件可使用DebugKits工具导出,步骤如下:
(DebugKits详细操作方法请参见“DebugKits使用说明”以及《DebugKits工具 使用指南》)
图 1 死机文件导出方法

- 在标注①处选好死机文件导出存放位置。
- 在标注②处填写“/user/exc”。
- 在标注⑤处点击“Get File List”按钮获取该目录下所有文件,在标注③处选择需要下载的死机文件。
- 在标记④处点击“Download”或“Download All”按钮,死机文件将下载至标注①选择的目录位置。
通过DebugKits工具获取
在死机故障发生时,如果DebugKits处于连接状态,会获取到两种死机信息:
- Last word信息
- Last dump信息
参照“DebugKits使用说明”中的1~4,打开DebugKits工具的消息界面,可以实时观测芯片运行时打印的具体信息,如图1所示。
当死机发生时消息界面将会打印出Last word以及Last dump信息。

获取Last word信息
Last word信息是死机发生时的临终遗言,其中包括PC地址、返回地址、栈地址、CPU寄存器值等信息。用户可以根据Last word的具体信息分析错误类型、定位错误原因。
在DebugKits的Message界面,点击Last word那一行,即可查看Last word具体信息,其中,A核的Last word和BT核的Last word有所不同,A核的Last word信息如图1所示。BT核Last word信息如图2所示。


A核和BT核的Last word信息差异在于:
- 在message界面中名称不同:A核名称为last_word,BT核名称为EXCEPTION_LAST_RUN_INFO。
- 内容中reg_value的个数不同和对应的含义不同:A核reg_value为32个,BT核reg_value为13个。其对应的含义详见“Last word信息查看”章节。
获取Last dump信息
-
Last dump信息是在死机故障发生时,将单板中的部分内存和寄存器信息通过串口发送到PC端,通过DebugKits工具生成bin文件存储到的安装目录中的DumpInfo子目录之下,具体参考图1。
用户可以通过解析这些文件来定位死机原因。解析这些文件的方法请参见“Last Dump解析”。

说明: 将内存dump到DebugKits中需要一定时间(Liteos:1~2 min,FreeRtos:4~5 min),因此如果需要使用Last dump分析死机信息,注意不要在发生死机故障后立即复位,否则Last dump信息可能无法完整获取。
-
死机故障发生时,如果单板没有连接debugkits,系统会同时将Last dump信息以bin文件的形式保存在Flash文件系统中。
- APP核死机文件路径:/user/exc/APP_ITCM_ORIGIN.bin、/user/exc/APP_DTCM_ORIGIN.bin、/user/exc/SHARE_MEM.bin、/user/exc/MCPU_TRACE_MEM_REGION.bin
- BT核死机文件路径:/user/exc/BT_RAM_ORIGIN、/user/exc/SHARE_MEM.bin、/user/exc/BCPU_TRACE_MEM_REGION.bin
连接J-Link调试器导出
在允许连接JTAG调试器的场景下,用户可连接劳特巴赫或J-Link仿真器等工具进一步获取死机现场的相关信息。以下主要介绍通过J-Link仿真器获取死机相关信息的过程。
在条件允许的情况下,建议开启死机不复位功能进行死机定位。死机现场时,连接J-Link,可以查看“串口工具界面输出”小节所展示的信息,还可查询内存信息、栈信息、外设寄存器、维测变量等更丰富的数据。
使用J-Link仿真器调试需先连接单板的20PIN排针,具体排针位置以实际产品为准。
硬件连接后,双击仓库中的 Commandline_hi3322_mcpu.bat 脚本,脚本将自动进行连接(其他核的连接操作可参照此方法进行)。
图 1 J-Link连接MCPU示意图

须知: 注意RISC-V架构处理器需要使用V10及以上版本的J-Link仿真器。
死机信息查看
对于“死机信息获取”中描述的几种方式获取的死机信息,本节分别介绍它们的查看方式和定位方法。
串口死机信息查看
在死机故障发生时,一般会在串口输出“串口工具界面输出”中描述的死机信息。其中包含几个部分:异常信息汇总、CPU寄存器信息、函数调用栈信息。
异常信息汇总
表 1 异常信息汇总
成员 |
说明 |
|---|---|
task |
死机的任务名称。 |
thrdPid |
死机的任务ID。 |
type |
死机类型,type = mcause & 0xFFF。 |
CPU寄存器信息
表 1 死机相关CPU寄存器说明
成员 |
说明 |
|---|---|
mepc |
机器异常程序计数器。当发生异常时,mepc指向导致异常的指令;对于中断,mepc指向中断处理后应该恢复的位置。 |
mstatus |
机器状态寄存器。 |
mtval |
机器陷入寄存器。保存地址异常中出错的地址或者发生指令异常的指令本身,对于其他错误,其值为零。 |
mcause |
机器异常寄存器。保存目前异常或者中断的原因,通过查询表2得到目前异常或者中断的类型。表格中的异常码 = mcause & 0xFFF。 |
ccause |
ccause为mcause的补充说明,对于某些异常通过读取ccause寄存器的内容可以进一步明确异常类型。 |
图 1 死机相关CPU寄存器说明

异常码 |
mcause异常描述 |
ccause异常描述 |
|---|---|---|
0x0 |
Instruction address misaligned |
Not available |
0x1 |
Instruction access fault |
Memory map region access fault |
0x2 |
Illegal instruction |
AXIM error response |
0x3 |
Breakpoint |
AHBM error response |
0x4 |
Load address misaligned |
Crossing PMP entries |
0x5 |
Load access fault |
System register access fault |
0x6 |
Store/AMO address misaligned |
No PMP entry matched |
0x7 |
Store/AMO access fault |
PMP access fault |
0x8 |
Environment call from U-mode |
CMO access fault |
0x9 |
Environment call from S-mode |
CSR access fault |
0xA |
Reserved |
LDM/STMIA instruction |
0xB |
Environment call from M-mode |
ITCM write access fault |
0xC |
Instruction page fault |
Not available |
0xD |
Load page fault |
Not available |
0xE |
Reserved |
Not available |
0xF |
Store/AMO page fault |
Not available |
0xFFF |
NMI interrupt |
Not available |
函数调用栈信息
函数调用栈call stack会显示与异常相关的所有函数调用指令。用户可以根据函数调用栈检查异常发生时函数调用的上下文定位。其中call back 0为栈顶函数,其对应的ra为栈顶函数的地址,以此类推。
用户可以到“output/3322/acore/diting-community/application.lst”中找到对应的函数。
Flash中的死机文件信息查看
按照“Flash中的死机文件获取”中的描述,从Flash中导出的死机文件为二进制文件,需使用死机信息解析脚本(dump_parser)解析后查看。
死机信息解析脚本支持在Windows和Linux环境下运行,可解析从Flash中读出的A核和BT核死机信息。
-
Linux运行方式:进入脚本目录给予脚本可执行权限并运行下列命令,结果如图1所示。
chmod +x run_hi3322.sh
./run_hi3322.sh <死机信息文件路径> [lst 文件路径(可选)]


-
Windows运行方式:在脚本目录下打开命令提示符,运行下列命令即可开始解析,结果如图2所示。
run.bat <死机信息文件路径> [lst 文件路径(可选)]


Flash死机文件解析后的具体内容以及含义,A核的死机信息可参考“串口死机信息查看”;BT核的死机信息,可参考“Last word信息查看”。
说明: 使用中的常见问题:
通过DebugKits获取的死机信息查看
Last word信息查看
如“获取Last word信息”中描述,在发生死机故障时,会将Last word信息发送到DebugKits工具上。
Last word上报的内容及含义如表1所示(具体含义中括号里面的为代称)。
变量名称 |
具体含义 |
|---|---|
stack_limit |
系统栈大小。 |
fault_type |
错误类型(mcause)。其中NMI interrupt在A核为0x80000FFF,在BT核为0x8000000C。 |
fault_address |
错误地址,属性值无意义。 |
fault_reason |
错误原因,属性值无意义。 |
reg_value |
保存寄存器值。 |
psp_value |
栈指针(sp)。 |
lr_value |
返回地址(ra)。 |
pc_value |
发生错误的指令地址(mepc)。 |
psps_value |
全局指针(gp)。 |
primask_value |
异常状态寄存器(mstatus)。 |
fault_mask_value |
CPU访问异常地址或异常值(mtval)。 |
bserpri_value |
自定义异常状态寄存器(ccause)。 |
control_value |
CPU访问异常地址或异常值(mtval)。 |
对于Last word内容中保存的寄存器的值(reg_value),其个数和具体含义A核和BT核有所不同。
成员名称 |
成员含义 |
|---|---|
reg_value[0] |
无意义 |
reg_value[1] |
返回地址(ra) |
reg_value[2] |
栈指针(sp) |
reg_value[3] |
全局指针(gp) |
reg_value[4] |
线程指针(tp) |
reg_value[5] |
临时寄存器(t0) |
reg_value[6] |
临时寄存器(t1) |
reg_value[7] |
临时寄存器(t2) |
reg_value[8] |
被调函数需要保存用的寄存器/调用栈的帧指针(s0) |
reg_value[9] |
被调函数需要保存用的寄存器(s1) |
reg_value[10] |
函数参数/返回值(a0) |
reg_value[11] |
函数参数/返回值(a1) |
reg_value[12] |
函数参数(a2) |
reg_value[13] |
函数参数(a3) |
reg_value[14] |
函数参数(a4) |
reg_value[15] |
函数参数(a5) |
reg_value[16] |
函数参数(a6) |
reg_value[17] |
函数参数(a7) |
reg_value[18] |
被调函数需要保存用的寄存器(s2) |
reg_value[19] |
被调函数需要保存用的寄存器(s3) |
reg_value[20] |
被调函数需要保存用的寄存器(s4) |
reg_value[21] |
被调函数需要保存用的寄存器(s5) |
reg_value[22] |
被调函数需要保存用的寄存器(s6) |
reg_value[23] |
被调函数需要保存用的寄存器(s7) |
reg_value[24] |
被调函数需要保存用的寄存器(s8) |
reg_value[25] |
被调函数需要保存用的寄存器(s9) |
reg_value[26] |
被调函数需要保存用的寄存器(s10) |
reg_value[27] |
被调函数需要保存用的寄存器(s11) |
reg_value[28] |
临时寄存器(t3) |
reg_value[29] |
临时寄存器(t4) |
reg_value[30] |
临时寄存器(t5) |
reg_value[31] |
临时寄存器(t6) |
表 3 BT核Last word中reg_value成员含义
成员名称 |
成员含义 |
|---|---|
reg_value[0] |
函数参数/返回值(a0) |
reg_value[1] |
函数参数/返回值(a1) |
reg_value[2] |
函数参数(a2) |
reg_value[3] |
函数参数(a3) |
reg_value[4] |
函数参数(a4) |
reg_value[5] |
函数参数(a5) |
reg_value[6] |
函数参数(a6) |
reg_value[7] |
函数参数(a7) |
reg_value[8] |
被调函数需要保存用的寄存器/调用栈的帧指针(s0) |
reg_value[9] |
被调函数需要保存用的寄存器(s1) |
reg_value[10] |
被调函数需要保存用的寄存器(s10) |
reg_value[11] |
被调函数需要保存用的寄存器(s11) |
reg_value[12] |
被调函数需要保存用的寄存器(s2) |
Last dump信息查看
如“获取Last dump信息”中描述,当死机故障发生时,同时会将当前的内存dump到DebugKits保存下来,并可使用相关工具做进一步解析。详细使用方法请参见“Last Dump解析”。
在解析生成的“memory_result.txt”中搜索“死机”可查询到死机信息,如图1所示。

其中的内容与串口中的死机信息类似(如图2所示),不同的是,Last dump的死机信息中函数调用栈中的地址会自动找到对应的函数。
连接J-Link调试器查看信息
本小节主要介绍在死机现场使用J-Link调试器导出死机信息的过程。
通过“连接J-Link调试器导出”的方法连接J-Link后,可使用表1中的命令查看当前的状态和信息,如:寄存器、内存、flash中的数据。
命令 |
说明 |
|---|---|
con/connect |
连接。 |
h/halt |
暂停,停止。 |
g/go |
继续,运行。 |
mem32 mem16 mem8 |
I/O读32bit:mem32 <Addr>, <NumItems> (hex) (Addr表示内存地址,NumItems表示从Addr开始连续读几个32bit) I/O读16bit:mem16 <Addr>, <NumItems> (hex) I/O读8bit:mem8 <Addr>, <NumItems> (hex) |
w4 w2 w1 |
I/O写4Byte:w4 <Addr>, <Data> (hex) I/O写2Byte:w2 <Addr>, <Data> (hex) I/O写1Byte:w1 <Addr>, <Data> (hex) |
readcsr |
读riscv csr寄存器:ReadCSR <RegIndex> |
writecsr |
写riscv csr寄存器:WriteCSR <RegIndex>,<Value> |
查询I/O信息
-
查询CPU寄存器信息,如图1所示。

-
查询内存信息,获取维测变量值或普通变量值。
说明: 以上地址信息仅作为演示使用,查询步骤供用户参考使用。
常见死机问题定位
看门狗重启问题定位
看门狗死机导致的重启问题,大概率为代码中存在死循环(包含次数很大的循环)或某个业务一直被执行(例如灌包),使得IDLE任务无法得到调度,规定时间内未进行踢狗造成的重启。通常可以通过表1中的信息并结合lst文件,确定具体的死机位置。
成员 |
说明 |
|---|---|
type/mcause |
看门狗死机,死机类型为0xFFF。 |
mepc |
通过mepc确定看门狗到期时的pc。根据概率推测可知,该代码基本为死循环中会调用的代码。 |
返回地址(ra)和栈 |
如果mepc在通用函数中,例如memcpy函数中,可以通过ra和栈内容进一步确认函数调用流程。 |
CPU异常触发重启问题定位
通过fault_type值的含义的描述内容,可确认CPU异常触发重启具体为哪种死机问题。
表 1 CPU异常的fault_type含义
fault_type错误 |
说明 |
|---|---|
Instruction address misaligned |
取址地址不对齐,riscv要求指令双字节对齐位置。 |
Instruction access fault |
取址地址异常。 |
Illegal instruction |
非法指令。 |
Load address misaligned |
取数据的目标地址不对齐。 |
Load access fault |
取数据的目的地址是禁止进行读操作的地址。 |
Store/AMO address misaligned |
存储数据目标地址不对齐。 |
Store/AMO access fault |
存储数据的目的地址是禁止进行写操作的地址。 |
Store或Load异常
表 1 store或load异常关键信息
成员 |
说明 |
|---|---|
mepc |
通过mepc确定异常的语句。 |
返回地址(ra)和栈 |
如果mepc在通用函数中,如memcpy中,可以通过ra和栈内容进一步确认函数调用流程。 |
mtval |
通过mtval确认访问的的异常地址。 |
寄存器值 |
如mepc指向下面语句时,可以确认a1值是否合法。
|
说明:
- 由于存储存在异步性,存储异常时mepc指向的语句可能不是异常语句。
RISCV lb、lh、lw、ld、sb、sh、sw、sd指令要求访问地址字节对齐。
- lb(load byte):对齐要求为1字节。
- lh(load halfword):对齐要求为2字节。
- lw(load word):对齐要求为4字节。
- ld(load doubleword):对齐要求为8字节。
- sb(store byte):对齐要求为1字节。
- sh(store halfword):对齐要求为2字节。
- sw(store word):对齐要求为4字节。
- sd(store doubleword):对齐要求为8字节。
因此,对于load和store指令,被访问的地址不满足对应数据长度的对齐要求,将会引发地址对齐异常,建议客户在定义全局变量时,使用__attribute__((aligned(8)))进行对齐。
取指异常
取指异常通常为PC跑飞造成的。首先可以确认mepc的范围是否正常,通过ra和调用栈分析可以确认代码跑飞的位置。
造成代码跑飞主要原因如下:
- 存储函数跳转地址的钩子变量被踩,导致函数跳转到非法地址。
- 栈被踩,导致函数无法正确返回上一级函数而跑飞。
- 代码段本身被踩。
Last Dump解析
概述
Last Dump解析功能是指将死机发生时导出的内存数据的内容进行解析,将.bin文件解析为可读性较好的文本文件,为问题定位提供参考信息。
功能描述
Last Dump解析功能主要包括两个部分:
- 第一部分主要功能是解析DWAEF文件的“.debug_info”段,将对应的tag解析生成python格式的class文件,同时解析符号表,获取全局变量信息。此步骤当前集成在版本构建流程中。
- 第二部分主要功能是将第一步生成的文件作为输入,解析死机dump文件,生成文本信息。此步骤当前集成在DebugKits工具中。
场景说明
针对死机问题定位信息少,问题定位困难等场景,提供Last Dump解析功能,为死机问题定位提供更多的参考信息。
工作流程
- 死机dump文件获取,请参考“获取Last dump信息”。其中,DebugKits工具导出的Last dump生成文件就是待解析的死机文件(Last Dump功能是否开启通过DUMP_MEM_SUPPORT、DUMP_REG_SUPPORT、SUPPORT_DFX_EXCEPTION这三个宏控制)。
-
编译构建生成解析工具。上文已经介绍了解析功能的第一步集成在版本构建流程中,Last Dump解析前需要先进行版本编译构建获取parse_tool解析工具。
- 在 /src/build/config/target_config/3322/target_config.py 的
target_standard_3322_application_template配置中,将gen_parse_tool从False改为True。 - 按开发环境快速入门完成版本编译。Last Dump 解析所需脚本和中间文件在构建过程中生成;脚本源文件见 /src/build/script/parse_tool/。生成成功时,构建日志会提示“Build parse tool success”。
- 编译结果确认,在output目录“output/3322/acore/<target-name>/”下生成“application.nm”文件、“application.llvminfo”文件以及“parse_tool”文件夹,其中“parse_tool”文件夹下包括如下文件。
- auto_class.py:此文件在编译过程中生成,内存解析脚本需要import的python模块。
- auto_struct.txt:database路径下“mss_cmd_db.xml”文件内结构体自动生成结果,可拷贝到Debugkits工具的database路径下,用于Debugkits工具解析日志。
- global.txt:此文件在编译过程中生成,内存解析时需要导入的全局变量信息。
- config.py:内存解析脚本配置文件。
- parse_basic.py:内存解析脚本。
- parse_elf.py:内存解析脚本。
- parse_freertos.py:FreeRTOS系统解析脚本。
- parse_liteos.py:Liteos系统解析脚本。
- parse_main_phase1.py:内存解析脚本的第一阶段入口,已集成在编译构建过程中,主要目的是生成上面的“auto_class.py”、“auto_struct.txt”以及“global.txt”文件。
- parse_main_liteos206_phase2.py:Liteos206版本内存解析脚本的第二阶段入口,对应Liteos206版本的解析,在DebugKits工具界面调用,用于将全内存.bin文件解析为用户可见的文本信息。
- parse_main_liteos207_phase2.py:Liteos207版本内存解析脚本的第二阶段入口,对应Liteos207版本的解析,在DebugKits工具界面调用,用于将全内存.bin文件解析为用户可见的文本信息。
- parse_main_liteos208_6_phase2.py:Liteos208版本内存解析脚本的第二阶段入口,对应Liteos208版本的解析,在DebugKits工具界面调用,用于将B核的全内存.bin文件解析为用户可见的文本信息。
- parse_main_liteos208_8_phase2.py:Liteos208版本内存解析脚本的第二阶段入口,对应Liteos208版本的解析,在DebugKits工具界面调用,用于将A核的全内存.bin文件解析为用户可见的文本信息。
- parse_main_freertos_phase2.py:FreeRTOS版本内存解析脚本的第二阶段入口,对应FreeRTOS版本的解析,在DebugKits工具界面调用,用于将全内存.bin文件解析为用户可见的文本信息。
- parse_print_global_var.py:内存解析脚本。
- xml_main.py:内存解析脚本。
- 在 /src/build/config/target_config/3322/target_config.py 的
-
执行Last Dump解析。在执行Last Dump解析之前,确保运行解析工具的PC上已安装python3和DebugKits工具。
-
在DebugKits工具的System界面选取“DumpAnalys”选项,在对应的选项上选取相应的路径;如图1所示(注:也可以将编译后的parse_tool文件夹,“application.nm”文件及Last dump内存导出文件拷贝到本地PC上进行处理,工具选取对应路径即可)。

- python file是解析脚本的路径,需要用户选取,例如“/output/3322/acore/<target-name>/parse_tool/parse_main_****_phase2.py”。根据固件使用的OS选择对应脚本:LiteOS 206、207、208(6/8)分别使用同名版本的
parse_main_liteos*_phase2.py,FreeRTOS使用parse_main_freertos_phase2.py;仓内脚本源文件见 /src/build/script/parse_tool/。 - NM file为内存解析脚本的输入文件,在版本构建时通过编译命令解析elf文件生成,路径:/output/3322/acore/<target-name>/application.nm。
- Global path为内存解析时需要导入的全局变量信息,在版本构建时通过解析脚本的第一步生成,路径:/output/3322/acore/<target-name>/parse_tool/global.txt。
- bin list为待解析的内存文件路径(即通过DebugKits工具导出的内存bin文件的存储路径:例如:D:\DebugKits\DumpInfo\DumpInfo_1),只需要选取路径即可,工具会自动加载该路径下相关的.bin文件。
- Output file为解析结果文件存放路径,需要用户选取,例如“D:\DebugKits\DumpInfo\DumpInfo_1\memory_result.txt”。
- python file是解析脚本的路径,需要用户选取,例如“/output/3322/acore/<target-name>/parse_tool/parse_main_****_phase2.py”。根据固件使用的OS选择对应脚本:LiteOS 206、207、208(6/8)分别使用同名版本的
-
单击Dump Analyze界面的“Execute”按钮,正常情况下DebugKits工具界面会显示解析结果,并且在用户选取的Output file路径下会生成“memory_result.txt”解析结果如图2所示,如果没有显示结果,则参考“异常处理”的介绍进行处理。

-
分析解析结果。
打开“memory_result.txt”文件可以查询到当前的中断信息、任务信息、消息队列、信号量、全局变量、死机信息、CPU_TRACE信息等。
图 3 Last Dump解析结果片段

-
异常处理
- 如果执行Last Dump解析后DebugKits工具没有显示解析结果,首先需要确认“application.nm”文件、“application.llvminfo”文件、“parse_tool”脚本及导出的“.bin”文件是否出自同一个软件版本。不同版本的输入不匹配可能会导致异常。
-
DebugKits工具导入待解析的.bin文件时选取的是整个目录,要保证DebugKits工具配置文件“\DebugKits\Source-Datas\bin\config\config.ini”中的配置与DumpInfo文件夹下导出文件的地址及大小一致,否则也会导致解析异常。
可以将“config.ini”中的 DumpInfo 配置项与源码 last_dump_adapt.c 中的 g_mem_dump_info 数组中的元素进行对比。如不一致,则要按照 g_mem_dump_info 数组的定义修改“config.ini”中的 DumpInfo 配置项。
例如图1中的“APP_ITCM_ORIGIN_StartAddr”的值应该等于图2中的“APP_ITCM_ORIGIN”的值,“APP_ITCM_ORIGIN_Length”的值应该等于“APP_ITCM_LENGTH”的值。

图 2 g_app_mem_dump_info和g_bt_mem_dump_info数组

-
上述两点都排查无误后,需要手工执行脚本进行问题定位。
方法如下:
内存DFX功能
概述
内存DFX功能主要用于内存调优分析,主要包括系统内存占用分析、各任务内存占用分析、任务栈使用率分析以及内存泄漏检测。
功能描述
须知: 所有命令在执行时均会关中断,因此可能导致消息队列满等异常,建议尽量避免在压测场景下使用“AT^SHOWALLTSKHEAP 、AT^SHOWMEMINFO”指令,这两个指令均可以用其他指令组合后替代。
查询指定任务内存占用情况
-
使用任意串口工具下发“AT^SHOWTSKHEAP=<taskId>”命令,taskId的获取请参见“查询任务信息”,以IPOP工具为例,如图1所示。

-
命令下发后可以得到四个信息。
①当前任务占用内存的详细信息,size表示一个内存节点的大小,blockCount表示已分配的内存块数量,callerRA表示该内存节点申请时的下一条指令地址。
②当前任务占用的非slab内存总量。
③当前任务占用的slab内存总量。
④当前系统中因为内存节点申请而带来的总内存开销。
具体内容如图2所示。

查询当前所有任务内存占用情况
-
使用任意串口工具下发“AT^SHOWALLTSKHEAP”命令,以IPOP工具为例,如图1所示。

-
命令下发后可以得到当前系统内所有任务的四个信息。
①当前任务占用内存的详细信息,size表示一个内存节点的大小,blockCount表示已分配的内存块数量,callerRA表示该内存节点申请时的下一条指令地址。
②当前任务占用的非slab内存总量。
③当前任务占用的slab内存总量。
④当前系统中因为内存节点申请而带来的总内存开销。
具内容如图2所示。

查询当前所有空闲内存信息
-
使用任意串口工具下发“AT^SHOWMEMFREE”命令,以IPOP工具为例,如图1所示。

-
命令下发后可以得到当前系统空闲内存的四个信息:
①size:空闲内存块的大小。
②from:该空闲块的起始地址。
③end:该空闲块的结束地址。
④当前总内存剩余量。
具体内容如图2所示。

查询当前内存统计信息
-
使用任意串口工具下发“AT^SHOWHEAPST”命令,以IPOP工具为例,如图1所示。

-
命令下发后可以得到三类信息:
①当前内存的使用信息,total表示内存的总量,used表示当前已使用的内存量,current free表示当前剩余内存量,peak usage表示峰值内存使用量,peak free表示峰值内存剩余量。
②当前所有任务内存分配信息,current malloc表示截止统计时任务依旧持有的内存量,peak malloc表示截止统计时任务所持有内存的最大值。
③非任务所占用的内存,比如中断等。
具体内容如图2所示。

查询内存的所有信息
-
使用任意串口工具下发“AT^SHOWMEMINFO”命令,以IPOP工具为例,如图1所示。

-
该命令执行结果包含“ATSHOWTSKWTL、ATSHOWHEAPST、ATSHOWALLTSKHEAP、ATSHOWMEMFREE”四个命令的执行结果,详情请参考各命令执行结果。
查询任务信息
查询任务水线
-
使用任意串口工具下发“AT^SHOWTSKWTL”命令,以IPOP工具为例,如图1 所示。

-
命令执行结果包含所有任务的任务栈分配情况如图2所示。
参数说明如下:
stackTop:任务栈初始化时的栈顶;
stackLen:任务栈大小;
peakUsage:峰值任务栈使用量;
sp:当前任务栈栈顶;
peakRatio:任务栈峰值使用率。

DebugKits 工具使用
DebugKits使用说明
DIAG 大部分维测功能都需要配合 DebugKits 使用。下面介绍连接、数据库更新、日志查看和命令执行等常用操作,完整功能参见《DebugKits工具 使用指南》。
-
进入工具页面,单击“Options”再选择“Change Chip”,在弹框中选择芯片类型,如图1所示。

-
单击“Connection”选择“Connect”在弹窗中选择连接方式以及对应的通道序号进行连接,如图2所示。

-
更新数据库。如果是第一次连接芯片或者芯片有新版本的程序,需要更新HDB并重新连接之后,日志的打印才能正确的显示,在Option菜单下选择“Update HDB”,选择生成的database目录(output\3322\database_evb)再单击“OK”即可完成配置,具体如图3所示。

-
消息界面。单击菜单栏或工具栏上的命令行图标,可打开消息界面查看日志。
图 4 打开消息界面

图 5 查看日志

-
命令行界面。单击菜单栏或工具栏上的命令行图标,可打开命令行界面。
图 6 打开命令行界面

图 7 命令输入

问题处理与注意事项
注意事项
- DIAG 日志宏当前仅支持日志 ID
0,可变参数最多 10 个;优化日志参数使用不超过 32 位的数值类型,避免字符串、浮点数、long或 64 位参数。 - 固件、
database_evb与 DebugKits 连接必须来自同一轮构建,否则日志可能无法解码。 - 自定义命令必须检查
diag_cmd_id.h、芯片命令 ID 头文件与mss_cmd_db.xml,不要把某个 ID 区间视为可直接复用范围。 - 离线日志和 CHR 的可用容量受功能配置与存储布局影响,应按当前目标配置和工具实际显示结果评估。
- 死机、Last Dump、内存 DFX 的采集和解析遵循对应章节中的固件、数据库与工具版本要求。
问题处理
| 现象 | 原因与处理 |
|---|---|
*_C 未声明 |
日志文件 ID 未登记到所选模块的 log_def_*.h。登记枚举项后重新构建。 |
| 新增的 DFX 日志代码未进入固件 | 确认承载代码的业务组件已进入当前目标的组件列表,并检查组件的源文件列表、日志模块和文件 ID 配置。 |
diag_log.h 或 app_init.h 找不到 |
保持原生样例 CMake 的头文件配置,并使用 SDK 标准构建入口。 |
| DebugKits 只显示消息 ID | 更新与当前固件同一次构建生成的 database_evb,重新连接设备。 |
| 自定义命令不可见或返回异常 | 同时检查命令注册、命令 ID、mss_cmd_db.xml 和数据库更新。 |
问题反馈
反馈 DFX 问题时,建议提供芯片型号、目标名称、固件版本、DebugKits 版本、匹配的 database_evb、复现步骤和相关日志。





