DWT(Data Watchpoint And Trace Unit),是 ARM Cortex M 系列内核(ARM
Cortex-M V7(K1 M4F, K3, M7))提供的数据监测点和跟踪单元,以支持数据断点
功能。
。CYCCNT 是一个 32BIT 的 UP
计数器,记录内核时钟的运行个数,内核时钟跳动一次,改计数器就加 1,对
K3X4 内核时钟最高 160M,每个时钟节拍周期是 6.25ns,最长能记录 26.84S。
要实现时间测量功能,总共涉及到三个寄存器,DEMCR, DWT_CTRL,
DWT_CYCCNT,分别用于开启 DWT 功能,开启 CYCCNT 及获得系统时钟计数
值。关于这三个寄存器更详细的说明,请参考”Armv7-M Architecture
Ref
- 修改在S32K3xx【xx是型号】.mac 文件(该文件是 PE Micro 调试工具下的一个脚本文件)
在该
脚本里可以执行一些寄存器的初始化,该脚本在 CPU Core 运行起来之前由调
试器加载,解释,并执行)开启 DWT,和 CYCCNT 并清空 CYCNT。
REM Enable DWT CYCCNT:
mm.1 $E000EDFC $010007F0
mm.1 $E0001000 $40000001
mm.1 $E0001004 $00000000
delay 20
注意:在这里我找不到实际调用的文件,所以我在main.c直接往地址写入了。
(*(volatile uint32*)0xE000EDFC) =0x010007F0; (*(volatile uint32*)0xE0001000) =0x40000001; (*(volatile uint32*)0xE0001004) =0x00000000;
- 在 Expressions 窗口添加 DWT_CTRL 和 DWT_CYCCNT 寄存器
利用脚本文件进行hardfault问题定位
set language c
define armex
printf "EXEC_RETURN (LR):\n",
info registers $lr
if (((unsigned int)$lr & 0x04) == 0x4)
printf "Uses PSP 0x%x return.\n",$psp
set $armex_base = (unsigned int)$psp
else
printf "Uses MSP 0x%x return.\n", $msp
set $armex_base =(unsigned int)$msp
end
printf "xPSR 0x%x\n",*($armex_base+28)
printf "ReturnAddress 0x%x\n",*($armex_base+24)
printf "LR(R14) 0x%x\n",*($armex_base+20)
printf "R12 0x%x\n",*($armex_base+16)
printf "R3 0x%x\n",*($armex_base+12)
printf "R2 0x%x\n",*($armex_base+8)
printf "R1 0x%x\n",*($armex_base+4)
printf "R0 0x%x\n",*($armex_base)
printf "Return instruction:\n"
x/i *($armex_base +24)
printf "LR instruction:\n"
x/i *($armex_base+20)
end
document armex
ARMv7 Exception entry bebavior.
xPSR, ReturnAddress,LR,R12,R14,R3,R2,R1,and R0
end
在 Window->Preferences->GDB 配置.gdbinit 脚本路径
HardFault 产生后,在 Debugger Console 窗口输入自定义的 armex 命令,可以
看到之前手工分析的栈数据回溯被自动的解析出来。根据这些信息可以看到,
代码执行到 0x0040196b 后执行了非法地址 0xe000000 访问导致了 HardFault.
查看堆栈信息定位hardfault问题
Cortex-M MCU 在接收到
一个异常后,芯片硬件会自动将 8 个通用寄存器(依次为 R0~R3, R12, LR, PC,
xPSR)压入到当前栈空间。Cortex-M MCU 有两个栈 MSP 主栈和 PSP 线程
栈。异常发生后 LR 会被更新为异常返回时需要用到的特殊值
EXC_RETURN,其中 BIT2 指示了当前用到的栈是 MSP 还是 PSP。了解到了
异常时 MCU 寄存器保存情况,我们就很容易找到发生异常时的指令地址即
PC
(注:S32DS 的 Registers 窗口只能看到 MSP,看不到 PSP), 如图根据 SP:
0x2042efc0,可以看到异常产生后保存在 MSP 栈上的 8 个通用寄存器的值,
PC:0xe000000, 异常时的 PC,该地址是一个非法的地址。LR:
0x0040196b,异常返回地址,根据这些信息可以看到,代码执行到
0x0040196b 后执行了非法地址 0xe000000 访问导致了 HardFault