OpenOCD
adi_v5_swd.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  *
5  * Copyright (C) 2010 by David Brownell
6  ***************************************************************************/
7 
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 
50 
51 
52 static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
53  uint32_t data);
54 
55 
56 static int swd_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq)
57 {
58  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
59  assert(swd);
60 
61  return swd->switch_seq(seq);
62 }
63 
64 static void swd_finish_read(struct adiv5_dap *dap)
65 {
66  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
67  if (dap->last_read) {
68  swd->read_reg(swd_cmd(true, false, DP_RDBUFF), dap->last_read, 0);
69  dap->last_read = NULL;
70  }
71 }
72 
73 static void swd_clear_sticky_errors(struct adiv5_dap *dap)
74 {
75  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
76  assert(swd);
77 
78  swd->write_reg(swd_cmd(false, false, DP_ABORT),
80 }
81 
82 static int swd_run_inner(struct adiv5_dap *dap)
83 {
84  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
85  int retval;
86 
87  retval = swd->run();
88 
89  if (retval != ERROR_OK) {
90  /* fault response */
91  dap->do_reconnect = true;
92  }
93 
94  return retval;
95 }
96 
97 static inline int check_sync(struct adiv5_dap *dap)
98 {
99  return do_sync ? swd_run_inner(dap) : ERROR_OK;
100 }
101 
103 static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg)
104 {
105  /* Only register address 0 and 4 are banked. */
106  if ((reg & 0xf) > 4)
107  return ERROR_OK;
108 
109  uint64_t sel = (reg & 0x000000F0) >> 4;
110  if (dap->select != DP_SELECT_INVALID)
111  sel |= dap->select & ~0xfULL;
112 
113  if (sel == dap->select)
114  return ERROR_OK;
115 
116  dap->select = sel;
117 
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;
121 
122  return retval;
123 }
124 
125 static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg,
126  uint32_t *data)
127 {
128  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
129  assert(swd);
130 
131  int retval = swd_queue_dp_bankselect(dap, reg);
132  if (retval != ERROR_OK)
133  return retval;
134 
135  swd->read_reg(swd_cmd(true, false, reg), data, 0);
136 
137  return check_sync(dap);
138 }
139 
140 static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
141  uint32_t data)
142 {
143  int retval;
144  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
145  assert(swd);
146 
147  swd_finish_read(dap);
148 
149  if (reg == DP_SELECT) {
151 
152  swd->write_reg(swd_cmd(false, false, reg), data, 0);
153 
154  retval = check_sync(dap);
155  if (retval != ERROR_OK)
156  dap->select = DP_SELECT_INVALID;
157 
158  return retval;
159  }
160 
161  retval = swd_queue_dp_bankselect(dap, reg);
162  if (retval != ERROR_OK)
163  return retval;
164 
165  swd->write_reg(swd_cmd(false, false, reg), data, 0);
166 
167  return check_sync(dap);
168 }
169 
170 
171 static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr,
172  uint32_t *dlpidr_ptr, bool clear_sticky)
173 {
174  int retval;
175  uint32_t dpidr, dlpidr;
176 
177  assert(dap_is_multidrop(dap));
178 
180  /* From ARM IHI 0074C ADIv6.0, chapter B4.3.3 "Connection and line reset
181  * sequence":
182  * - line reset sets DP_SELECT_DPBANK to zero;
183  * - read of DP_DPIDR takes the connection out of reset;
184  * - write of DP_TARGETSEL keeps the connection in reset;
185  * - other accesses return protocol error (SWDIO not driven by target).
186  *
187  * Read DP_DPIDR to get out of reset. Initialize dap->select to zero to
188  * skip the write to DP_SELECT, avoiding the protocol error. Set again
189  * dap->select to DP_SELECT_INVALID because the rest of the register is
190  * unknown after line reset.
191  */
192  dap->select = 0;
193 
195  if (retval != ERROR_OK)
196  return retval;
197 
198  retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr);
199  if (retval != ERROR_OK)
200  return retval;
201 
202  if (clear_sticky) {
203  /* Clear all sticky errors (including ORUN) */
205  } else {
206  /* Ideally just clear ORUN flag which is set by reset */
208  if (retval != ERROR_OK)
209  return retval;
210  }
211 
212  dap->select = DP_SELECT_INVALID;
213 
214  retval = swd_queue_dp_read_inner(dap, DP_DLPIDR, &dlpidr);
215  if (retval != ERROR_OK)
216  return retval;
217 
218  retval = swd_run_inner(dap);
219  if (retval != ERROR_OK)
220  return retval;
221 
222  if ((dpidr & DP_DPIDR_VERSION_MASK) < (2UL << DP_DPIDR_VERSION_SHIFT)) {
223  LOG_INFO("Read DPIDR 0x%08" PRIx32
224  " has version < 2. A non multidrop capable device connected?",
225  dpidr);
226  return ERROR_FAIL;
227  }
228 
229  /* TODO: check TARGETID if DLIPDR is same for more than one DP */
230  uint32_t expected_dlpidr = DP_DLPIDR_PROTVSN |
232  if (dlpidr != expected_dlpidr) {
233  LOG_INFO("Read incorrect DLPIDR 0x%08" PRIx32
234  " (possibly CTRL/STAT value)",
235  dlpidr);
236  return ERROR_FAIL;
237  }
238 
239  LOG_DEBUG_IO("Selected DP_TARGETSEL 0x%08" PRIx32, dap->multidrop_targetsel);
241 
242  if (dpidr_ptr)
243  *dpidr_ptr = dpidr;
244 
245  if (dlpidr_ptr)
246  *dlpidr_ptr = dlpidr;
247 
248  return retval;
249 }
250 
251 static int swd_multidrop_select(struct adiv5_dap *dap)
252 {
253  if (!dap_is_multidrop(dap))
254  return ERROR_OK;
255 
256  if (swd_multidrop_selected_dap == dap)
257  return ERROR_OK;
258 
259  int retval = ERROR_OK;
260  for (unsigned int retry = 0; ; retry++) {
261  bool clear_sticky = retry > 0;
262 
263  retval = swd_multidrop_select_inner(dap, NULL, NULL, clear_sticky);
264  if (retval == ERROR_OK)
265  break;
266 
268  if (retry > 3) {
269  LOG_ERROR("Failed to select multidrop %s", adiv5_dap_name(dap));
270  return retval;
271  }
272 
273  LOG_DEBUG("Failed to select multidrop %s, retrying...",
274  adiv5_dap_name(dap));
275  /* we going to retry localy, do not ask for full reconnect */
276  dap->do_reconnect = false;
277  }
278 
279  return retval;
280 }
281 
282 static int swd_connect_multidrop(struct adiv5_dap *dap)
283 {
284  int retval;
285  uint32_t dpidr = 0xdeadbeef;
286  uint32_t dlpidr = 0xdeadbeef;
287  int64_t timeout = timeval_ms() + 500;
288 
289  do {
292 
293  /* Clear link state, including the SELECT cache. */
294  dap->do_reconnect = false;
297 
298  retval = swd_multidrop_select_inner(dap, &dpidr, &dlpidr, true);
299  if (retval == ERROR_OK)
300  break;
301 
302  alive_sleep(1);
303 
304  } while (timeval_ms() < timeout);
305 
306  if (retval != ERROR_OK) {
308  LOG_ERROR("Failed to connect multidrop %s", adiv5_dap_name(dap));
309  return retval;
310  }
311 
312  LOG_INFO("SWD DPIDR 0x%08" PRIx32 ", DLPIDR 0x%08" PRIx32,
313  dpidr, dlpidr);
314 
315  return retval;
316 }
317 
318 static int swd_connect_single(struct adiv5_dap *dap)
319 {
320  int retval;
321  uint32_t dpidr = 0xdeadbeef;
322  int64_t timeout = timeval_ms() + 500;
323 
324  do {
325  if (dap->switch_through_dormant) {
328  } else {
330  }
331 
332  /* Clear link state, including the SELECT cache. */
333  dap->do_reconnect = false;
335 
336  /* The sequences to enter in SWD (JTAG_TO_SWD and DORMANT_TO_SWD) end
337  * with a SWD line reset sequence (50 clk with SWDIO high).
338  * From ARM IHI 0074C ADIv6.0, chapter B4.3.3 "Connection and line reset
339  * sequence":
340  * - line reset sets DP_SELECT_DPBANK to zero;
341  * - read of DP_DPIDR takes the connection out of reset;
342  * - write of DP_TARGETSEL keeps the connection in reset;
343  * - other accesses return protocol error (SWDIO not driven by target).
344  *
345  * Read DP_DPIDR to get out of reset. Initialize dap->select to zero to
346  * skip the write to DP_SELECT, avoiding the protocol error. Set again
347  * dap->select to DP_SELECT_INVALID because the rest of the register is
348  * unknown after line reset.
349  */
350  dap->select = 0;
351  retval = swd_queue_dp_read_inner(dap, DP_DPIDR, &dpidr);
352  if (retval == ERROR_OK) {
353  retval = swd_run_inner(dap);
354  if (retval == ERROR_OK)
355  break;
356  }
357 
358  alive_sleep(1);
359 
361  } while (timeval_ms() < timeout);
362 
363  dap->select = DP_SELECT_INVALID;
364 
365  if (retval != ERROR_OK) {
366  LOG_ERROR("Error connecting DP: cannot read IDR");
367  return retval;
368  }
369 
370  LOG_INFO("SWD DPIDR 0x%08" PRIx32, dpidr);
371 
372  do {
373  dap->do_reconnect = false;
374 
375  /* force clear all sticky faults */
377 
378  retval = swd_run_inner(dap);
379  if (retval != ERROR_WAIT)
380  break;
381 
382  alive_sleep(10);
383 
384  } while (timeval_ms() < timeout);
385 
386  return retval;
387 }
388 
389 static int swd_connect(struct adiv5_dap *dap)
390 {
391  int status;
392 
393  /* FIXME validate transport config ... is the
394  * configured DAP present (check IDCODE)?
395  */
396 
397  /* Check if we should reset srst already when connecting, but not if reconnecting. */
398  if (!dap->do_reconnect) {
400 
404  else
405  LOG_WARNING("\'srst_nogate\' reset_config option is required");
406  }
407  }
408 
409  if (dap_is_multidrop(dap))
411  else
412  status = swd_connect_single(dap);
413 
414  /* IHI 0031E B4.3.2:
415  * "A WAIT response must not be issued to the ...
416  * ... writes to the ABORT register"
417  * swd_clear_sticky_errors() writes to the ABORT register only.
418  *
419  * Unfortunately at least Microchip SAMD51/E53/E54 returns WAIT
420  * in a corner case. Just try if ABORT resolves the problem.
421  */
422  if (status == ERROR_WAIT) {
423  LOG_WARNING("Connecting DP: stalled AP operation, issuing ABORT");
424 
425  dap->do_reconnect = false;
426 
429 
430  if (status == ERROR_OK)
431  status = swd_run_inner(dap);
432  }
433 
434  if (status == ERROR_OK)
435  status = dap_dp_init(dap);
436 
437  return status;
438 }
439 
440 static int swd_check_reconnect(struct adiv5_dap *dap)
441 {
442  if (dap->do_reconnect)
443  return swd_connect(dap);
444 
445  return ERROR_OK;
446 }
447 
448 static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
449 {
450  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
451  assert(swd);
452 
453  /* TODO: Send DAPABORT in swd_multidrop_select_inner()
454  * in the case the multidrop dap is not selected?
455  * swd_queue_ap_abort() is not currently used anyway...
456  */
457  int retval = swd_multidrop_select(dap);
458  if (retval != ERROR_OK)
459  return retval;
460 
461  swd->write_reg(swd_cmd(false, false, DP_ABORT),
463  return check_sync(dap);
464 }
465 
466 static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
467  uint32_t *data)
468 {
469  int retval = swd_check_reconnect(dap);
470  if (retval != ERROR_OK)
471  return retval;
472 
473  retval = swd_multidrop_select(dap);
474  if (retval != ERROR_OK)
475  return retval;
476 
477  return swd_queue_dp_read_inner(dap, reg, data);
478 }
479 
480 static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg,
481  uint32_t data)
482 {
483  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
484  assert(swd);
485 
486  int retval = swd_check_reconnect(dap);
487  if (retval != ERROR_OK)
488  return retval;
489 
490  retval = swd_multidrop_select(dap);
491  if (retval != ERROR_OK)
492  return retval;
493 
494  return swd_queue_dp_write_inner(dap, reg, data);
495 }
496 
498 static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg)
499 {
500  int retval;
501  struct adiv5_dap *dap = ap->dap;
502  uint64_t sel;
503 
504  if (is_adiv6(dap)) {
505  sel = ap->ap_num | (reg & 0x00000FF0);
506  if (sel == (dap->select & ~0xfULL))
507  return ERROR_OK;
508 
509  if (dap->select != DP_SELECT_INVALID)
510  sel |= dap->select & 0xf;
511  dap->select = sel;
512  LOG_DEBUG("AP BANKSEL: %" PRIx64, sel);
513 
514  retval = swd_queue_dp_write(dap, DP_SELECT, (uint32_t)sel);
515 
516  if (retval == ERROR_OK && dap->asize > 32)
517  retval = swd_queue_dp_write(dap, DP_SELECT1, (uint32_t)(sel >> 32));
518 
519  if (retval != ERROR_OK)
520  dap->select = DP_SELECT_INVALID;
521 
522  return retval;
523  }
524 
525  /* ADIv5 */
526  sel = (ap->ap_num << 24) | (reg & 0x000000F0);
527  if (dap->select != DP_SELECT_INVALID)
528  sel |= dap->select & DP_SELECT_DPBANK;
529 
530  if (sel == dap->select)
531  return ERROR_OK;
532 
533  dap->select = sel;
534 
535  retval = swd_queue_dp_write_inner(dap, DP_SELECT, sel);
536  if (retval != ERROR_OK)
537  dap->select = DP_SELECT_INVALID;
538 
539  return retval;
540 }
541 
542 static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg,
543  uint32_t *data)
544 {
545  struct adiv5_dap *dap = ap->dap;
546  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
547  assert(swd);
548 
549  int retval = swd_check_reconnect(dap);
550  if (retval != ERROR_OK)
551  return retval;
552 
553  retval = swd_multidrop_select(dap);
554  if (retval != ERROR_OK)
555  return retval;
556 
557  retval = swd_queue_ap_bankselect(ap, reg);
558  if (retval != ERROR_OK)
559  return retval;
560 
561  swd->read_reg(swd_cmd(true, true, reg), dap->last_read, ap->memaccess_tck);
562  dap->last_read = data;
563 
564  return check_sync(dap);
565 }
566 
567 static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg,
568  uint32_t data)
569 {
570  struct adiv5_dap *dap = ap->dap;
571  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
572  assert(swd);
573 
574  int retval = swd_check_reconnect(dap);
575  if (retval != ERROR_OK)
576  return retval;
577 
578  retval = swd_multidrop_select(dap);
579  if (retval != ERROR_OK)
580  return retval;
581 
582  swd_finish_read(dap);
583 
584  retval = swd_queue_ap_bankselect(ap, reg);
585  if (retval != ERROR_OK)
586  return retval;
587 
588  swd->write_reg(swd_cmd(false, true, reg), data, ap->memaccess_tck);
589 
590  return check_sync(dap);
591 }
592 
594 static int swd_run(struct adiv5_dap *dap)
595 {
596  int retval = swd_multidrop_select(dap);
597  if (retval != ERROR_OK)
598  return retval;
599 
600  swd_finish_read(dap);
601 
602  return swd_run_inner(dap);
603 }
604 
606 static void swd_quit(struct adiv5_dap *dap)
607 {
608  const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
609  static bool done;
610 
611  /* There is no difference if the sequence is sent at the last
612  * or the first swd_quit() call, send it just once */
613  if (done)
614  return;
615 
616  done = true;
617  if (dap_is_multidrop(dap)) {
619  /* Revisit!
620  * Leaving DPs in dormant state was tested and offers some safety
621  * against DPs mismatch in case of unintentional use of non-multidrop SWD.
622  * To put SWJ-DPs to power-on state issue
623  * swd->switch_seq(DORMANT_TO_JTAG);
624  */
625  } else {
626  if (dap->switch_through_dormant) {
629  } else {
630  swd->switch_seq(SWD_TO_JTAG);
631  }
632  }
633 
634  /* flush the queue to shift out the sequence before exit */
635  swd->run();
636 }
637 
638 const struct dap_ops swd_dap_ops = {
639  .connect = swd_connect,
640  .send_sequence = swd_send_sequence,
641  .queue_dp_read = swd_queue_dp_read,
642  .queue_dp_write = swd_queue_dp_write,
643  .queue_ap_read = swd_queue_ap_read,
644  .queue_ap_write = swd_queue_ap_write,
645  .queue_ap_abort = swd_queue_ap_abort,
646  .run = swd_run,
647  .quit = swd_quit,
648 };
649 
650 static const struct command_registration swd_commands[] = {
651  {
652  /*
653  * Set up SWD and JTAG targets identically, unless/until
654  * infrastructure improves ... meanwhile, ignore all
655  * JTAG-specific stuff like IR length for SWD.
656  *
657  * REVISIT can we verify "just one SWD DAP" here/early?
658  */
659  .name = "newdap",
660  .jim_handler = jim_jtag_newtap,
661  .mode = COMMAND_CONFIG,
662  .help = "declare a new SWD DAP"
663  },
665 };
666 
667 static const struct command_registration swd_handlers[] = {
668  {
669  .name = "swd",
670  .mode = COMMAND_ANY,
671  .help = "SWD command group",
672  .chain = swd_commands,
673  .usage = "",
674  },
676 };
677 
678 static int swd_select(struct command_context *ctx)
679 {
680  /* FIXME: only place where global 'adapter_driver' is still needed */
681  extern struct adapter_driver *adapter_driver;
682  const struct swd_driver *swd = adapter_driver->swd_ops;
683  int retval;
684 
685  retval = register_commands(ctx, NULL, swd_handlers);
686  if (retval != ERROR_OK)
687  return retval;
688 
689  /* be sure driver is in SWD mode; start
690  * with hardware default TRN (1), it can be changed later
691  */
692  if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) {
693  LOG_DEBUG("no SWD driver?");
694  return ERROR_FAIL;
695  }
696 
697  retval = swd->init();
698  if (retval != ERROR_OK) {
699  LOG_DEBUG("can't init SWD driver");
700  return retval;
701  }
702 
703  return retval;
704 }
705 
706 static int swd_init(struct command_context *ctx)
707 {
708  /* nothing done here, SWD is initialized
709  * together with the DAP */
710  return ERROR_OK;
711 }
712 
713 static struct transport swd_transport = {
714  .name = "swd",
715  .select = swd_select,
716  .init = swd_init,
717 };
718 
719 static void swd_constructor(void) __attribute__((constructor));
720 static void swd_constructor(void)
721 {
723 }
724 
729 {
731 }
struct adapter_driver * adapter_driver
Definition: adapter.c:30
static int swd_multidrop_select(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:251
const struct dap_ops swd_dap_ops
Definition: adi_v5_swd.c:638
static int swd_connect_single(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:318
static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg)
Select the AP register bank matching bits 7:4 of reg.
Definition: adi_v5_swd.c:498
static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
Definition: adi_v5_swd.c:448
static const struct command_registration swd_commands[]
Definition: adi_v5_swd.c:650
static void swd_clear_sticky_errors(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:73
static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg, uint32_t data)
Definition: adi_v5_swd.c:140
static int check_sync(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:97
static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg, uint32_t data)
Definition: adi_v5_swd.c:567
static int swd_run_inner(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:82
static int swd_connect(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:389
static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data)
Definition: adi_v5_swd.c:466
static int swd_connect_multidrop(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:282
static int swd_init(struct command_context *ctx)
Definition: adi_v5_swd.c:706
static int swd_run(struct adiv5_dap *dap)
Executes all queued DAP operations.
Definition: adi_v5_swd.c:594
static int swd_select(struct command_context *ctx)
Definition: adi_v5_swd.c:678
static void swd_finish_read(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:64
static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned int reg)
Select the DP register bank matching bits 7:4 of reg.
Definition: adi_v5_swd.c:103
static int swd_queue_dp_read_inner(struct adiv5_dap *dap, unsigned int reg, uint32_t *data)
Definition: adi_v5_swd.c:125
static struct transport swd_transport
Definition: adi_v5_swd.c:713
bool transport_is_swd(void)
Returns true if the current debug session is using SWD as its transport.
Definition: adi_v5_swd.c:728
static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg, uint32_t *data)
Definition: adi_v5_swd.c:542
static bool do_sync
Definition: adi_v5_swd.c:47
static int swd_check_reconnect(struct adiv5_dap *dap)
Definition: adi_v5_swd.c:440
static int swd_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq)
Definition: adi_v5_swd.c:56
static void swd_quit(struct adiv5_dap *dap)
Put the SWJ-DP back to JTAG mode.
Definition: adi_v5_swd.c:606
static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg, uint32_t data)
Definition: adi_v5_swd.c:480
static const struct command_registration swd_handlers[]
Definition: adi_v5_swd.c:667
static struct adiv5_dap * swd_multidrop_selected_dap
Definition: adi_v5_swd.c:49
static int swd_multidrop_select_inner(struct adiv5_dap *dap, uint32_t *dpidr_ptr, uint32_t *dlpidr_ptr, bool clear_sticky)
Definition: adi_v5_swd.c:171
static void swd_constructor(void)
Definition: adi_v5_swd.c:719
Holds the interface to ARM cores.
int dap_dp_init(struct adiv5_dap *dap)
Initialize a DAP.
Definition: arm_adi_v5.c:675
void dap_invalidate_cache(struct adiv5_dap *dap)
Invalidate cached DP select and cached TAR and CSW of all APs.
Definition: arm_adi_v5.c:656
This defines formats and data structures used to talk to ADIv5 entities.
#define DP_ABORT
Definition: arm_adi_v5.h:46
#define WDERRCLR
Definition: arm_adi_v5.h:71
#define DP_SELECT
Definition: arm_adi_v5.h:57
const struct swd_driver * adiv5_dap_swd_driver(struct adiv5_dap *self)
Definition: arm_dap.c:62
#define DP_TARGETSEL_INSTANCEID_MASK
Definition: arm_adi_v5.h:110
#define DP_SELECT1
Definition: arm_adi_v5.h:55
#define STKERRCLR
Definition: arm_adi_v5.h:70
#define DP_DPIDR
Definition: arm_adi_v5.h:45
#define DP_SELECT_INVALID
Definition: arm_adi_v5.h:103
#define DP_RDBUFF
Definition: arm_adi_v5.h:58
#define DP_DLPIDR
Definition: arm_adi_v5.h:53
#define ORUNERRCLR
Definition: arm_adi_v5.h:72
#define DP_DLPIDR_PROTVSN
Definition: arm_adi_v5.h:98
#define STKCMPCLR
Definition: arm_adi_v5.h:69
#define DAPABORT
Definition: arm_adi_v5.h:68
#define DP_DPIDR_VERSION_MASK
Definition: arm_adi_v5.h:65
#define DP_SELECT_APSEL
Definition: arm_adi_v5.h:100
swd_special_seq
Definition: arm_adi_v5.h:229
@ DORMANT_TO_JTAG
Definition: arm_adi_v5.h:236
@ JTAG_TO_SWD
Definition: arm_adi_v5.h:231
@ DORMANT_TO_SWD
Definition: arm_adi_v5.h:235
@ LINE_RESET
Definition: arm_adi_v5.h:230
@ JTAG_TO_DORMANT
Definition: arm_adi_v5.h:232
@ SWD_TO_DORMANT
Definition: arm_adi_v5.h:234
@ SWD_TO_JTAG
Definition: arm_adi_v5.h:233
const char * adiv5_dap_name(struct adiv5_dap *self)
Definition: arm_dap.c:56
static bool is_adiv6(const struct adiv5_dap *dap)
Check if DAP is ADIv6.
Definition: arm_adi_v5.h:479
#define DP_TARGETSEL
Definition: arm_adi_v5.h:59
#define DP_DPIDR_VERSION_SHIFT
Definition: arm_adi_v5.h:64
#define DP_SELECT_APBANK
Definition: arm_adi_v5.h:101
static bool dap_is_multidrop(struct adiv5_dap *dap)
Check if SWD multidrop configuration is valid.
Definition: arm_adi_v5.h:712
#define DP_SELECT_DPBANK
Definition: arm_adi_v5.h:102
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:247
static int register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, const struct command_registration *cmds)
Register one or more commands in the specified context, as children of parent (or top-level commends,...
Definition: command.h:268
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
struct esp_usb_jtag __attribute__
Definition: armv8.c:804
static enum reset_types jtag_reset_config
Definition: jtag/core.c:87
enum reset_types jtag_get_reset_config(void)
Definition: jtag/core.c:1734
int adapter_assert_reset(void)
Definition: jtag/core.c:1880
reset_types
Definition: jtag.h:212
@ RESET_SRST_NO_GATING
Definition: jtag.h:221
@ RESET_CNCT_UNDER_SRST
Definition: jtag.h:222
int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Definition: jtag/tcl.c:715
void alive_sleep(uint64_t ms)
Definition: log.c:460
#define ERROR_WAIT
Definition: log.h:162
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:101
#define LOG_WARNING(expr ...)
Definition: log.h:120
#define ERROR_FAIL
Definition: log.h:161
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define LOG_INFO(expr ...)
Definition: log.h:117
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:155
Represents a driver for a debugging interface.
Definition: interface.h:207
const struct swd_driver * swd_ops
Low-level SWD APIs.
Definition: interface.h:345
This represents an ARM Debug Interface (v5) Access Port (AP).
Definition: arm_adi_v5.h:243
uint64_t ap_num
ADIv5: Number of this AP (0~255) ADIv6: Base address of this AP (4k aligned) TODO: to be more coheren...
Definition: arm_adi_v5.h:254
struct adiv5_dap * dap
DAP this AP belongs to.
Definition: arm_adi_v5.h:247
uint32_t memaccess_tck
Configures how many extra tck clocks are added after starting a MEM-AP access before we try to read i...
Definition: arm_adi_v5.h:279
This represents an ARM Debug Interface (v5) Debug Access Port (DAP).
Definition: arm_adi_v5.h:320
struct adiv5_ap ap[DP_APSEL_MAX+1]
Definition: arm_adi_v5.h:336
bool do_reconnect
Signals that an attempt to reestablish communication afresh should be performed before the next acces...
Definition: arm_adi_v5.h:376
uint32_t * last_read
Holds the pointer to the destination word for the last queued read, for use with posted AP read seque...
Definition: arm_adi_v5.h:354
bool switch_through_dormant
Record if enter in SWD required passing through DORMANT.
Definition: arm_adi_v5.h:392
uint32_t multidrop_targetsel
Value to select DP in SWD multidrop mode or DP_TARGETSEL_INVALID.
Definition: arm_adi_v5.h:383
uint64_t select
Cache for DP_SELECT register.
Definition: arm_adi_v5.h:345
unsigned int asize
Definition: arm_adi_v5.h:398
const char * name
Definition: command.h:229
const char * usage
a string listing the options and arguments, required or optional
Definition: command.h:235
Transport-neutral representation of queued DAP transactions, supporting both JTAG and SWD transports.
Definition: arm_adi_v5.h:408
int(* connect)(struct adiv5_dap *dap)
connect operation for SWD
Definition: arm_adi_v5.h:410
Definition: register.h:111
int(* switch_seq)(enum swd_special_seq seq)
Queue a special SWDIO sequence.
Definition: swd.h:264
void(* read_reg)(uint8_t cmd, uint32_t *value, uint32_t ap_delay_hint)
Queued read of an AP or DP register.
Definition: swd.h:274
int(* init)(void)
Initialize the debug link so it can perform SWD operations.
Definition: swd.h:255
int(* run)(void)
Execute any queued transactions and collect the result.
Definition: swd.h:292
void(* write_reg)(uint8_t cmd, uint32_t value, uint32_t ap_delay_hint)
Queued write of an AP or DP register.
Definition: swd.h:284
Definition: psoc6.c:84
Wrapper for transport lifecycle operations.
Definition: transport.h:35
const char * name
Each transport has a unique name, used to select it from among the alternatives.
Definition: transport.h:41
static uint8_t swd_cmd(bool is_read, bool is_ap, uint8_t regnum)
Construct a "cmd" byte, in lSB bit order, which swd_driver.read_reg() and swd_driver....
Definition: swd.h:35
int64_t timeval_ms(void)
struct transport * get_current_transport(void)
Returns the transport currently being used by this debug or programming session.
Definition: transport.c:157
int transport_register(struct transport *new_transport)
Registers a transport.
Definition: transport.c:129
#define NULL
Definition: usb.h:16
uint8_t status[4]
Definition: vdebug.c:17