2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2014 Angus Gratton <gus@projectgus.com>
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 2 of the License, or
9 ## (at your option) any later version.
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ## GNU General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, see <http://www.gnu.org/licenses/>.
20 import sigrokdecode as srd
32 - 'AP_WRITE' (AP write)
33 - 'DP_WRITE' (DP write)
34 - 'LINE_RESET' (line reset sequence)
37 - tuple of address, ack state, data for the given sequence
41 'IDLE', # Idle/unknown
42 'REQUEST', # Request phase (first 8 bits)
43 'ACK', # Ack phase (next 3 bits)
44 'READ', # Reading phase (next 32 bits for reads)
45 'WRITE', # Writing phase (next 32 bits for write)
46 'DPARITY', # Data parity phase
49 # Regexes for matching SWD data out of bitstring ('1' / '0' characters) format
50 RE_SWDSWITCH = re.compile(bin(0xE79E)[:1:-1] + '$')
51 RE_SWDREQ = re.compile(r'1(?P<apdp>.)(?P<rw>.)(?P<addr>..)(?P<parity>.)01$')
52 RE_IDLE = re.compile('0' * 50 + '$')
59 ADDR_DP_CTRLSTAT = 0x4
61 BIT_SELECT_CTRLSEL = 1
62 BIT_CTRLSTAT_ORUNDETECT = 1
64 ANNOTATIONS = ['reset', 'enable', 'read', 'write', 'ack', 'data', 'parity']
66 class Decoder(srd.Decoder):
70 longname = 'Serial Wire Debug'
71 desc = 'Two-wire protocol for debug access to ARM CPUs.'
75 tags = ['Debug/trace']
77 {'id': 'swclk', 'name': 'SWCLK', 'desc': 'Master clock'},
78 {'id': 'swdio', 'name': 'SWDIO', 'desc': 'Data input/output'},
81 {'id': 'strict_start',
82 'desc': 'Wait for a line reset before starting to decode',
83 'default': 'no', 'values': ('yes', 'no')},
99 # SWD data/clock state
100 self.state = 'UNKNOWN'
101 self.sample_edge = RISING
102 self.ack = None # Ack state of the current phase
103 self.ss_req = 0 # Start sample of current req
104 self.turnaround = 0 # Number of turnaround edges to ignore before continuing
105 self.bits = '' # Bits from SWDIO are accumulated here, matched against expected sequences
106 self.samplenums = [] # Sample numbers that correspond to the samples in self.bits
107 self.linereset_count = 0
109 # SWD debug port state
112 self.rw = None # Are we inside an SWD read or a write?
113 self.ctrlsel = 0 # 'ctrlsel' is bit 0 in the SELECT register.
114 self.orundetect = 0 # 'orundetect' is bit 0 in the CTRLSTAT register.
117 self.out_ann = self.register(srd.OUTPUT_ANN)
118 self.out_python = self.register(srd.OUTPUT_PYTHON)
119 if self.options['strict_start'] == 'no':
120 self.state = 'REQ' # No need to wait for a LINE RESET.
122 def putx(self, ann, length, data):
123 '''Output annotated data.'''
124 ann = ANNOTATIONS.index(ann)
126 ss = self.samplenums[-length]
128 ss = self.samplenums[0]
129 if self.state == 'REQ':
132 self.put(ss, es, self.out_ann, [ann, [data]])
134 def putp(self, ptype, pdata):
135 self.put(self.ss_req, self.samplenum, self.out_python, [ptype, pdata])
137 def put_python_data(self):
138 '''Emit Python data item based on current SWD packet contents.'''
140 ('AP', 'R'): 'AP_READ',
141 ('AP', 'W'): 'AP_WRITE',
142 ('DP', 'R'): 'DP_READ',
143 ('DP', 'W'): 'DP_WRITE',
144 }[(self.apdp, self.rw)]
145 self.putp(ptype, (self.addr, self.data, self.ack))
149 # Wait for any clock edge.
150 clk, dio = self.wait({0: 'e'})
152 # Count rising edges with DIO held high,
153 # as a line reset (50+ high edges) can happen from any state.
156 self.linereset_count += 1
158 if self.linereset_count >= 50:
159 self.putx('reset', self.linereset_count, 'LINERESET')
160 self.putp('LINE_RESET', None)
162 self.linereset_count = 0
164 # Otherwise, we only care about either rising or falling edges
165 # (depending on sample_edge, set according to current state).
166 if clk != self.sample_edge:
169 # Turnaround bits get skipped.
170 if self.turnaround > 0:
174 self.bits += str(dio)
175 self.samplenums.append(self.samplenum)
177 'UNKNOWN': self.handle_unknown_edge,
178 'REQ': self.handle_req_edge,
179 'ACK': self.handle_ack_edge,
180 'DATA': self.handle_data_edge,
181 'DPARITY': self.handle_dparity_edge,
184 def next_state(self):
185 '''Step to the next SWD state, reset internal counters accordingly.'''
188 self.linereset_count = 0
189 if self.state == 'UNKNOWN':
191 self.sample_edge = RISING
193 elif self.state == 'REQ':
195 self.sample_edge = FALLING
197 elif self.state == 'ACK':
199 self.sample_edge = RISING if self.rw == 'W' else FALLING
200 self.turnaround = 0 if self.rw == 'R' else 2
201 elif self.state == 'DATA':
202 self.state = 'DPARITY'
203 elif self.state == 'DPARITY':
204 self.put_python_data()
206 self.sample_edge = RISING
207 self.turnaround = 1 if self.rw == 'R' else 0
209 def reset_state(self):
210 '''Line reset (or equivalent), wait for a new pending SWD request.'''
211 if self.state != 'REQ': # Emit a Python data item.
212 self.put_python_data()
216 self.linereset_count = 0
218 self.sample_edge = RISING
223 def handle_unknown_edge(self):
225 Clock edge in the UNKNOWN state.
226 In the unknown state, clock edges get ignored until we see a line
227 reset (which is detected in the decode method, not here.)
231 def handle_req_edge(self):
232 '''Clock edge in the REQ state (waiting for SWD r/w request).'''
233 # Check for a JTAG->SWD enable sequence.
234 m = re.search(RE_SWDSWITCH, self.bits)
236 self.putx('enable', 16, 'JTAG->SWD')
240 # Or a valid SWD Request packet.
241 m = re.search(RE_SWDREQ, self.bits)
243 calc_parity = sum([int(x) for x in m.group('rw') + m.group('apdp') + m.group('addr')]) % 2
244 parity = '' if str(calc_parity) == m.group('parity') else 'E'
245 self.rw = 'R' if m.group('rw') == '1' else 'W'
246 self.apdp = 'AP' if m.group('apdp') == '1' else 'DP'
247 self.addr = int(m.group('addr')[::-1], 2) << 2
248 self.putx('read' if self.rw == 'R' else 'write', 8, self.get_address_description())
252 def handle_ack_edge(self):
253 '''Clock edge in the ACK state (waiting for complete ACK sequence).'''
254 if len(self.bits) < 3:
256 if self.bits == '100':
257 self.putx('ack', 3, 'OK')
260 elif self.bits == '001':
261 self.putx('ack', 3, 'FAULT')
263 if self.orundetect == 1:
268 elif self.bits == '010':
269 self.putx('ack', 3, 'WAIT')
271 if self.orundetect == 1:
276 elif self.bits == '111':
277 self.putx('ack', 3, 'NOREPLY')
281 self.putx('ack', 3, 'ERROR')
285 def handle_data_edge(self):
286 '''Clock edge in the DATA state (waiting for 32 bits to clock past).'''
287 if len(self.bits) < 32:
292 if self.bits[x] == '1':
293 self.data += (1 << x)
295 self.dparity = self.dparity % 2
297 self.putx('data', 32, '0x%08x' % self.data)
300 def handle_dparity_edge(self):
301 '''Clock edge in the DPARITY state (clocking in parity bit).'''
302 if str(self.dparity) != self.bits:
303 self.putx('parity', 1, str(self.dparity) + self.bits) # PARITY ERROR
305 self.handle_completed_write()
308 def handle_completed_write(self):
310 Update internal state of the debug port based on a completed
313 if self.apdp != 'DP':
315 elif self.addr == ADDR_DP_SELECT:
316 self.ctrlsel = self.data & BIT_SELECT_CTRLSEL
317 elif self.addr == ADDR_DP_CTRLSTAT and self.ctrlsel == 0:
318 self.orundetect = self.data & BIT_CTRLSTAT_ORUNDETECT
320 def get_address_description(self):
322 Return a human-readable description of the currently selected address,
323 for annotated results.
325 if self.apdp == 'DP':
327 # Tables 2-4 & 2-5 in ADIv5.2 spec ARM document IHI 0031C
330 0x4: 'R CTRL/STAT' if self.ctrlsel == 0 else 'R DLCR',
335 # Tables 2-4 & 2-5 in ADIv5.2 spec ARM document IHI 0031C
338 0x4: 'W CTRL/STAT' if self.ctrlsel == 0 else 'W DLCR',
342 elif self.apdp == 'AP':
344 return 'R AP%x' % self.addr
346 return 'W AP%x' % self.addr
348 # Any legitimate operations shouldn't fall through to here, probably
350 return '? %s%s%x' % (self.rw, self.apdp, self.addr)