Mercurial > lcfOS
comparison python/utils/stlink.py @ 292:534b94b40aa8
Fixup reorganize
author | Windel Bouwman |
---|---|
date | Wed, 27 Nov 2013 08:06:42 +0100 |
parents | python/stlink.py@c694ec551f34 |
children |
comparison
equal
deleted
inserted
replaced
290:7b38782ed496 | 292:534b94b40aa8 |
---|---|
1 import struct, time | |
2 from usb import UsbContext, UsbDevice | |
3 from devices import Interface, STLinkException, registerInterface | |
4 import adi | |
5 | |
6 """ | |
7 More or less copied from: | |
8 https://github.com/texane/stlink | |
9 Tracing from: | |
10 https://github.com/obe1line/stlink-trace | |
11 | |
12 """ | |
13 ST_VID, STLINK2_PID = 0x0483, 0x3748 | |
14 | |
15 def checkDevice(device): | |
16 return device.VendorId == ST_VID and device.ProductId == STLINK2_PID | |
17 | |
18 DFU_MODE, MASS_MODE, DEBUG_MODE = 0, 1, 2 | |
19 | |
20 CORE_RUNNING = 0x80 | |
21 CORE_HALTED = 0x81 | |
22 | |
23 # Commands: | |
24 GET_VERSION = 0xf1 | |
25 DEBUG_COMMAND = 0xf2 | |
26 DFU_COMMAND = 0xf3 | |
27 GET_CURRENT_MODE = 0xf5 | |
28 | |
29 # dfu commands: | |
30 DFU_EXIT = 0x7 | |
31 | |
32 # debug commands: | |
33 DEBUG_ENTER = 0x20 | |
34 DEBUG_EXIT = 0x21 | |
35 DEBUG_ENTER_SWD = 0xa3 | |
36 DEBUG_GETSTATUS = 0x01 | |
37 DEBUG_FORCEDEBUG = 0x02 | |
38 DEBUG_RESETSYS = 0x03 | |
39 DEBUG_READALLREGS = 0x04 | |
40 DEBUG_READREG = 0x5 | |
41 DEBUG_WRITEREG = 0x6 | |
42 DEBUG_READMEM_32BIT = 0x7 | |
43 DEBUG_WRITEMEM_32BIT = 0x8 | |
44 DEBUG_RUNCORE = 0x9 | |
45 DEBUG_STEPCORE = 0xa | |
46 | |
47 JTAG_WRITEDEBUG_32BIT = 0x35 | |
48 JTAG_READDEBUG_32BIT = 0x36 | |
49 TRACE_GET_BYTE_COUNT = 0x42 | |
50 | |
51 # cortex M3 | |
52 CM3_REG_CPUID = 0xE000ED00 | |
53 | |
54 @registerInterface((ST_VID, STLINK2_PID)) | |
55 class STLink2(Interface): | |
56 """ STlink2 interface implementation. """ | |
57 def __init__(self, stlink2=None): | |
58 self.devHandle = None | |
59 if not stlink2: | |
60 context = UsbContext() | |
61 stlink2s = list(filter(checkDevice, context.DeviceList)) | |
62 if not stlink2s: | |
63 raise STLinkException('Could not find an ST link 2 interface') | |
64 if len(stlink2s) > 1: | |
65 print('More then one stlink2 found, picking first one') | |
66 stlink2 = stlink2s[0] | |
67 assert isinstance(stlink2, UsbDevice) # Nifty type checking | |
68 assert checkDevice(stlink2) | |
69 self.stlink2 = stlink2 | |
70 def __del__(self): | |
71 if self.IsOpen: | |
72 if self.CurrentMode == DEBUG_MODE: | |
73 self.exitDebugMode() | |
74 self.close() | |
75 def __str__(self): | |
76 if self.IsOpen: | |
77 return 'STlink2 device version {0}'.format(self.Version) | |
78 else: | |
79 return 'STlink2 device' | |
80 def open(self): | |
81 if self.IsOpen: | |
82 return | |
83 self.devHandle = self.stlink2.open() | |
84 if self.devHandle.Configuration != 1: | |
85 self.devHandle.Configuration = 1 | |
86 self.devHandle.claimInterface(0) | |
87 | |
88 # First initialization: | |
89 if self.CurrentMode == DFU_MODE: | |
90 self.exitDfuMode() | |
91 if self.CurrentMode != DEBUG_MODE: | |
92 self.enterSwdMode() | |
93 #self.reset() | |
94 def close(self): | |
95 if self.IsOpen: | |
96 self.devHandle.close() | |
97 self.devHandle = None | |
98 @property | |
99 def IsOpen(self): | |
100 return self.devHandle != None | |
101 # modes: | |
102 def getCurrentMode(self): | |
103 cmd = bytearray(16) | |
104 cmd[0] = GET_CURRENT_MODE | |
105 reply = self.send_recv(cmd, 2) # Expect 2 bytes back | |
106 return reply[0] | |
107 CurrentMode = property(getCurrentMode) | |
108 @property | |
109 def CurrentModeString(self): | |
110 modes = {DFU_MODE: 'dfu', MASS_MODE: 'massmode', DEBUG_MODE:'debug'} | |
111 return modes[self.CurrentMode] | |
112 def exitDfuMode(self): | |
113 cmd = bytearray(16) | |
114 cmd[0:2] = DFU_COMMAND, DFU_EXIT | |
115 self.send_recv(cmd) | |
116 def enterSwdMode(self): | |
117 cmd = bytearray(16) | |
118 cmd[0:3] = DEBUG_COMMAND, DEBUG_ENTER, DEBUG_ENTER_SWD | |
119 self.send_recv(cmd) | |
120 def exitDebugMode(self): | |
121 cmd = bytearray(16) | |
122 cmd[0:2] = DEBUG_COMMAND, DEBUG_EXIT | |
123 self.send_recv(cmd) | |
124 | |
125 def getVersion(self): | |
126 cmd = bytearray(16) | |
127 cmd[0] = GET_VERSION | |
128 data = self.send_recv(cmd, 6) # Expect 6 bytes back | |
129 # Parse 6 bytes into various versions: | |
130 b0, b1, b2, b3, b4, b5 = data | |
131 stlink_v = b0 >> 4 | |
132 jtag_v = ((b0 & 0xf) << 2) | (b1 >> 6) | |
133 swim_v = b1 & 0x3f | |
134 vid = (b3 << 8) | b2 | |
135 pid = (b5 << 8) | b4 | |
136 return 'stlink={0} jtag={1} swim={2} vid:pid={3:04X}:{4:04X}'.format(\ | |
137 stlink_v, jtag_v, swim_v, vid, pid) | |
138 Version = property(getVersion) | |
139 | |
140 @property | |
141 def ChipId(self): | |
142 return self.read_debug32(0xE0042000) | |
143 @property | |
144 def CpuId(self): | |
145 u32 = self.read_debug32(CM3_REG_CPUID) | |
146 implementer_id = (u32 >> 24) & 0x7f | |
147 variant = (u32 >> 20) & 0xf | |
148 part = (u32 >> 4) & 0xfff | |
149 revision = u32 & 0xf | |
150 return implementer_id, variant, part, revision | |
151 def getStatus(self): | |
152 cmd = bytearray(16) | |
153 cmd[0:2] = DEBUG_COMMAND, DEBUG_GETSTATUS | |
154 reply = self.send_recv(cmd, 2) | |
155 return reply[0] | |
156 Status = property(getStatus) | |
157 @property | |
158 def StatusString(self): | |
159 s = self.Status | |
160 statii = {CORE_RUNNING: 'CORE RUNNING', CORE_HALTED: 'CORE HALTED'} | |
161 if s in statii: | |
162 return statii[s] | |
163 return 'Unknown status' | |
164 | |
165 def reset(self): | |
166 cmd = bytearray(16) | |
167 cmd[0:2] = DEBUG_COMMAND, DEBUG_RESETSYS | |
168 self.send_recv(cmd, 2) | |
169 | |
170 # debug commands: | |
171 def step(self): | |
172 cmd = bytearray(16) | |
173 cmd[0:2] = DEBUG_COMMAND, DEBUG_STEPCORE | |
174 self.send_recv(cmd, 2) | |
175 def run(self): | |
176 cmd = bytearray(16) | |
177 cmd[0:2] = DEBUG_COMMAND, DEBUG_RUNCORE | |
178 self.send_recv(cmd, 2) | |
179 def halt(self): | |
180 cmd = bytearray(16) | |
181 cmd[0:2] = DEBUG_COMMAND, DEBUG_FORCEDEBUG | |
182 self.send_recv(cmd, 2) | |
183 | |
184 # Tracing: | |
185 def traceEnable(self): | |
186 self.write_debug32(0xE000EDF0, 0xA05F0003) | |
187 | |
188 # Enable TRCENA: | |
189 DEMCR = 0xE000EDFC | |
190 v = self.read_debug32(DEMCR) | |
191 v |= (1 << 24) | |
192 self.write_debug32(DEMCR, v) | |
193 | |
194 # ?? Enable write?? | |
195 self.write_debug32(0xE0002000, 0x2) # | |
196 | |
197 # DBGMCU_CR: | |
198 self.write_debug32(0xE0042004, 0x27) # Enable trace in async mode | |
199 | |
200 # TPIU config: | |
201 self.write_debug32(0xE0040004, 0x00000001) # current port size register --> 1 == port size = 1 | |
202 self.write_debug32(0xE0040010, 0x23) # random clock divider?? | |
203 self.write_debug32(0xE00400F0, 0x2) # selected pin protocol (2 == NRZ) | |
204 self.write_debug32(0xE0040304, 0x100) # continuous formatting | |
205 | |
206 # ITM config: | |
207 self.write_debug32(0xE0000FB0, 0xC5ACCE55) # Unlock write access to ITM | |
208 self.write_debug32(0xE0000F80, 0x00010005) # ITM Enable, sync enable, ATB=1 | |
209 self.write_debug32(0xE0000E00, 0xFFFFFFFF) # Enable all trace ports in ITM | |
210 self.write_debug32(0xE0000E40, 0x0000000F) # Set privilege mask for all 32 ports. | |
211 def writePort0(self, v32): | |
212 self.write_debug32(0xE0000000, v32) | |
213 def getTraceByteCount(self): | |
214 cmd = bytearray(16) | |
215 cmd[0:2] = DEBUG_COMMAND, 0x42 | |
216 reply = self.send_recv(cmd, 2) | |
217 return struct.unpack('<H', reply[0:2])[0] | |
218 def readTraceData(self): | |
219 bsize = self.getTraceByteCount() | |
220 if bsize > 0: | |
221 td = self.recv_ep3(bsize) | |
222 print(td) | |
223 else: | |
224 print('no trace data') | |
225 | |
226 # Helper 1 functions: | |
227 def write_debug32(self, address, value): | |
228 cmd = bytearray(16) | |
229 cmd[0:2] = DEBUG_COMMAND, JTAG_WRITEDEBUG_32BIT | |
230 cmd[2:10] = struct.pack('<II', address, value) | |
231 r = self.send_recv(cmd, 2) | |
232 def read_debug32(self, address): | |
233 cmd = bytearray(16) | |
234 cmd[0:2] = DEBUG_COMMAND, JTAG_READDEBUG_32BIT | |
235 cmd[2:6] = struct.pack('<I', address) # pack into u32 little endian | |
236 reply = self.send_recv(cmd, 8) | |
237 return struct.unpack('<I', reply[4:8])[0] | |
238 def write_reg(self, reg, value): | |
239 cmd = bytearray(16) | |
240 cmd[0:3] = DEBUG_COMMAND, DEBUG_WRITEREG, reg | |
241 cmd[3:7] = struct.pack('<I', value) | |
242 r = self.send_recv(cmd, 2) | |
243 def read_reg(self, reg): | |
244 cmd = bytearray(16) | |
245 cmd[0:3] = DEBUG_COMMAND, DEBUG_READREG, reg | |
246 reply = self.send_recv(cmd, 4) | |
247 return struct.unpack('<I', reply)[0] | |
248 def read_all_regs(self): | |
249 cmd = bytearray(16) | |
250 cmd[0:2] = DEBUG_COMMAND, DEBUG_READALLREGS | |
251 reply = self.send_recv(cmd, 84) | |
252 fmt = '<' + 'I' * 21 # unpack 21 register values | |
253 return list(struct.unpack(fmt, reply)) | |
254 def write_mem32(self, address, content): | |
255 assert len(content) % 4 == 0 | |
256 cmd = bytearray(16) | |
257 cmd[0:2] = DEBUG_COMMAND, DEBUG_WRITEMEM_32BIT | |
258 cmd[2:8] = struct.pack('<IH', address, len(content)) | |
259 self.send_recv(cmd) | |
260 self.send_recv(content) | |
261 def read_mem32(self, address, length): | |
262 assert length % 4 == 0 | |
263 cmd = bytearray(16) | |
264 cmd[0:2] = DEBUG_COMMAND, DEBUG_READMEM_32BIT | |
265 cmd[2:8] = struct.pack('<IH', address, length) | |
266 reply = self.send_recv(cmd, length) # expect memory back! | |
267 return reply | |
268 | |
269 # Helper 2 functions: | |
270 def send_recv(self, tx, rxsize=0): | |
271 """ Helper function that transmits and receives data in bulk mode. """ | |
272 # TODO: we could use here the non-blocking libusb api. | |
273 tx = bytes(tx) | |
274 #assert len(tx) == 16 | |
275 self.devHandle.bulkWrite(2, tx) # write to endpoint 2 | |
276 if rxsize > 0: | |
277 return self.devHandle.bulkRead(1, rxsize) # read from endpoint 1 | |
278 def recv_ep3(self, rxsize): | |
279 return self.devHandle.bulkRead(3, rxsize) | |
280 | |
281 if __name__ == '__main__': | |
282 # Test program | |
283 sl = STLink2() | |
284 sl.open() | |
285 sl.reset() | |
286 print('version:', sl.Version) | |
287 print('mode before doing anything:', sl.CurrentModeString) | |
288 if sl.CurrentMode == DFU_MODE: | |
289 sl.exitDfuMode() | |
290 sl.enterSwdMode() | |
291 print('mode after entering swd mode:', sl.CurrentModeString) | |
292 | |
293 i = sl.ChipId | |
294 print('chip id: 0x{0:X}'.format(i)) | |
295 print('cpu: {0}'.format(sl.CpuId)) | |
296 | |
297 print('status: {0}'.format(sl.StatusString)) | |
298 | |
299 # test registers: | |
300 sl.write_reg(0, 0xdeadbeef) | |
301 sl.write_reg(1, 0xcafebabe) | |
302 sl.write_reg(2, 0xc0ffee) | |
303 sl.write_reg(3, 0x1337) | |
304 sl.write_reg(5, 0x1332) | |
305 sl.write_reg(6, 0x12345) | |
306 assert sl.read_reg(3) == 0x1337 | |
307 assert sl.read_reg(5) == 0x1332 | |
308 assert sl.read_reg(6) == 0x12345 | |
309 regs = sl.read_all_regs() | |
310 for i in range(len(regs)): | |
311 print('R{0}=0x{1:X}'.format(i, regs[i])) | |
312 | |
313 print('tracing') | |
314 sl.traceEnable() | |
315 sl.run() | |
316 sl.writePort0(0x1337) # For test | |
317 time.sleep(0.1) | |
318 td = sl.readTraceData() | |
319 print('trace data:', td) | |
320 | |
321 # Test CoreSight registers: | |
322 idr4 = sl.read_debug32(0xE0041fd0) | |
323 print('idr4 =', idr4) | |
324 | |
325 print('== ADI ==') | |
326 a = adi.Adi(sl) | |
327 a.parseRomTable(0xE00FF000) # why is rom table at 0xE00FF000? | |
328 print('== ADI ==') | |
329 | |
330 # Detect ROM table: | |
331 id4 = sl.read_debug32(0xE00FFFD0) | |
332 id5 = sl.read_debug32(0xE00FFFD4) | |
333 id6 = sl.read_debug32(0xE00FFFD8) | |
334 id7 = sl.read_debug32(0xE00FFFDC) | |
335 id0 = sl.read_debug32(0xE00FFFE0) | |
336 id1 = sl.read_debug32(0xE00FFFE4) | |
337 id2 = sl.read_debug32(0xE00FFFE8) | |
338 id3 = sl.read_debug32(0xE00FFFEC) | |
339 pIDs = [id0, id1, id2, id3, id4, id5, id6, id7] | |
340 print(pIDs) | |
341 | |
342 print('reading from 0xE00FF000') | |
343 scs = sl.read_debug32(0xE00FF000) | |
344 print('scs {0:08X}'.format(scs)) | |
345 dwt = sl.read_debug32(0xE00FF004) | |
346 print('dwt {0:08X}'.format(dwt)) | |
347 fpb = sl.read_debug32(0xE00FF008) | |
348 print('fpb {0:08X}'.format(fpb)) | |
349 itm = sl.read_debug32(0xE00FF00C) | |
350 print('itm {0:08X}'.format(itm)) | |
351 tpiu = sl.read_debug32(0xE00FF010) | |
352 print('tpiu {0:08X}'.format(tpiu)) | |
353 etm = sl.read_debug32(0xE00FF014) | |
354 print('etm {0:08X}'.format(etm)) | |
355 assert sl.read_debug32(0xE00FF018) == 0x0 # end marker | |
356 | |
357 devid = sl.read_debug32(0xE0040FC8) | |
358 print('TPIU_DEVID: {0:X}'.format(devid)) | |
359 devtype = sl.read_debug32(0xE0040FCC) | |
360 print('TPIU_TYPEID: {0:X}'.format(devtype)) | |
361 | |
362 sl.exitDebugMode() | |
363 print('mode at end:', sl.CurrentModeString) | |
364 | |
365 sl.close() | |
366 print('Test succes!') | |
367 |