Skip to content

Commit f0f3d10

Browse files
committed
WIP. Adding a CMSIS-DAP debug interface.
This is being used with the NXP MIMXRT1020-EVK.
1 parent 4b7ecbe commit f0f3d10

File tree

6 files changed

+345
-75
lines changed

6 files changed

+345
-75
lines changed

dap.py

+213
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
#------------------------------------------------------------------------------
2+
"""
3+
4+
CMSIS-DAP Driver
5+
6+
"""
7+
#------------------------------------------------------------------------------
8+
9+
#import struct
10+
#from array import array as Array
11+
12+
import usbdev
13+
#import cortexm
14+
#import iobuf
15+
16+
#------------------------------------------------------------------------------
17+
# supported devices
18+
19+
dap_devices = (
20+
(0x0d28, 0x0204, 1), # NXP MIMXRT1020-EVK
21+
)
22+
23+
def itf_lookup(vid, pid):
24+
"""return the interface to use for a given device"""
25+
for (v, p, i) in dap_devices:
26+
if (v == vid) and (p == pid):
27+
return i
28+
return None
29+
30+
def find(vps=None, sn=None):
31+
"""find an cmsis-dap device based on vid, pid and serial number"""
32+
if vps is None:
33+
# look for any dap device
34+
vps = [(vid, pid) for (vid, pid, itf) in dap_devices]
35+
return usbdev.find(vps, sn)
36+
37+
38+
#------------------------------------------------------------------------------
39+
# map register names to cmsis-dap register numbers
40+
41+
regmap = {
42+
'r0':0, 'r1':1, 'r2':2, 'r3':3, 'r4':4, 'r5':5, 'r6':6, 'r7':7,
43+
'r8':8, 'r9':9, 'r10':10, 'r11':11, 'r12':12, 'r13':13, 'r14':14, 'r15':15,
44+
'lr':14, 'pc':15, 'psr':16, 'msp':17, 'psp':18,
45+
# primask
46+
# faultmask
47+
# basepri
48+
# control
49+
# 19 ?
50+
# 20 ?
51+
}
52+
53+
#------------------------------------------------------------------------------
54+
55+
class dap:
56+
"""CMSIS-DAP Device Driver"""
57+
58+
def __init__(self, vid, pid, sn):
59+
self.vid = vid
60+
self.pid = pid
61+
self.sn = sn
62+
itf = itf_lookup(self.vid, self.pid)
63+
self.usb = usbdev.usbdev()
64+
self.usb.open(self.vid, self.pid, interface=itf, serial=self.sn)
65+
66+
def __del__(self):
67+
if self.usb is not None:
68+
self.close()
69+
70+
def close(self):
71+
"""close the usb interface"""
72+
self.usb.close()
73+
self.usb = None
74+
75+
def rd_reg(self, n):
76+
"""read from a register"""
77+
# TODO
78+
return 0
79+
80+
def wr_reg(self, n, val):
81+
"""write to a register"""
82+
# TODO
83+
84+
def rd_mem8(self, adr, n):
85+
"""read n 8-bit values from memory region"""
86+
# TODO
87+
return [0 for i in range(n)]
88+
89+
def rd_mem16(self, adr, n):
90+
"""read n 16-bit values from memory region"""
91+
assert adr & 1 == 0
92+
# TODO
93+
return [0 for i in range(n)]
94+
95+
def rd_mem32(self, adr, n):
96+
"""read n 32-bit values from memory region"""
97+
assert adr & 3 == 0
98+
# TODO
99+
return [0 for i in range(n)]
100+
101+
def __str__(self):
102+
"""return a string for basic device description"""
103+
s = []
104+
s.append('CMSIS-DAP usb %04x:%04x serial %r' % (self.vid, self.pid, self.sn))
105+
#s.append('target voltage %.3fV' % (float(self.get_voltage()) / 1000.0))
106+
return '\n'.join(s)
107+
108+
#------------------------------------------------------------------------------
109+
110+
class dbgio:
111+
"""CMSIS-DAP implementation of dbgio cpu interface"""
112+
113+
def __init__(self, vid=None, pid=None, idx=None, sn=None):
114+
"""no actual operations, record the selected usb device"""
115+
self.vid = vid
116+
self.pid = pid
117+
self.idx = idx
118+
self.sn = sn
119+
self.cpu_name = None
120+
self.itf = None
121+
self.menu = (
122+
('info', self.cmd_info),
123+
)
124+
125+
def connect(self, cpu_name, itf):
126+
"""connect the debugger to the target"""
127+
self.cpu_name = cpu_name
128+
self.dbg_itf = itf
129+
self.dap = dap(self.vid, self.pid, self.sn)
130+
131+
def disconnect(self):
132+
"""disconnect the debugger from the target"""
133+
self.dap.close()
134+
135+
def cmd_info(self, ui, args):
136+
"""display cmsis-dap information"""
137+
ui.put('%s\n' % self)
138+
139+
def is_halted(self):
140+
"""return True if target is halted"""
141+
# TODO
142+
return True
143+
144+
def rdreg(self, reg):
145+
"""read from the named register"""
146+
n = regmap.get(reg, None)
147+
if n is None:
148+
return None
149+
return self.dap.rd_reg(n)
150+
151+
def wrreg(self, reg, val):
152+
"""write to the named register"""
153+
n = regmap.get(reg, None)
154+
if n is None:
155+
return
156+
self.dap.wr_reg(n, val)
157+
158+
def rdmem32(self, adr, n, io):
159+
"""read n 32-bit words from memory starting at adr"""
160+
max_n = 0x20
161+
while n > 0:
162+
nread = (n, max_n)[n >= max_n]
163+
_ = [io.wr32(x) for x in self.dap.rd_mem32(adr, nread)]
164+
n -= nread
165+
adr += nread * 4
166+
167+
def rdmem16(self, adr, n, io):
168+
"""read n 16-bit words from memory starting at adr"""
169+
max_n = 0x20
170+
while n > 0:
171+
nread = (n, max_n)[n >= max_n]
172+
_ = [io.wr16(x) for x in self.dap.rd_mem16(adr, nread)]
173+
n -= nread
174+
adr += nread * 2
175+
176+
def rdmem8(self, adr, n, io):
177+
"""read n 8-bit words from memory starting at adr"""
178+
# n = 0..0x3c (ok), 0x3d..0x40 (slow), >= 0x41 (fails)
179+
max_n = 0x20
180+
while n > 0:
181+
nread = (n, max_n)[n >= max_n]
182+
_ = [io.wr8(x) for x in self.dap.rd_mem8(adr, nread)]
183+
n -= nread
184+
adr += nread
185+
186+
def rdmem(self, adr, n, io):
187+
"""read a buffer from memory starting at adr"""
188+
if io.has_wr(32):
189+
self.rdmem32(adr, n, io)
190+
elif io.has_wr(16):
191+
self.rdmem16(adr, n, io)
192+
elif io.has_wr(8):
193+
self.rdmem8(adr, n, io)
194+
else:
195+
assert False, 'bad buffer width'
196+
197+
def rd32(self, adr):
198+
"""read 32 bit value from adr"""
199+
return self.dap.rd_mem32(adr, 1)[0]
200+
201+
def rd16(self, adr):
202+
"""read 16 bit value from adr"""
203+
return self.dap.rd_mem16(adr, 1)[0]
204+
205+
def rd8(self, adr):
206+
"""read 8 bit value from adr"""
207+
return self.dap.rd_mem8(adr, 1)[0]
208+
209+
def __str__(self):
210+
return str(self.dap)
211+
212+
213+
#------------------------------------------------------------------------------

pycs

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import util
1616

1717
import jlink
1818
import stlink
19+
import dap
1920

2021
# -----------------------------------------------------------------------------
2122

@@ -138,6 +139,10 @@ def get_dbgio(target):
138139
(dev, _) = stlink.find()
139140
assert dev is not None
140141
return stlink.dbgio(vid=dev[0], pid=dev[1], sn=dev[2])
142+
elif itf['name'] == 'cmsis-dap':
143+
(dev, _) = dap.find()
144+
assert dev is not None
145+
return dap.dbgio(vid=dev[0], pid=dev[1], sn=dev[2])
141146
else:
142147
return None
143148

stlink.py

+43-43
Original file line numberDiff line numberDiff line change
@@ -50,48 +50,48 @@ def find(vps=None, sn=None):
5050
#------------------------------------------------------------------------------
5151
# stlink protocol constants
5252

53-
STLINK_GET_VERSION = 0xF1
54-
STLINK_DEBUG_COMMAND = 0xF2
55-
STLINK_DFU_COMMAND = 0xF3
56-
STLINK_SWIM_COMMAND = 0xF4
57-
STLINK_GET_CURRENT_MODE = 0xF5
53+
STLINK_GET_VERSION = 0xF1
54+
STLINK_DEBUG_COMMAND = 0xF2
55+
STLINK_DFU_COMMAND = 0xF3
56+
STLINK_SWIM_COMMAND = 0xF4
57+
STLINK_GET_CURRENT_MODE = 0xF5
5858
STLINK_GET_TARGET_VOLTAGE = 0xF7
5959

6060
# STLINK_DEBUG_COMMAND + ...
61-
STLINK_DEBUG_ENTER_JTAG = 0x00
62-
STLINK_DEBUG_GETSTATUS = 0x01
63-
STLINK_DEBUG_FORCEDEBUG = 0x02
64-
STLINK_DEBUG_APIV1_RESETSYS = 0x03
65-
STLINK_DEBUG_APIV1_READALLREGS = 0x04
66-
STLINK_DEBUG_APIV1_READREG = 0x05
67-
STLINK_DEBUG_APIV1_WRITEREG = 0x06
68-
STLINK_DEBUG_READMEM_32BIT = 0x07
69-
STLINK_DEBUG_WRITEMEM_32BIT = 0x08
70-
STLINK_DEBUG_RUNCORE = 0x09
71-
STLINK_DEBUG_STEPCORE = 0x0a
72-
STLINK_DEBUG_APIV1_SETFP = 0x0b
73-
STLINK_DEBUG_READMEM_8BIT = 0x0c
74-
STLINK_DEBUG_WRITEMEM_8BIT = 0x0d
75-
STLINK_DEBUG_APIV1_CLEARFP = 0x0e
76-
STLINK_DEBUG_APIV1_WRITEDEBUGREG = 0x0f
77-
STLINK_DEBUG_APIV1_SETWATCHPOINT = 0x10
78-
STLINK_DEBUG_APIV1_ENTER = 0x20
79-
STLINK_DEBUG_EXIT = 0x21
80-
STLINK_DEBUG_READCOREID = 0x22
81-
STLINK_DEBUG_APIV2_ENTER = 0x30
82-
STLINK_DEBUG_APIV2_READ_IDCODES = 0x31
83-
STLINK_DEBUG_APIV2_RESETSYS = 0x32
84-
STLINK_DEBUG_APIV2_READREG = 0x33
85-
STLINK_DEBUG_APIV2_WRITEREG = 0x34
86-
STLINK_DEBUG_APIV2_WRITEDEBUGREG = 0x35
87-
STLINK_DEBUG_APIV2_READDEBUGREG = 0x36
88-
STLINK_DEBUG_APIV2_READALLREGS = 0x3A
61+
STLINK_DEBUG_ENTER_JTAG = 0x00
62+
STLINK_DEBUG_GETSTATUS = 0x01
63+
STLINK_DEBUG_FORCEDEBUG = 0x02
64+
STLINK_DEBUG_APIV1_RESETSYS = 0x03
65+
STLINK_DEBUG_APIV1_READALLREGS = 0x04
66+
STLINK_DEBUG_APIV1_READREG = 0x05
67+
STLINK_DEBUG_APIV1_WRITEREG = 0x06
68+
STLINK_DEBUG_READMEM_32BIT = 0x07
69+
STLINK_DEBUG_WRITEMEM_32BIT = 0x08
70+
STLINK_DEBUG_RUNCORE = 0x09
71+
STLINK_DEBUG_STEPCORE = 0x0a
72+
STLINK_DEBUG_APIV1_SETFP = 0x0b
73+
STLINK_DEBUG_READMEM_8BIT = 0x0c
74+
STLINK_DEBUG_WRITEMEM_8BIT = 0x0d
75+
STLINK_DEBUG_APIV1_CLEARFP = 0x0e
76+
STLINK_DEBUG_APIV1_WRITEDEBUGREG = 0x0f
77+
STLINK_DEBUG_APIV1_SETWATCHPOINT = 0x10
78+
STLINK_DEBUG_APIV1_ENTER = 0x20
79+
STLINK_DEBUG_EXIT = 0x21
80+
STLINK_DEBUG_READCOREID = 0x22
81+
STLINK_DEBUG_APIV2_ENTER = 0x30
82+
STLINK_DEBUG_APIV2_READ_IDCODES = 0x31
83+
STLINK_DEBUG_APIV2_RESETSYS = 0x32
84+
STLINK_DEBUG_APIV2_READREG = 0x33
85+
STLINK_DEBUG_APIV2_WRITEREG = 0x34
86+
STLINK_DEBUG_APIV2_WRITEDEBUGREG = 0x35
87+
STLINK_DEBUG_APIV2_READDEBUGREG = 0x36
88+
STLINK_DEBUG_APIV2_READALLREGS = 0x3A
8989
STLINK_DEBUG_APIV2_GETLASTRWSTATUS = 0x3B
90-
STLINK_DEBUG_APIV2_DRIVE_NRST = 0x3C
91-
STLINK_DEBUG_APIV2_START_TRACE_RX = 0x40
92-
STLINK_DEBUG_APIV2_STOP_TRACE_RX = 0x41
93-
STLINK_DEBUG_APIV2_GET_TRACE_NB = 0x42
94-
STLINK_DEBUG_APIV2_SWD_SET_FREQ = 0x43
90+
STLINK_DEBUG_APIV2_DRIVE_NRST = 0x3C
91+
STLINK_DEBUG_APIV2_START_TRACE_RX = 0x40
92+
STLINK_DEBUG_APIV2_STOP_TRACE_RX = 0x41
93+
STLINK_DEBUG_APIV2_GET_TRACE_NB = 0x42
94+
STLINK_DEBUG_APIV2_SWD_SET_FREQ = 0x43
9595

9696
# STLINK_DEBUG_COMMAND + STLINK_DEBUG_APIVx_ENTER + ...
9797
STLINK_DEBUG_ENTER_JTAG = 0x00
@@ -106,7 +106,7 @@ def find(vps=None, sn=None):
106106

107107
# api v1 core state
108108
STLINK_CORE_RUNNING = 0x80
109-
STLINK_CORE_HALTED = 0x81
109+
STLINK_CORE_HALTED = 0x81
110110

111111
#------------------------------------------------------------------------------
112112
# map register names to stlink register numbers
@@ -139,7 +139,7 @@ def read_u32(x):
139139

140140
#------------------------------------------------------------------------------
141141

142-
class stlink(object):
142+
class stlink:
143143
"""ST-Link Device Driver"""
144144

145145
def __init__(self, vid, pid, sn):
@@ -360,7 +360,7 @@ def __str__(self):
360360

361361
#------------------------------------------------------------------------------
362362

363-
class dbgio(object):
363+
class dbgio:
364364
"""ST-Link implementation of dbgio cpu interface"""
365365

366366
def __init__(self, vid=None, pid=None, idx=None, sn=None):
@@ -434,7 +434,7 @@ def rdmem32(self, adr, n, io):
434434
# avoid reads that are a multiple of 16 x 32-bit, they are slow
435435
if nread & 15 == 0:
436436
nread -= 1
437-
[io.wr32(x) for x in self.stlink.rd_mem32(adr, nread)]
437+
_ = [io.wr32(x) for x in self.stlink.rd_mem32(adr, nread)]
438438
n -= nread
439439
adr += nread * 4
440440

@@ -452,7 +452,7 @@ def rdmem8(self, adr, n, io):
452452
max_n = 0x3c
453453
while n > 0:
454454
nread = (n, max_n)[n >= max_n]
455-
[io.wr8(x) for x in self.stlink.rd_mem8(adr, nread)]
455+
_ = [io.wr8(x) for x in self.stlink.rd_mem8(adr, nread)]
456456
n -= nread
457457
adr += nread
458458

0 commit comments

Comments
 (0)