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