BES(恒玄)平台log分析

前言 

    恒玄软件调试和分析基本是通过日志形式分析的,今天就详细说下日志组成和常用分析方法

1.日志组成解析

        bes日志组成一般说由以下组成:tick时钟 +模块+log打印所在线程编码+log内容

[17:31:22.834]     21786/NONE   /  2 | CPU USAGE: busy=18 light=82 sys_deep=0 chip_deep=0
[17:31:23.089]     22058/M_SBC  /  4 | PLC_bad_frame, HEADER_ERROR
[17:31:24.402]     23450/RT_OS  /  3 | feed watchdog

比如上面的log  这个没有加设备状态的打印 首先打印的是芯片上电开始的tick时钟 然后是模块单元,后面是执行log的线程编号 最后是log输出的内容。原型是这样的 

后续TWS发展 加了设备模块的状态  格式就变成了 

tick时钟 +设备状态+日志等级+模块+log打印所在线程编码+log内容

[10:17:22:130]   132744/R-M/I/NONE  / 17 | [anc_fadeout_impl] OK
[10:17:22:130]   132744/R-M/I/NONE  / 17 | [app_anc_switch_coef] mode_old: 4, mode_new: 1
[10:17:22:130]   132744/R-M/I/NONE  / 17 | anc_set_cfg:0x1
[10:17:22:130]   132744/R-M/I/NONE  / 17 | anc_set_cfg:iir0_type|iir1_type:0x1
[10:17:22:169]   132745/R-M/I/NONE  / 17 | anc_set_cfg_internal: ff_offset_r=0...
[10:17:22:169]   132745/R-M/I/NONE  / 17 | ana: set anc adc gain: type=1
[10:17:22:169]   132745/R-M/I/NONE  / 17 | anc_set_cfg_internal: ANC_FEEDFORWARD
[10:17:22:169]   132745/R-M/I/NONE  / 17 | anc_set_cfg_internal: ANC_FF ch_L...
[10:17:22:169]   132745/R-M/I/NONE  / 17 | anc_set_cfg:0x4
[10:17:22:169]   132745/R-M/I/NONE  / 17 | [app_anc_reset_gain] type:1, gain_l:0, gain_r:0
[10:17:22:169]   132745/R-M/I/NONE  / 17 | anc_set_gain anc_type:2, gain_ch_l:0,gain_ch_r:0

分析:先打印的还是时间轴 +设备(左/右-主/从)+log等级+模块+调用线程编号+log内容

设备块的打印可以通过 宏定义管理“TRACE_GLOBAL_TAG” ,TRACE_GLOBAL_TAG =1 log的输出形式就是上图的形式了 

        1.1 tick 

                        -----体现芯片上电运行时间 下面的log如果不借助电脑时间轴打印请问时间差是多少呢 ?答案是大约2.14s 

现在我们看下电脑的结果 是不是完全匹配的 

    所以 从tick的分析 可以看到log是否连续  (复位重启会重置)是否丢失log,在没有电脑时间的时候也能初略判断事件发生的时间差(计算方式(tick1-tick1)/1000

       1.2. 设备状态

         -----  这个是TWS 耳机区分日志引入的打印变量

     U--未知 状态  L--左  R--右   M--主  S--从 

       1.3.日志等级

      ---- 'C', 'E', 'W', 'N', 'I', 'D', 'V', '-' 对应

     1.4.模块

           -----这个部分的组成比较灵活  一般是根据功能块划分的 

          比如我自己写的一个mic声音幅度判断函数里面加个打印 这样的话我只要搜索MUTE_C  全部的信息就都出来了 其实就是为了方便查找

TR_INFO(TR_MOD(MUTE_C), "agv:%d,residual:%d  #least:", app_interphone_mute_frame_dat.val_frame_agv,
app_interphone_mute_frame_dat.enery_diff_residual);
DUMP32("%d ", app_interphone_mute_frame_dat.enery_measure, PCM_AUDIO_CNT);

  打印运行结果:

121092/MUTE_C/4/ agv:1843,residual:2828265 #least:193875 282826 316619 261641 353510

1.5 打印线程

     ----这个通常用来查询SDK 或者其他人代码用的  比如封装库了 或者你不知道源码的情况下 大概能推测log出现的位置

比如上图出现的 log PLC_bad_frame 属于线程ID 为4打印发出  feed watchdog 属于线程ID3 发出

下面从log截图追溯下打印的线程验证是否匹配

从代码查阅 确实是属于 audio_flinger 线程执行的处理

这个打印需要修改下代码  在RTOS 底层文件 把函数替换下以下代码即可

static void _rtx_show_thread_usage(const os_thread_t *thread, uint32_t sample_time)
{if (thread) {if (thread->thread_addr && thread->stack_mem) {uint32_t min_free_stack_sz = rtx_thread_get_stack_space(thread);REL_TRACE_NOTS(4,"---Thread name=%s id:%d cpu=%d  min-free-stack=%d",thread->name==NULL ? "null" : (char *)thread->name,thread->id,sample_time != 0 ? ((thread->rtime - thread->step_rtime) * 100 / sample_time) : 0,min_free_stack_sz);print_thread_sw_statitics(thread);((os_thread_t *)thread)->step_rtime = thread->rtime;} else {REL_TRACE_NOTS(0,"--- Thread BAD");}} else {REL_TRACE_NOTS(0,"--- Thread NONE");}
}

2.log源代码分析:

 2.1 通常情况下为了方便都是用的 "TRACE",翻译的中文为“跟踪/追溯”

比ru

TRACE(3,"app_interphone_captrue_audio work:%d op:%d freq:26M", captrue_isRun, on);

为了区分模块 统一处理  可以加一些自定义字符 :

值得注意的是需要在 hal_trace_mod.h里面添加 要不然会编译出错 

简而言之 log是一个分析工具 尽量做到规范和便捷 就好 

2.2 代码分析常规 log打印流程

     ----- 最后的log都是通过这个函数执行的 因为不同线程可能存在打印log 所以有一个list缓存 打印也是单线执行的 

除log本身之外的 tick+设备状态+模块+优先级+线程ID 这些其实都在这函数处理的 "hal_trace_print_time" 

2.3 非常规的一些log打印 

   ----- 这些包含了dump 的数据  或者死机日志打印接口

dump其实就是转化为数据输出 不会包含上面介绍的前半轴 比如常见的HCI log 

死机日志分为两种 但是最后都会走“hal_trace_crash_end” 这个函数

2.3.1 ---hal_trace_fault_handler 空指针 总线执行错误 堆栈溢出等

2.3.1 ---hal_trace_assert_dump 非法数据 或者操作设置强制死机

死机后可以设置为快速重启 

详细的死机原因分析其实代码里面也比较明确 “hal_trace_print_fault_info_cm”

3.死机日志追寻

        3.1 arm寄存器

        Cortex-A处理器的寄存器结构,包括40个32位寄存器中的通用寄存器、状态寄存器如CPSR和SPSR,以及堆栈指针R13、链接寄存器R14和程序寄存器R15.(不是很理解的请百度下冯诺依曼架构)

通用寄存器 R0~R7

  • R0-R3一般作为参数传递,如果参数再多,则通过压栈的方式传递

  • R0、R1还会作为返回值进行传递,如果是32位则是R0,64位则会用R0-R1

  • 通用目的寄存器R8-R12

    ,高组寄存器,32bit,较少的16位thumb指令可以访问,一般是 thumb-2指令访问。

  • R11一般用作FP指针,保存栈帧

  • R12 临时寄存器 

寄存器描述
未分组寄存器R0-R7
分组寄存器R8-R14
程序寄存器PCR15
程序状态保存寄存器SPSR


堆栈指针R13(SP)
链接寄存器R14(LR)
程序寄存器R15(PC)
CPSR 当前程序状态寄存器
可以在任何运行模式下被访问

SPSR 备份的程序状态寄存器
当异常发生时,SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复CPSR

3.2 分析文件 

    ---- list 文件 或者 elf文件

    elf 文件会直接在编译工程文件生成

     list  由代码编译后加 lst 生成 如:

 

lst直接在lst文件里面找相应的执行处理函数 

如下面的死机log 

elf 则借助wsl 工具 输入 "arm-none-eabi-addr2line -apsfCe  xx.elf  指针地址 1 2 3 4"

从而找到或者推测出死机的函数和执行处

上面的死机打印IPSR =000 说明不是中断函数 PC是当前指针地址 为 00200DA8 

在bes 地址中 :C开头的是flash地址 2开头是 内存地址  说明是内存地址访问错误导致的死机

4.常用log相关宏定义

CRASH_REBOOT 用于死机重启 需要关闭 CORE_DUMP CONTROLLER_DUMP_ENABLE

TRACE_GLOBAL_TAG 设备定义管理  

TRACE_BUF_SIZE  log缓冲区大小 出现 “loss”时候可能就是缓存不足

TRACE_BAUD_RATE log串口输出波特率 

TRACE_PRINTF_LEN  单帧打印长度 默认120  如果出现打印不完整 可能就是长度不够,需要注意的是 hal_trace.c  和hal_uart.c 里面都要改

5. 总结 

log作为一个分析工具  能够精准分析和熟练使用是 学习bes 平台必不可少的 只有多练习和实践才能更快的定位问题 解决问题 

   今天的解说就到这里 有啥不到之处 敬请指出 谢谢 ! 



 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/394900.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebStorm格式化JSON,将一行很长的JSON展开

webstorm json格式化插件将一行很长的json展开 在WebStorm中,要展开很长的JSON行,可以使用内置的JSON格式化功能。 打开WebStorm,并打开包含JSON的文件。 选择JSON文件中的任意部分。 按下快捷键 CtrlAltL (Windows/Linux) 或 CmdAltL (Ma…

GPT-4.o mini

https://share.xuzhugpt.cloud/ GPT-4.o mini 目前免费使用 把上面[chatgpt4o-mini-xuzhu]复制到UserToken的文本框中 点击[个人账户] 测试一下哈,看看: GPT-4.o代码有时候还是有严重错误:好奇怎么来的 上面是我写得,下面是GPT写…

01背包问题 c++

题目描述 有一个背包能装的重量maxw(正整数,0≤maxw≤20000),同时有n件物品(0≤n≤100)(每件物品只有一件,要么拿,要么不拿),每件物品有一个重量wi(正整数)和一个价值vi(正整数)。要求从这n件物品中任取若干件装入背包…

C++ 简单学习

C简单编译 auto关键字 auto 关键字用于自动类型推导。它允许编译器自动推断变量的类型,使得代码更加简洁和易于编写,尤其是在处理复杂类型或模板编程时。使用 auto 可以避免编写冗长的类型声明,同时减少由于类型不匹配导致的编译错误 auto x…

论文阅读报告: 在时间双向图上查询基于时间的的密集子图 | ICDE 2024

摘要 本文提出了一个新的模型(α, β, T)-core,用于在时间双向图上寻找凝聚子图。时间双向图中,不同实体之间的关系随着时间的推移而变化。为了提高查询效率,本文提出了顶点分区和时间分区的历史索引(VH-I…

Java学习Day24:基础篇14:多线程

1.程序、进程和线程 程序 进程 进程(process)是程序的一次执行过程,或是一个正在执行的程序。是一个动态的过程:有它自身的产 生、存在和消亡的过程。 如: 运行中的QQ运行中的音乐播放器视频播放器等;程序是静态的&#xff0c…

【大模型从入门到精通13】openAI API 构建和评估大型语言模型(LLM)应用1

这里写目录标题 构建和评估大型语言模型(LLM)应用开发性能评估指标从开发到部署高风险应用LLM应用开发的最佳实践和建议从小处着手快速迭代自动化测试根据应用需求定制评估考虑伦理影响 构建和评估大型语言模型(LLM)应用 开发和部…

Sqli-labs-master靶场--布尔盲注

目录 1、布尔盲注 2、布尔盲注的流程(以靶场less-8为例) 2.1输入id尝试是否存在注入点 2.1.1通过以上尝试,联想到可能是布尔盲注 2.2猜测数据库长度 2.3获取数据库名 2.3.1python脚本获取 代码: 获取结果为: …

Hive SQL ——窗口函数源码阅读

前言 使用Starrocks引擎中的窗口函数 row_number() over( )对10亿的数据集进行去重操作,BE内存溢出问题频发(忘记当时指定的BE内存上限是多少了.....),此时才意识到,开窗操作,如果使用 不当,反而…

1. js混淆-源码乱码

目录 调试干扰参数逆向 调试干扰 打开开发者工具,首先会进入 setInterval 生成的 debugger 将 uzt.js uyt.js 内容替换 将这两个文件的内容置空,并刷新页面就可以正常调试了 参数逆向 点击翻页,可以发现 https://match.yuanrenxue.cn/api…

Arduino导入实例程序的过程,实例包文件却编译显示缺失文件

参考中实例程序中的readme.txt 导入方式 下面是文档中的使用方式 1.基本信息: 本例程是基于Arduino进行开发的,例程均在E-Paper ESP8266 Driver Board上进行了验证;2.基本使用:方法1:将整个esp8266-waveshare-epd文件夹复制到C…

【Go】通过反射解析对象tag信息,实现简易ORM

反射是运行时,需要在运行时解析类型信息,编译期无法优化这些操作,因此比编译时已知类型信息的直接调用效率要低。 package mainimport ("fmt""reflect""strings" )type Person struct {Name string json:&quo…

PicGo + gitee 免费搭建个人图床

目录 1 图床概念2 使用gitee和PicGo搭建图床流程2.1 下载安装PicGo工具 3 图片上传错误处理3.1 PicGo客户端提示404错误信息图片上传失败3.2 PicGo客户端提示400错误信息图片上传失败 1 图床概念 ​ "图床"是一个网络术语,它指的是一种用于存储和托管图片…

理解张量拼接(torch.cat)

拼接 维度顺序:对于 3D 张量,通常可以理解为 (深度, 行, 列) 或 (批次, 行, 列)。 选择一个dim进行拼接的时候其他两个维度大小要相等 对于三维张量,理解 torch.cat 的 dim 参数确实变得更加抽象,但原理是相同的。让我们通过一…

算法力扣刷题记录 六十九【动态规划基础及509. 斐波那契数】

前言 调整一下做题顺序,多个章节同步进行,穿插练习。可以在各章节的专栏中找同一类。 记录 六十九【动态规划基础】。 一、动态规划理论基础学习 参考学习链接 二、509. 斐波那契数 2.1 题目阅读 斐波那契数 (通常用 F(n) 表示&#x…

html+css+js网页设计 中国移动5个页面(带js)

htmlcssjs网页设计 中国移动5个页面(带js) 网页作品代码简单,可使用任意HTML编辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xf…

Cpp中的this指针--复习记录

1.什么是this指针? 每个类都有一个this指针,我们的非静态成员函数可以通过这个this指针来操作对象的成员属性。this指针存储的就是类的实例的地址,this指针时时刻刻指向的都是这个实例对象本身。 由下图可知: 我在主函数中栈上创建了一个类的实例(由操…

【Python-实操】LabelMe to YOLOv8 Converter

LabelMe to YOLOv8 Converter 这是一个 Python 脚本,用于将 LabelMe 标注工具导出的 JSON 文件转换为 YOLOv8 格式的标注文件,并同时在图像上绘制标注的多边形。 功能 读取 LabelMe JSON 文件。解码并显示图像。从 classes.txt 文件加载类别标签。将多…

Java | Leetcode Java题解之第327题区间和的个数

题目&#xff1a; 题解&#xff1a; class Solution {public int countRangeSum(int[] nums, int lower, int upper) {long sum 0;long[] preSum new long[nums.length 1];for (int i 0; i < nums.length; i) {sum nums[i];preSum[i 1] sum;}BalancedTree treap ne…

Java参数传递

Java参数传递 一、 方法重载 一个类中可以存在多个同名的方法&#xff0c;只要这些方法的参数列表不同即可。 参数列表不同&#xff1a;参数个数或者参数类型不同方法重载与修饰符、返回值类型等统统无关&#xff0c;只看参数列表 二、 可变个数的形参 从Java5.0开始&…