对于一般程序调试,获取通用寄存器的状态是比较重要的一种调试手段,读取这些通用寄存器的状态的前提是CORE必须处于HALT状态,否则这个寄存器的值是一直变化的,我们也就无法获取一个比较准确的值。另外对这些寄存器的值进行修改也需要将CORE HALT。
通过DAP HALT ARM CORE的方式也是访问一系列系统寄存器完成的,这些内核调试寄存器定义如下:
地址 | 类型 | 复位值 | 描述 |
---|---|---|---|
0xE000EDF0 | 读写 | 0x00000000 | 调试停止控制和状态寄存器 |
0xE000EDF4 | 只写 | - | 调试内核寄存器的选择寄存器 |
0xE000EDF8 | 读写 | - | 调试内核寄存器数据寄存器 |
0xE000EDFC | 读写 | 0x00000000 | 调试异常和监控控制寄存器 |
位范围 | R/W | 名称 | 功能 |
---|---|---|---|
[31:16] | W | DEBGKEY | 写操作必须是0xA05F,否则写操作被忽略,读操作返回状态位 |
[25] | R | S_RESET_ST | 自上一次读该位时,系统已经复位或正在复位,读造作清零 |
[24] | R | S_RETIRE_ST | 表示自上一次读该位时,已经执行一条指令 |
[19] | R | S_LOCKUP | 系统处于lockup状态 |
[18] | R | S_SLEEP | 系统处于睡眠状态,必须使用C_HALT来获得或者等待中断唤醒内核 |
[5] | R/W | C_SNAPSTALL | 使能停止调试来获得对内核的控制,如果内核正在加载、存储操作,则操作无效,指令强制执行,如果C_DBUGEN=1, C_HALT=1,该位只能置1 |
[3] | R/W | C_MASKINS | 处于调试状态的内核执行单布或运行时屏蔽中断,NMI依然有效 |
[2] | R/W | C_STEP | 对内核进行单步操作,C_DEBUGEN=0时无效,S_HALT=1时仅修改 |
[1] | R/W | C_HALT | 停止内核,内核停止时(比如断点)自动置位,C_DEBUGEN=1时只能写,该位置位时C_DEBUGEN也必须写1 |
[0] | R/W | C_DEBUGEN | 使能调试,只能通过AHP-AP写入,内核不能写 |
位范围 | R/W | 名称 | 功能 |
---|---|---|---|
[16] | W | REGWnR | 写操作为1,读操作为0 |
[4:0] | W | REGSEL | 0000 - R0 ... 1111 - R15 10000 - xPSR/Flags 10001 - MSP 10010 - PSP 10011 - RAZ/WI 10100 - CONTROL/FAULTMASK/BASEPRI/PRIMASK |
0xA05F0003
,该操作会使能调试并停止内核S_HALT
置位,置位表示内核已经停止这个操作用Jlink Command的方式写下来就是下面这个样子:
connect
// select AP[1]
writedp 2 01000000
// halt core
writeap 1 E000EDF0
writeap 3 A05F0003
// set pc
writeap 1 E000EDF8
writeap 3 06000000
writeap 1 E000EDF4
writeap 3 0001000F
// release pc
writeap 1 E000EDF0
writeap 3 A05F0000
这个时候就可以直接写个生成JLink脚本的小脚本,用于直接下载程序了:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import binascii
bin_path = sys.argv[1]
start = """connect
writedp 2 01000000
// halt core
writeap 1 E000EDF0
writeap 3 A05F0003
// write code"""
start_address = 0x06000000
end = """ // set pc
writeap 1 E000EDF8
writeap 3 06000000
writeap 1 E000EDF4
writeap 3 0001000F
// set msp
writeap 1 E000EDF4
writeap 3 00010101
writeap 1 E000EDF8
writeap 3 0602807c
// release pc
writeap 1 E000EDF0
writeap 3 A05F0000"""
print(start)
with open(bin_path, 'rb') as src:
word = src.read(4)
while word != b'':
print("writeap 1 %08x" % start_address)
print("writeap 3 %08x" % int.from_bytes(word, byteorder='little'))
start_address += 4
word = src.read(4)
print(end)