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

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)