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

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)