Lauterbach调试器
前言
劳特巴赫的Trace分为三种:
- snoop:非严格意义Trace,只能不断的打断程序运行进行采样
- onchip Trace:把跟踪数据放到芯片内部空间,大多数只有1K~2MB空间
- offchip Trace:跟踪数据放在lauterbach硬件Trace设备里,比如PowerTrace
本文主要记录一下第三种方式。
一、Trace介绍
lauterbach官网上介绍的比较好,摘抄过来看一下:
1️⃣为什么需要Trace实时追踪?:
传统的调试就像在汽车飞驰而过时拍摄汽车比赛的快照:你会错过比赛中发生的大部分情况。
基于跟踪的调试就像访问汽车的车载遥测技术、赛道条件和驾驶员的动作。每个动作及其时间都被记录下来。
PowerTrace扩展提供的程序流数据可以准确地告诉你哪些指令被执行了,以及执行这些指令用了多长时间。通过使用实时跟踪,你可以:
- 找到只在运行时发生的难以发现的错误。
- 分析目标代码的性能。
- 确保符合所有的时间要求。
- 创建用于认证的代码覆盖率报告。
2️⃣跟踪能做什么?:
首先Trace能够记录程序流:
其次能够记录数据流:
ppt来源:Trace32 线上培训资料下载
3️⃣用到的设备:
- TC397开发板(必须带有ED芯片)
- PowerDebug X50
- PowerTrace III
连接方式如下:
二、代码覆盖率测试
基于跟踪(Trace)的代码覆盖率统计与分析
1️⃣ 配置过程
先配置一下trace
- METHOD中的Analyzer是OffChip的Trace,如果不插PowerTrace模块这里是灰色的
- state中选择OFF后,勾选autoArm即可自动开始追踪数据
- 勾选AutoIni后,每次记录都会清一下buff
- size不知道填多少可以直接填个0,表示使用最大存储(不明白为什么只能用3G?)
配置一下COVerage
覆盖率测试使用的是Cov选项
2️⃣启动覆盖率测试
先点启动再点停止,即可记录一段跟踪数据(我只记录了一点点,因为录时间太长分析会很慢)
点击+ADD后等待一段时间
3️⃣结果展示
三、CTS上下文回溯调试
1️⃣ 程序运行时序
部分代码如下所示:
#include "Ifx_Ssw_Infra.h"
#include "IFX_Os.h"
#include "Mcu.h"
#include "Port.h"
#include "Dio.h"
#include "Stm.h"
#include "Irq.h"
#include "IfxSrc_reg.h"
/*Core0 Stm0 10ms Counter*/
uint32 Core0_10msTaskCnt = 0;
uint32 main_cnt;
volatile uint32 test;
volatile uint32 fun3cnt = 0;
volatile uint32 fun2cnt = 0;
volatile uint32 fun1cnt = 0;
/*a Call-back function after the elapse of 10ms*/
void Cpu0_10msTask(void)
{
Core0_10msTaskCnt++;
Dio_FlipChannel(DioConf_DioChannel_Dio_12_00);
/*Whether the timer upto 1 second*/
if(Core0_10msTaskCnt>=100)
{
Dio_FlipChannel(DioConf_DioChannel_Dio_33_04);
Dio_FlipChannel(DioConf_DioChannel_Dio_12_01);
Core0_10msTaskCnt = 0;
}
}
void fun1()
{
fun1cnt++;
for(int i=0;i<100;i++)
{
test++;
}
Dio_FlipChannel(DioConf_DioChannel_Dio_33_05);
}
void fun2()
{
fun2cnt++;
for(int i=0;i<100;i++)
{
test++;
}
Dio_FlipChannel(DioConf_DioChannel_Dio_33_06);
}
void fun3()
{
fun3cnt++;
for(int i=0;i<100;i++)
{
test++;
}
Dio_FlipChannel(DioConf_DioChannel_Dio_33_07);
}
void core0_main (void)
{
volatile unsigned short LoopFlag = 1U;
unsigned short cpuWdtPassword;
unsigned short safetyWdtPassword;
ENABLE();
/*
* !!WATCHDOG0 AND SAFETY WATCHDOG ARE DISABLED HERE!!
* Enable the watchdog in the demo if it is required and also service the watchdog periodically
* */
cpuWdtPassword = Ifx_Ssw_getCpuWatchdogPassword(&MODULE_SCU.WDTCPU[0]);
safetyWdtPassword = Ifx_Ssw_getSafetyWatchdogPassword();
Ifx_Ssw_disableCpuWatchdog(&MODULE_SCU.WDTCPU[0], cpuWdtPassword);
Ifx_Ssw_disableSafetyWatchdog(safetyWdtPassword);
/*Initializes Mcu Module*/
Mcu_Init(&Mcu_Config);
/*Initializes Clock*/
Mcu_InitClock(0);
while(Mcu_GetPllStatus()!=MCU_PLL_LOCKED);
Mcu_DistributePllClock();
/*Initializes Port Module*/
Port_Init(&Port_Config);
/*Enable Stm Module 0*/
Stm_EnableModule(0);
/*provides service to invoke a Call-back function after the elapse of 10ms*/
Stm_EnableAlarm(0,0,1,1000000,Cpu0_10msTask);
/*Enable Stm Interrupt*/
IrqStm_Init();
SRC_STM0SR0.B.SRE = 1;
while (LoopFlag == 1U)
{
main_cnt++;
fun1();
fun2();
fun3();
}
}
观察函数运行时序:
2️⃣ CTS上下文回溯
可以看到和之前调试的界面不太一样了
可以向前,向后运行程序了。
四、CPU负载分析
可以看到某个函数占用了多少CPU负载。
五、数据流分析
只能抓一点点,不知道为什么
总结
后面再完善