1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
5 * Copyright (C) 2010 by David Brownell
6 ***************************************************************************/
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.
16 * Single-DAP support only.
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
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).
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.
38 #include "arm_adi_v5.h"
39 #include <helper/time_support.h>
41 #include <transport/transport.h>
42 #include <jtag/interface.h>
46 /* for debug, set do_sync to true to force synchronous transfers */
49 static struct adiv5_dap
*swd_multidrop_selected_dap
;
52 static int swd_queue_dp_write_inner(struct adiv5_dap
*dap
, unsigned int reg
,
56 static int swd_send_sequence(struct adiv5_dap
*dap
, enum swd_special_seq seq
)
58 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
61 return swd
->switch_seq(seq
);
64 static void swd_finish_read(struct adiv5_dap
*dap
)
66 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
68 swd
->read_reg(swd_cmd(true, false, DP_RDBUFF
), dap
->last_read
, 0);
69 dap
->last_read
= NULL
;
73 static void swd_clear_sticky_errors(struct adiv5_dap
*dap
)
75 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
78 swd
->write_reg(swd_cmd(false, false, DP_ABORT
),
79 STKCMPCLR
| STKERRCLR
| WDERRCLR
| ORUNERRCLR
, 0);
82 static int swd_run_inner(struct adiv5_dap
*dap
)
84 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
89 if (retval
!= ERROR_OK
) {
91 dap
->do_reconnect
= true;
97 static inline int check_sync(struct adiv5_dap
*dap
)
99 return do_sync
? swd_run_inner(dap
) : ERROR_OK
;
102 /** Select the DP register bank matching bits 7:4 of reg. */
103 static int swd_queue_dp_bankselect(struct adiv5_dap
*dap
, unsigned int reg
)
105 /* Only register address 0 and 4 are banked. */
109 uint64_t sel
= (reg
& 0x000000F0) >> 4;
110 if (dap
->select
!= DP_SELECT_INVALID
)
111 sel
|= dap
->select
& ~0xfULL
;
113 if (sel
== dap
->select
)
118 int retval
= swd_queue_dp_write_inner(dap
, DP_SELECT
, (uint32_t)sel
);
119 if (retval
!= ERROR_OK
)
120 dap
->select
= DP_SELECT_INVALID
;
125 static int swd_queue_dp_read_inner(struct adiv5_dap
*dap
, unsigned int reg
,
128 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
131 int retval
= swd_queue_dp_bankselect(dap
, reg
);
132 if (retval
!= ERROR_OK
)
135 swd
->read_reg(swd_cmd(true, false, reg
), data
, 0);
137 return check_sync(dap
);
140 static int swd_queue_dp_write_inner(struct adiv5_dap
*dap
, unsigned int reg
,
144 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
147 swd_finish_read(dap
);
149 if (reg
== DP_SELECT
) {
150 dap
->select
= data
& (DP_SELECT_APSEL
| DP_SELECT_APBANK
| DP_SELECT_DPBANK
);
152 swd
->write_reg(swd_cmd(false, false, reg
), data
, 0);
154 retval
= check_sync(dap
);
155 if (retval
!= ERROR_OK
)
156 dap
->select
= DP_SELECT_INVALID
;
161 retval
= swd_queue_dp_bankselect(dap
, reg
);
162 if (retval
!= ERROR_OK
)
165 swd
->write_reg(swd_cmd(false, false, reg
), data
, 0);
167 return check_sync(dap
);
171 static int swd_multidrop_select_inner(struct adiv5_dap
*dap
, uint32_t *dpidr_ptr
,
172 uint32_t *dlpidr_ptr
, bool clear_sticky
)
175 uint32_t dpidr
, dlpidr
;
177 assert(dap_is_multidrop(dap
));
179 swd_send_sequence(dap
, LINE_RESET
);
181 retval
= swd_queue_dp_write_inner(dap
, DP_TARGETSEL
, dap
->multidrop_targetsel
);
182 if (retval
!= ERROR_OK
)
185 retval
= swd_queue_dp_read_inner(dap
, DP_DPIDR
, &dpidr
);
186 if (retval
!= ERROR_OK
)
190 /* Clear all sticky errors (including ORUN) */
191 swd_clear_sticky_errors(dap
);
193 /* Ideally just clear ORUN flag which is set by reset */
194 retval
= swd_queue_dp_write_inner(dap
, DP_ABORT
, ORUNERRCLR
);
195 if (retval
!= ERROR_OK
)
199 retval
= swd_queue_dp_read_inner(dap
, DP_DLPIDR
, &dlpidr
);
200 if (retval
!= ERROR_OK
)
203 retval
= swd_run_inner(dap
);
204 if (retval
!= ERROR_OK
)
207 if ((dpidr
& DP_DPIDR_VERSION_MASK
) < (2UL << DP_DPIDR_VERSION_SHIFT
)) {
208 LOG_INFO("Read DPIDR 0x%08" PRIx32
209 " has version < 2. A non multidrop capable device connected?",
214 /* TODO: check TARGETID if DLIPDR is same for more than one DP */
215 uint32_t expected_dlpidr
= DP_DLPIDR_PROTVSN
|
216 (dap
->multidrop_targetsel
& DP_TARGETSEL_INSTANCEID_MASK
);
217 if (dlpidr
!= expected_dlpidr
) {
218 LOG_INFO("Read incorrect DLPIDR 0x%08" PRIx32
219 " (possibly CTRL/STAT value)",
224 LOG_DEBUG_IO("Selected DP_TARGETSEL 0x%08" PRIx32
, dap
->multidrop_targetsel
);
225 swd_multidrop_selected_dap
= dap
;
231 *dlpidr_ptr
= dlpidr
;
236 static int swd_multidrop_select(struct adiv5_dap
*dap
)
238 if (!dap_is_multidrop(dap
))
241 if (swd_multidrop_selected_dap
== dap
)
244 int retval
= ERROR_OK
;
245 for (unsigned int retry
= 0; ; retry
++) {
246 bool clear_sticky
= retry
> 0;
248 retval
= swd_multidrop_select_inner(dap
, NULL
, NULL
, clear_sticky
);
249 if (retval
== ERROR_OK
)
252 swd_multidrop_selected_dap
= NULL
;
254 LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap
));
258 LOG_DEBUG("Failed to select multidrop %s, retrying...",
259 adiv5_dap_name(dap
));
265 static int swd_connect_multidrop(struct adiv5_dap
*dap
)
268 uint32_t dpidr
= 0xdeadbeef;
269 uint32_t dlpidr
= 0xdeadbeef;
270 int64_t timeout
= timeval_ms() + 500;
273 swd_send_sequence(dap
, JTAG_TO_DORMANT
);
274 swd_send_sequence(dap
, DORMANT_TO_SWD
);
276 /* Clear link state, including the SELECT cache. */
277 dap
->do_reconnect
= false;
278 dap_invalidate_cache(dap
);
279 swd_multidrop_selected_dap
= NULL
;
281 retval
= swd_multidrop_select_inner(dap
, &dpidr
, &dlpidr
, true);
282 if (retval
== ERROR_OK
)
287 } while (timeval_ms() < timeout
);
289 if (retval
!= ERROR_OK
) {
290 swd_multidrop_selected_dap
= NULL
;
291 LOG_ERROR("Failed to connect multidrop %s", adiv5_dap_name(dap
));
295 LOG_INFO("SWD DPIDR 0x%08" PRIx32
", DLPIDR 0x%08" PRIx32
,
301 static int swd_connect_single(struct adiv5_dap
*dap
)
304 uint32_t dpidr
= 0xdeadbeef;
305 int64_t timeout
= timeval_ms() + 500;
308 if (dap
->switch_through_dormant
) {
309 swd_send_sequence(dap
, JTAG_TO_DORMANT
);
310 swd_send_sequence(dap
, DORMANT_TO_SWD
);
312 swd_send_sequence(dap
, JTAG_TO_SWD
);
315 /* Clear link state, including the SELECT cache. */
316 dap
->do_reconnect
= false;
317 dap_invalidate_cache(dap
);
319 /* The sequences to enter in SWD (JTAG_TO_SWD and DORMANT_TO_SWD) end
320 * with a SWD line reset sequence (50 clk with SWDIO high).
321 * From ARM IHI 0074C ADIv6.0, chapter B4.3.3 "Connection and line reset
323 * - line reset sets DP_SELECT_DPBANK to zero;
324 * - read of DP_DPIDR takes the connection out of reset;
325 * - write of DP_TARGETSEL keeps the connection in reset;
326 * - other accesses return protocol error (SWDIO not driven by target).
328 * Read DP_DPIDR to get out of reset. Initialize dap->select to zero to
329 * skip the write to DP_SELECT, avoiding the protocol error. Set again
330 * dap->select to DP_SELECT_INVALID because the rest of the register is
331 * unknown after line reset.
334 retval
= swd_queue_dp_read_inner(dap
, DP_DPIDR
, &dpidr
);
335 if (retval
== ERROR_OK
) {
336 retval
= swd_run_inner(dap
);
337 if (retval
== ERROR_OK
)
343 dap
->switch_through_dormant
= !dap
->switch_through_dormant
;
344 } while (timeval_ms() < timeout
);
345 dap
->select
= DP_SELECT_INVALID
;
347 if (retval
!= ERROR_OK
) {
348 LOG_ERROR("Error connecting DP: cannot read IDR");
352 LOG_INFO("SWD DPIDR 0x%08" PRIx32
, dpidr
);
355 dap
->do_reconnect
= false;
357 /* force clear all sticky faults */
358 swd_clear_sticky_errors(dap
);
360 retval
= swd_run_inner(dap
);
361 if (retval
!= ERROR_WAIT
)
366 } while (timeval_ms() < timeout
);
371 static int swd_connect(struct adiv5_dap
*dap
)
375 /* FIXME validate transport config ... is the
376 * configured DAP present (check IDCODE)?
379 /* Check if we should reset srst already when connecting, but not if reconnecting. */
380 if (!dap
->do_reconnect
) {
381 enum reset_types jtag_reset_config
= jtag_get_reset_config();
383 if (jtag_reset_config
& RESET_CNCT_UNDER_SRST
) {
384 if (jtag_reset_config
& RESET_SRST_NO_GATING
)
385 adapter_assert_reset();
387 LOG_WARNING("\'srst_nogate\' reset_config option is required");
391 if (dap_is_multidrop(dap
))
392 status
= swd_connect_multidrop(dap
);
394 status
= swd_connect_single(dap
);
397 * "A WAIT response must not be issued to the ...
398 * ... writes to the ABORT register"
399 * swd_clear_sticky_errors() writes to the ABORT register only.
401 * Unfortunately at least Microchip SAMD51/E53/E54 returns WAIT
402 * in a corner case. Just try if ABORT resolves the problem.
404 if (status
== ERROR_WAIT
) {
405 LOG_WARNING("Connecting DP: stalled AP operation, issuing ABORT");
407 dap
->do_reconnect
= false;
409 status
= swd_queue_dp_write_inner(dap
, DP_ABORT
,
410 DAPABORT
| STKCMPCLR
| STKERRCLR
| WDERRCLR
| ORUNERRCLR
);
412 if (status
== ERROR_OK
)
413 status
= swd_run_inner(dap
);
416 if (status
== ERROR_OK
)
417 status
= dap_dp_init(dap
);
422 static int swd_check_reconnect(struct adiv5_dap
*dap
)
424 if (dap
->do_reconnect
)
425 return swd_connect(dap
);
430 static int swd_queue_ap_abort(struct adiv5_dap
*dap
, uint8_t *ack
)
432 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
435 /* TODO: Send DAPABORT in swd_multidrop_select_inner()
436 * in the case the multidrop dap is not selected?
437 * swd_queue_ap_abort() is not currently used anyway...
439 int retval
= swd_multidrop_select(dap
);
440 if (retval
!= ERROR_OK
)
443 swd
->write_reg(swd_cmd(false, false, DP_ABORT
),
444 DAPABORT
| STKCMPCLR
| STKERRCLR
| WDERRCLR
| ORUNERRCLR
, 0);
445 return check_sync(dap
);
448 static int swd_queue_dp_read(struct adiv5_dap
*dap
, unsigned reg
,
451 int retval
= swd_check_reconnect(dap
);
452 if (retval
!= ERROR_OK
)
455 retval
= swd_multidrop_select(dap
);
456 if (retval
!= ERROR_OK
)
459 return swd_queue_dp_read_inner(dap
, reg
, data
);
462 static int swd_queue_dp_write(struct adiv5_dap
*dap
, unsigned reg
,
465 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
468 int retval
= swd_check_reconnect(dap
);
469 if (retval
!= ERROR_OK
)
472 retval
= swd_multidrop_select(dap
);
473 if (retval
!= ERROR_OK
)
476 return swd_queue_dp_write_inner(dap
, reg
, data
);
479 /** Select the AP register bank matching bits 7:4 of reg. */
480 static int swd_queue_ap_bankselect(struct adiv5_ap
*ap
, unsigned reg
)
483 struct adiv5_dap
*dap
= ap
->dap
;
487 sel
= ap
->ap_num
| (reg
& 0x00000FF0);
488 if (sel
== (dap
->select
& ~0xfULL
))
491 if (dap
->select
!= DP_SELECT_INVALID
)
492 sel
|= dap
->select
& 0xf;
494 LOG_DEBUG("AP BANKSEL: %" PRIx64
, sel
);
496 retval
= swd_queue_dp_write(dap
, DP_SELECT
, (uint32_t)sel
);
498 if (retval
== ERROR_OK
&& dap
->asize
> 32)
499 retval
= swd_queue_dp_write(dap
, DP_SELECT1
, (uint32_t)(sel
>> 32));
501 if (retval
!= ERROR_OK
)
502 dap
->select
= DP_SELECT_INVALID
;
508 sel
= (ap
->ap_num
<< 24) | (reg
& 0x000000F0);
509 if (dap
->select
!= DP_SELECT_INVALID
)
510 sel
|= dap
->select
& DP_SELECT_DPBANK
;
512 if (sel
== dap
->select
)
517 retval
= swd_queue_dp_write_inner(dap
, DP_SELECT
, sel
);
518 if (retval
!= ERROR_OK
)
519 dap
->select
= DP_SELECT_INVALID
;
524 static int swd_queue_ap_read(struct adiv5_ap
*ap
, unsigned reg
,
527 struct adiv5_dap
*dap
= ap
->dap
;
528 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
531 int retval
= swd_check_reconnect(dap
);
532 if (retval
!= ERROR_OK
)
535 retval
= swd_multidrop_select(dap
);
536 if (retval
!= ERROR_OK
)
539 retval
= swd_queue_ap_bankselect(ap
, reg
);
540 if (retval
!= ERROR_OK
)
543 swd
->read_reg(swd_cmd(true, true, reg
), dap
->last_read
, ap
->memaccess_tck
);
544 dap
->last_read
= data
;
546 return check_sync(dap
);
549 static int swd_queue_ap_write(struct adiv5_ap
*ap
, unsigned reg
,
552 struct adiv5_dap
*dap
= ap
->dap
;
553 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
556 int retval
= swd_check_reconnect(dap
);
557 if (retval
!= ERROR_OK
)
560 retval
= swd_multidrop_select(dap
);
561 if (retval
!= ERROR_OK
)
564 swd_finish_read(dap
);
566 retval
= swd_queue_ap_bankselect(ap
, reg
);
567 if (retval
!= ERROR_OK
)
570 swd
->write_reg(swd_cmd(false, true, reg
), data
, ap
->memaccess_tck
);
572 return check_sync(dap
);
575 /** Executes all queued DAP operations. */
576 static int swd_run(struct adiv5_dap
*dap
)
578 int retval
= swd_multidrop_select(dap
);
579 if (retval
!= ERROR_OK
)
582 swd_finish_read(dap
);
584 return swd_run_inner(dap
);
587 /** Put the SWJ-DP back to JTAG mode */
588 static void swd_quit(struct adiv5_dap
*dap
)
590 const struct swd_driver
*swd
= adiv5_dap_swd_driver(dap
);
593 /* There is no difference if the sequence is sent at the last
594 * or the first swd_quit() call, send it just once */
599 if (dap_is_multidrop(dap
)) {
600 swd
->switch_seq(SWD_TO_DORMANT
);
602 * Leaving DPs in dormant state was tested and offers some safety
603 * against DPs mismatch in case of unintentional use of non-multidrop SWD.
604 * To put SWJ-DPs to power-on state issue
605 * swd->switch_seq(DORMANT_TO_JTAG);
608 if (dap
->switch_through_dormant
) {
609 swd
->switch_seq(SWD_TO_DORMANT
);
610 swd
->switch_seq(DORMANT_TO_JTAG
);
612 swd
->switch_seq(SWD_TO_JTAG
);
616 /* flush the queue to shift out the sequence before exit */
620 const struct dap_ops swd_dap_ops
= {
621 .connect
= swd_connect
,
622 .send_sequence
= swd_send_sequence
,
623 .queue_dp_read
= swd_queue_dp_read
,
624 .queue_dp_write
= swd_queue_dp_write
,
625 .queue_ap_read
= swd_queue_ap_read
,
626 .queue_ap_write
= swd_queue_ap_write
,
627 .queue_ap_abort
= swd_queue_ap_abort
,
632 static const struct command_registration swd_commands
[] = {
635 * Set up SWD and JTAG targets identically, unless/until
636 * infrastructure improves ... meanwhile, ignore all
637 * JTAG-specific stuff like IR length for SWD.
639 * REVISIT can we verify "just one SWD DAP" here/early?
642 .jim_handler
= jim_jtag_newtap
,
643 .mode
= COMMAND_CONFIG
,
644 .help
= "declare a new SWD DAP"
646 COMMAND_REGISTRATION_DONE
649 static const struct command_registration swd_handlers
[] = {
653 .help
= "SWD command group",
654 .chain
= swd_commands
,
657 COMMAND_REGISTRATION_DONE
660 static int swd_select(struct command_context
*ctx
)
662 /* FIXME: only place where global 'adapter_driver' is still needed */
663 extern struct adapter_driver
*adapter_driver
;
664 const struct swd_driver
*swd
= adapter_driver
->swd_ops
;
667 retval
= register_commands(ctx
, NULL
, swd_handlers
);
668 if (retval
!= ERROR_OK
)
671 /* be sure driver is in SWD mode; start
672 * with hardware default TRN (1), it can be changed later
674 if (!swd
|| !swd
->read_reg
|| !swd
->write_reg
|| !swd
->init
) {
675 LOG_DEBUG("no SWD driver?");
679 retval
= swd
->init();
680 if (retval
!= ERROR_OK
) {
681 LOG_DEBUG("can't init SWD driver");
688 static int swd_init(struct command_context
*ctx
)
690 /* nothing done here, SWD is initialized
691 * together with the DAP */
695 static struct transport swd_transport
= {
697 .select
= swd_select
,
701 static void swd_constructor(void) __attribute__((constructor
));
702 static void swd_constructor(void)
704 transport_register(&swd_transport
);
707 /** Returns true if the current debug session
708 * is using SWD as its transport.
710 bool transport_is_swd(void)
712 return get_current_transport() == &swd_transport
;
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)