jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / adi_v5_swd.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 *
5 * Copyright (C) 2010 by David Brownell
6 ***************************************************************************/
7
8 /**
9 * @file
10 * Utilities to support ARM "Serial Wire Debug" (SWD), a low pin-count debug
11 * link protocol used in cases where JTAG is not wanted. This is coupled to
12 * recent versions of ARM's "CoreSight" debug framework. This specific code
13 * is a transport level interface, with "target/arm_adi_v5.[hc]" code
14 * understanding operation semantics, shared with the JTAG transport.
15 *
16 * Single DAP and multidrop-SWD support.
17 *
18 * for details, see "ARM IHI 0031A"
19 * ARM Debug Interface v5 Architecture Specification
20 * especially section 5.3 for SWD protocol
21 * and "ARM IHI 0074C" ARM Debug Interface Architecture Specification ADIv6.0
22 *
23 * On many chips (most current Cortex-M3 parts) SWD is a run-time alternative
24 * to JTAG. Boards may support one or both. There are also SWD-only chips,
25 * (using SW-DP not SWJ-DP).
26 *
27 * Even boards that also support JTAG can benefit from SWD support, because
28 * usually there's no way to access the SWO trace view mechanism in JTAG mode.
29 * That is, trace access may require SWD support.
30 *
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "arm.h"
38 #include "arm_adi_v5.h"
39 #include <helper/time_support.h>
40
41 #include <transport/transport.h>
42 #include <jtag/interface.h>
43
44 #include <jtag/swd.h>
45
46 /* for debug, set do_sync to true to force synchronous transfers */
47 static bool do_sync;
48
49 static struct adiv5_dap *swd_multidrop_selected_dap;
50
51 static bool swd_multidrop_in_swd_state;
52
53
54 static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
55 uint32_t data);
56
57
58 static int swd_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq)
59 {
60 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
61 assert(swd);
62
63 return swd->switch_seq(seq);
64 }
65
66 static void swd_finish_read(struct adiv5_dap *dap)
67 {
68 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
69 if (dap->last_read) {
70 swd->read_reg(swd_cmd(true, false, DP_RDBUFF), dap->last_read, 0);
71 dap->last_read = NULL;
72 }
73 }
74
75 static void swd_clear_sticky_errors(struct adiv5_dap *dap)
76 {
77 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
78 assert(swd);
79
80 swd->write_reg(swd_cmd(false, false, DP_ABORT),
81 STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
82 }
83
84 static int swd_run_inner(struct adiv5_dap *dap)
85 {
86 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
87
88 return swd->run();
89 }
90
91 static inline int check_sync(struct adiv5_dap *dap)
92 {
93 return do_sync ? swd_run_inner(dap) : ERROR_OK;
94 }
95
96 /** Select the DP register bank */
97 static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg)
98 {
99 /* Only register address 0 (ADIv6 only) and 4 are banked. */
100 if (is_adiv6(dap) ? (reg & 0xf) > 4 : (reg & 0xf) != 4)
101 return ERROR_OK;
102
103 uint32_t sel = (reg >> 4) & DP_SELECT_DPBANK;
104
105 /* ADIv6 ensures DPBANKSEL = 0 after line reset */
106 if ((dap->select_valid || (is_adiv6(dap) && dap->select_dpbanksel_valid))
107 && (sel == (dap->select & DP_SELECT_DPBANK)))
108 return ERROR_OK;
109
110 /* Use the AP part of dap->select regardless of dap->select_valid:
111 * if !dap->select_valid
112 * dap->select contains a speculative value likely going to be used
113 * in the following swd_queue_ap_bankselect() */
114 sel |= (uint32_t)(dap->select & SELECT_AP_MASK);
115
116 LOG_DEBUG_IO("DP BANK SELECT: %" PRIx32, sel);
117
118 /* dap->select cache gets updated in the following call */
119 return swd_queue_dp_write_inner(dap, DP_SELECT, sel);
120 }
121
122 static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg,
123 uint32_t *data)
124 {
125 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
126 assert(swd);
127
128 int retval = swd_queue_dp_bankselect(dap, reg);
129 if (retval != ERROR_OK)
130 return retval;
131
132 swd->read_reg(swd_cmd(true, false, reg), data, 0);
133
134 return check_sync(dap);
135 }
136
137 static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
138 uint32_t data)
139 {
140 int retval = ERROR_OK;
141 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
142 assert(swd);
143
144 swd_finish_read(dap);
145
146 if (reg == DP_SELECT) {
147 dap->select = data | (dap->select & (0xffffffffull << 32));
148
149 swd->write_reg(swd_cmd(false, false, reg), data, 0);
150
151 retval = check_sync(dap);
152 dap->select_valid = (retval == ERROR_OK);
153 dap->select_dpbanksel_valid = dap->select_valid;
154
155 return retval;
156 }
157
158 if (reg == DP_SELECT1)
159 dap->select = ((uint64_t)data << 32) | (dap->select & 0xffffffffull);
160
161 /* DP_ABORT write is not banked.
162 * Prevent writing DP_SELECT before as it would fail on locked up DP */
163 if (reg != DP_ABORT)
164 retval = swd_queue_dp_bankselect(dap, reg);
165
166 if (retval == ERROR_OK) {
167 swd->write_reg(swd_cmd(false, false, reg), data, 0);
168
169 retval = check_sync(dap);
170 }
171
172 if (reg == DP_SELECT1)
173 dap->select1_valid = (retval == ERROR_OK);
174
175 return retval;
176 }
177
178
179 static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr,
180 uint32_t *dlpidr_ptr, bool clear_sticky)
181 {
182 int retval;
183 uint32_t dpidr, dlpidr;
184
185 assert(dap_is_multidrop(dap));
186
187 /* Send JTAG_TO_DORMANT and DORMANT_TO_SWD just once
188 * and then use shorter LINE_RESET until communication fails */
189 if (!swd_multidrop_in_swd_state) {
190 swd_send_sequence(dap, JTAG_TO_DORMANT);
191 swd_send_sequence(dap, DORMANT_TO_SWD);
192 } else {
193 swd_send_sequence(dap, LINE_RESET);
194 }
195
196 /*
197 * Zero dap->select and set dap->select_dpbanksel_valid
198 * to skip the write to DP_SELECT before DPIDR read, avoiding
199 * the protocol error.
200 * Clear the other validity flags because the rest of the DP
201 * SELECT and SELECT1 registers is unknown after line reset.
202 */
203 dap->select = 0;
204 dap->select_dpbanksel_valid = true;
205 dap->select_valid = false;
206 dap->select1_valid = false;
207
208 retval = swd_queue_dp_write_inner(dap, DP_TARGETSEL, dap->multidrop_targetsel);
209 if (retval != ERROR_OK)
210 return retval;
211
212 retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr);
213 if (retval != ERROR_OK)
214 return retval;
215
216 if (clear_sticky) {
217 /* Clear all sticky errors (including ORUN) */
218 swd_clear_sticky_errors(dap);
219 } else {
220 /* Ideally just clear ORUN flag which is set by reset */
221 retval = swd_queue_dp_write_inner(dap, DP_ABORT, ORUNERRCLR);
222 if (retval != ERROR_OK)
223 return retval;
224 }
225
226 retval = swd_queue_dp_read_inner(dap, DP_DLPIDR, &dlpidr);
227 if (retval != ERROR_OK)
228 return retval;
229
230 retval = swd_run_inner(dap);
231 if (retval != ERROR_OK)
232 return retval;
233
234 if ((dpidr & DP_DPIDR_VERSION_MASK) < (2UL << DP_DPIDR_VERSION_SHIFT)) {
235 LOG_INFO("Read DPIDR 0x%08" PRIx32
236 " has version < 2. A non multidrop capable device connected?",
237 dpidr);
238 return ERROR_FAIL;
239 }
240
241 /* TODO: check TARGETID if DLIPDR is same for more than one DP */
242 uint32_t expected_dlpidr = DP_DLPIDR_PROTVSN |
243 (dap->multidrop_targetsel & DP_TARGETSEL_INSTANCEID_MASK);
244 if (dlpidr != expected_dlpidr) {
245 LOG_INFO("Read incorrect DLPIDR 0x%08" PRIx32
246 " (possibly CTRL/STAT value)",
247 dlpidr);
248 return ERROR_FAIL;
249 }
250
251 LOG_DEBUG_IO("Selected DP_TARGETSEL 0x%08" PRIx32, dap->multidrop_targetsel);
252 swd_multidrop_selected_dap = dap;
253 swd_multidrop_in_swd_state = true;
254
255 if (dpidr_ptr)
256 *dpidr_ptr = dpidr;
257
258 if (dlpidr_ptr)
259 *dlpidr_ptr = dlpidr;
260
261 return retval;
262 }
263
264 static int swd_multidrop_select(struct adiv5_dap *dap)
265 {
266 if (!dap_is_multidrop(dap))
267 return ERROR_OK;
268
269 if (swd_multidrop_selected_dap == dap)
270 return ERROR_OK;
271
272 int retval = ERROR_OK;
273 for (unsigned int retry = 0; ; retry++) {
274 bool clear_sticky = retry > 0;
275
276 retval = swd_multidrop_select_inner(dap, NULL, NULL, clear_sticky);
277 if (retval == ERROR_OK)
278 break;
279
280 swd_multidrop_selected_dap = NULL;
281 if (retry > 3) {
282 LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap));
283 dap->do_reconnect = true;
284 return retval;
285 }
286
287 LOG_DEBUG("Failed to select multidrop %s, retrying...",
288 adiv5_dap_name(dap));
289 }
290
291 dap->do_reconnect = false;
292 return retval;
293 }
294
295 static int swd_connect_multidrop(struct adiv5_dap *dap)
296 {
297 int retval;
298 uint32_t dpidr = 0xdeadbeef;
299 uint32_t dlpidr = 0xdeadbeef;
300 int64_t timeout = timeval_ms() + 500;
301
302 do {
303 /* Do not make any assumptions about SWD state in case of reconnect */
304 if (dap->do_reconnect)
305 swd_multidrop_in_swd_state = false;
306
307 /* Clear link state, including the SELECT cache. */
308 dap->do_reconnect = false;
309 dap_invalidate_cache(dap);
310 swd_multidrop_selected_dap = NULL;
311
312 retval = swd_multidrop_select_inner(dap, &dpidr, &dlpidr, true);
313 if (retval == ERROR_OK)
314 break;
315
316 swd_multidrop_in_swd_state = false;
317 alive_sleep(1);
318
319 } while (timeval_ms() < timeout);
320
321 if (retval != ERROR_OK) {
322 swd_multidrop_selected_dap = NULL;
323 LOG_ERROR("Failed to connect multidrop %s", adiv5_dap_name(dap));
324 return retval;
325 }
326
327 swd_multidrop_in_swd_state = true;
328 LOG_INFO("SWD DPIDR 0x%08" PRIx32 ", DLPIDR 0x%08" PRIx32,
329 dpidr, dlpidr);
330
331 return retval;
332 }
333
334 static int swd_connect_single(struct adiv5_dap *dap)
335 {
336 int retval;
337 uint32_t dpidr = 0xdeadbeef;
338 int64_t timeout = timeval_ms() + 500;
339
340 do {
341 if (dap->switch_through_dormant) {
342 swd_send_sequence(dap, JTAG_TO_DORMANT);
343 swd_send_sequence(dap, DORMANT_TO_SWD);
344 } else {
345 swd_send_sequence(dap, JTAG_TO_SWD);
346 }
347
348 /* Clear link state, including the SELECT cache. */
349 dap->do_reconnect = false;
350 dap_invalidate_cache(dap);
351
352 /* The sequences to enter in SWD (JTAG_TO_SWD and DORMANT_TO_SWD) end
353 * with a SWD line reset sequence (50 clk with SWDIO high).
354 * From ARM IHI 0031F ADIv5.2 and ARM IHI 0074C ADIv6.0,
355 * chapter B4.3.3 "Connection and line reset sequence":
356 * - DPv3 (ADIv6) only: line reset sets DP_SELECT_DPBANK to zero;
357 * - read of DP_DPIDR takes the connection out of reset;
358 * - write of DP_TARGETSEL keeps the connection in reset;
359 * - other accesses return protocol error (SWDIO not driven by target).
360 *
361 * dap_invalidate_cache() sets dap->select to zero and all validity
362 * flags to invalid. Set dap->select_dpbanksel_valid only
363 * to skip the write to DP_SELECT, avoiding the protocol error.
364 * Read DP_DPIDR to get out of reset.
365 */
366 dap->select_dpbanksel_valid = true;
367
368 retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr);
369 if (retval == ERROR_OK) {
370 retval = swd_run_inner(dap);
371 if (retval == ERROR_OK)
372 break;
373 }
374
375 alive_sleep(1);
376
377 dap->switch_through_dormant = !dap->switch_through_dormant;
378 } while (timeval_ms() < timeout);
379
380 if (retval != ERROR_OK) {
381 LOG_ERROR("Error connecting DP: cannot read IDR");
382 return retval;
383 }
384
385 LOG_INFO("SWD DPIDR 0x%08" PRIx32, dpidr);
386
387 do {
388 dap->do_reconnect = false;
389
390 /* force clear all sticky faults */
391 swd_clear_sticky_errors(dap);
392
393 retval = swd_run_inner(dap);
394 if (retval != ERROR_WAIT)
395 break;
396
397 alive_sleep(10);
398
399 } while (timeval_ms() < timeout);
400
401 return retval;
402 }
403
404 static int swd_pre_connect(struct adiv5_dap *dap)
405 {
406 swd_multidrop_in_swd_state = false;
407
408 return ERROR_OK;
409 }
410
411 static int swd_connect(struct adiv5_dap *dap)
412 {
413 int status;
414
415 /* FIXME validate transport config ... is the
416 * configured DAP present (check IDCODE)?
417 */
418
419 /* Check if we should reset srst already when connecting, but not if reconnecting. */
420 if (!dap->do_reconnect) {
421 enum reset_types jtag_reset_config = jtag_get_reset_config();
422
423 if (jtag_reset_config & RESET_CNCT_UNDER_SRST) {
424 if (jtag_reset_config & RESET_SRST_NO_GATING)
425 adapter_assert_reset();
426 else
427 LOG_WARNING("\'srst_nogate\' reset_config option is required");
428 }
429 }
430
431 if (dap_is_multidrop(dap))
432 status = swd_connect_multidrop(dap);
433 else
434 status = swd_connect_single(dap);
435
436 /* IHI 0031E B4.3.2:
437 * "A WAIT response must not be issued to the ...
438 * ... writes to the ABORT register"
439 * swd_clear_sticky_errors() writes to the ABORT register only.
440 *
441 * Unfortunately at least Microchip SAMD51/E53/E54 returns WAIT
442 * in a corner case. Just try if ABORT resolves the problem.
443 */
444 if (status == ERROR_WAIT) {
445 LOG_WARNING("Connecting DP: stalled AP operation, issuing ABORT");
446
447 dap->do_reconnect = false;
448
449 status = swd_queue_dp_write_inner(dap, DP_ABORT,
450 DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR);
451
452 if (status == ERROR_OK)
453 status = swd_run_inner(dap);
454 }
455
456 if (status == ERROR_OK)
457 status = dap_dp_init(dap);
458
459 return status;
460 }
461
462 static int swd_check_reconnect(struct adiv5_dap *dap)
463 {
464 if (dap->do_reconnect)
465 return swd_connect(dap);
466
467 return ERROR_OK;
468 }
469
470 static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
471 {
472 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
473 assert(swd);
474
475 /* TODO: Send DAPABORT in swd_multidrop_select_inner()
476 * in the case the multidrop dap is not selected?
477 * swd_queue_ap_abort() is not currently used anyway...
478 */
479 int retval = swd_multidrop_select(dap);
480 if (retval != ERROR_OK)
481 return retval;
482
483 swd->write_reg(swd_cmd(false, false, DP_ABORT),
484 DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0);
485 return check_sync(dap);
486 }
487
488 static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
489 uint32_t *data)
490 {
491 int retval = swd_check_reconnect(dap);
492 if (retval != ERROR_OK)
493 return retval;
494
495 retval = swd_multidrop_select(dap);
496 if (retval != ERROR_OK)
497 return retval;
498
499 return swd_queue_dp_read_inner(dap, reg, data);
500 }
501
502 static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg,
503 uint32_t data)
504 {
505 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
506 assert(swd);
507
508 int retval = swd_check_reconnect(dap);
509 if (retval != ERROR_OK)
510 return retval;
511
512 retval = swd_multidrop_select(dap);
513 if (retval != ERROR_OK)
514 return retval;
515
516 return swd_queue_dp_write_inner(dap, reg, data);
517 }
518
519 /** Select the AP register bank */
520 static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg)
521 {
522 int retval;
523 struct adiv5_dap *dap = ap->dap;
524 uint64_t sel;
525
526 if (is_adiv6(dap))
527 sel = ap->ap_num | (reg & 0x00000FF0);
528 else
529 sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK);
530
531 uint64_t sel_diff = (sel ^ dap->select) & SELECT_AP_MASK;
532
533 bool set_select = !dap->select_valid || (sel_diff & 0xffffffffull);
534 bool set_select1 = is_adiv6(dap) && dap->asize > 32
535 && (!dap->select1_valid
536 || sel_diff & (0xffffffffull << 32));
537
538 if (set_select && set_select1) {
539 /* Prepare DP bank for DP_SELECT1 now to save one write */
540 sel |= (DP_SELECT1 & 0x000000f0) >> 4;
541 } else {
542 /* Use the DP part of dap->select regardless of dap->select_valid:
543 * if !dap->select_valid
544 * dap->select contains a speculative value likely going to be used
545 * in the following swd_queue_dp_bankselect().
546 * Moreover dap->select_valid should never be false here as a DP bank
547 * is always selected before selecting an AP bank */
548 sel |= dap->select & DP_SELECT_DPBANK;
549 }
550
551 if (set_select) {
552 LOG_DEBUG_IO("AP BANK SELECT: %" PRIx32, (uint32_t)sel);
553
554 retval = swd_queue_dp_write(dap, DP_SELECT, (uint32_t)sel);
555 if (retval != ERROR_OK)
556 return retval;
557 }
558
559 if (set_select1) {
560 LOG_DEBUG_IO("AP BANK SELECT1: %" PRIx32, (uint32_t)(sel >> 32));
561
562 retval = swd_queue_dp_write(dap, DP_SELECT1, (uint32_t)(sel >> 32));
563 if (retval != ERROR_OK)
564 return retval;
565 }
566
567 return ERROR_OK;
568 }
569
570 static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg,
571 uint32_t *data)
572 {
573 struct adiv5_dap *dap = ap->dap;
574 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
575 assert(swd);
576
577 int retval = swd_check_reconnect(dap);
578 if (retval != ERROR_OK)
579 return retval;
580
581 retval = swd_multidrop_select(dap);
582 if (retval != ERROR_OK)
583 return retval;
584
585 retval = swd_queue_ap_bankselect(ap, reg);
586 if (retval != ERROR_OK)
587 return retval;
588
589 swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck);
590 dap->last_read = data;
591
592 return check_sync(dap);
593 }
594
595 static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg,
596 uint32_t data)
597 {
598 struct adiv5_dap *dap = ap->dap;
599 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
600 assert(swd);
601
602 int retval = swd_check_reconnect(dap);
603 if (retval != ERROR_OK)
604 return retval;
605
606 retval = swd_multidrop_select(dap);
607 if (retval != ERROR_OK)
608 return retval;
609
610 swd_finish_read(dap);
611
612 retval = swd_queue_ap_bankselect(ap, reg);
613 if (retval != ERROR_OK)
614 return retval;
615
616 swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck);
617
618 return check_sync(dap);
619 }
620
621 /** Executes all queued DAP operations. */
622 static int swd_run(struct adiv5_dap *dap)
623 {
624 int retval = swd_multidrop_select(dap);
625 if (retval != ERROR_OK)
626 return retval;
627
628 swd_finish_read(dap);
629
630 retval = swd_run_inner(dap);
631 if (retval != ERROR_OK) {
632 /* fault response */
633 dap->do_reconnect = true;
634 }
635
636 return retval;
637 }
638
639 /** Put the SWJ-DP back to JTAG mode */
640 static void swd_quit(struct adiv5_dap *dap)
641 {
642 const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
643 static bool done;
644
645 /* There is no difference if the sequence is sent at the last
646 * or the first swd_quit() call, send it just once */
647 if (done)
648 return;
649
650 done = true;
651 if (dap_is_multidrop(dap)) {
652 /* Emit the switch seq to dormant state regardless the state mirrored
653 * in swd_multidrop_in_swd_state. Doing so ensures robust operation
654 * in the case the variable is out of sync.
655 * Sending SWD_TO_DORMANT makes no change if the DP is already dormant. */
656 swd->switch_seq(SWD_TO_DORMANT);
657 swd_multidrop_in_swd_state = false;
658 /* Revisit!
659 * Leaving DPs in dormant state was tested and offers some safety
660 * against DPs mismatch in case of unintentional use of non-multidrop SWD.
661 * To put SWJ-DPs to power-on state issue
662 * swd->switch_seq(DORMANT_TO_JTAG);
663 */
664 } else {
665 if (dap->switch_through_dormant) {
666 swd->switch_seq(SWD_TO_DORMANT);
667 swd->switch_seq(DORMANT_TO_JTAG);
668 } else {
669 swd->switch_seq(SWD_TO_JTAG);
670 }
671 }
672
673 /* flush the queue to shift out the sequence before exit */
674 swd->run();
675 }
676
677 const struct dap_ops swd_dap_ops = {
678 .pre_connect_init = swd_pre_connect,
679 .connect = swd_connect,
680 .send_sequence = swd_send_sequence,
681 .queue_dp_read = swd_queue_dp_read,
682 .queue_dp_write = swd_queue_dp_write,
683 .queue_ap_read = swd_queue_ap_read,
684 .queue_ap_write = swd_queue_ap_write,
685 .queue_ap_abort = swd_queue_ap_abort,
686 .run = swd_run,
687 .quit = swd_quit,
688 };
689
690 static const struct command_registration swd_commands[] = {
691 {
692 /*
693 * Set up SWD and JTAG targets identically, unless/until
694 * infrastructure improves ... meanwhile, ignore all
695 * JTAG-specific stuff like IR length for SWD.
696 *
697 * REVISIT can we verify "just one SWD DAP" here/early?
698 */
699 .name = "newdap",
700 .handler = handle_jtag_newtap,
701 .mode = COMMAND_CONFIG,
702 .help = "declare a new SWD DAP",
703 .usage = "basename dap_type ['-irlen' count] "
704 "['-enable'|'-disable'] "
705 "['-expected_id' number] "
706 "['-ignore-version'] "
707 "['-ignore-bypass'] "
708 "['-ircapture' number] "
709 "['-ir-bypass' number] "
710 "['-mask' number]",
711 },
712 COMMAND_REGISTRATION_DONE
713 };
714
715 static const struct command_registration swd_handlers[] = {
716 {
717 .name = "swd",
718 .mode = COMMAND_ANY,
719 .help = "SWD command group",
720 .chain = swd_commands,
721 .usage = "",
722 },
723 COMMAND_REGISTRATION_DONE
724 };
725
726 static int swd_select(struct command_context *ctx)
727 {
728 /* FIXME: only place where global 'adapter_driver' is still needed */
729 extern struct adapter_driver *adapter_driver;
730 const struct swd_driver *swd = adapter_driver->swd_ops;
731 int retval;
732
733 retval = register_commands(ctx, NULL, swd_handlers);
734 if (retval != ERROR_OK)
735 return retval;
736
737 /* be sure driver is in SWD mode; start
738 * with hardware default TRN (1), it can be changed later
739 */
740 if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) {
741 LOG_DEBUG("no SWD driver?");
742 return ERROR_FAIL;
743 }
744
745 retval = swd->init();
746 if (retval != ERROR_OK) {
747 LOG_DEBUG("can't init SWD driver");
748 return retval;
749 }
750
751 return retval;
752 }
753
754 static int swd_init(struct command_context *ctx)
755 {
756 /* nothing done here, SWD is initialized
757 * together with the DAP */
758 return ERROR_OK;
759 }
760
761 static struct transport swd_transport = {
762 .name = "swd",
763 .select = swd_select,
764 .init = swd_init,
765 };
766
767 static void swd_constructor(void) __attribute__((constructor));
768 static void swd_constructor(void)
769 {
770 transport_register(&swd_transport);
771 }
772
773 /** Returns true if the current debug session
774 * is using SWD as its transport.
775 */
776 bool transport_is_swd(void)
777 {
778 return get_current_transport() == &swd_transport;
779 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)