]> git.sur5r.net Git - openocd/blob - src/target/adi_v5_swd.c
adi_v5_swd: Improve SWD support
[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, write to the
17  *   Free Software Foundation, Inc.,
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  ***************************************************************************/
20
21 /**
22  * @file
23  * Utilities to support ARM "Serial Wire Debug" (SWD), a low pin-count debug
24  * link protocol used in cases where JTAG is not wanted.  This is coupled to
25  * recent versions of ARM's "CoreSight" debug framework.  This specific code
26  * is a transport level interface, with "target/arm_adi_v5.[hc]" code
27  * understanding operation semantics, shared with the JTAG transport.
28  *
29  * Single-DAP support only.
30  *
31  * for details, see "ARM IHI 0031A"
32  * ARM Debug Interface v5 Architecture Specification
33  * especially section 5.3 for SWD protocol
34  *
35  * On many chips (most current Cortex-M3 parts) SWD is a run-time alternative
36  * to JTAG.  Boards may support one or both.  There are also SWD-only chips,
37  * (using SW-DP not SWJ-DP).
38  *
39  * Even boards that also support JTAG can benefit from SWD support, because
40  * usually there's no way to access the SWO trace view mechanism in JTAG mode.
41  * That is, trace access may require SWD support.
42  *
43  */
44
45 #ifdef HAVE_CONFIG_H
46 #include "config.h"
47 #endif
48
49 #include "arm.h"
50 #include "arm_adi_v5.h"
51 #include <helper/time_support.h>
52
53 #include <transport/transport.h>
54 #include <jtag/interface.h>
55
56 #include <jtag/swd.h>
57
58 /* YUK! - but this is currently a global.... */
59 extern struct jtag_interface *jtag_interface;
60
61 static int (swd_queue_dp_write)(struct adiv5_dap *dap, unsigned reg,
62                 uint32_t data);
63
64 static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
65 {
66         const struct swd_driver *swd = jtag_interface->swd;
67         assert(swd);
68
69         return swd->write_reg(swd_cmd(false,  false, DP_ABORT),
70                 STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR);
71 }
72
73 /** Select the DP register bank matching bits 7:4 of reg. */
74 static int swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg)
75 {
76         uint32_t select_dp_bank = (reg & 0x000000F0) >> 4;
77
78         if (reg == DP_SELECT)
79                 return ERROR_OK;
80
81         if (select_dp_bank == dap->dp_bank_value)
82                 return ERROR_OK;
83
84         dap->dp_bank_value = select_dp_bank;
85         select_dp_bank |= dap->ap_current | dap->ap_bank_value;
86
87         return swd_queue_dp_write(dap, DP_SELECT, select_dp_bank);
88 }
89
90 static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
91                 uint32_t *data)
92 {
93         int retval;
94         /* REVISIT status return vs ack ... */
95         const struct swd_driver *swd = jtag_interface->swd;
96         assert(swd);
97
98         retval = swd_queue_dp_bankselect(dap, reg);
99         if (retval != ERROR_OK)
100                 return retval;
101
102         retval = swd->read_reg(swd_cmd(true,  false, reg), data);
103
104         if (retval != ERROR_OK) {
105                 /* fault response */
106                 uint8_t ack = retval & 0xff;
107                 swd_queue_ap_abort(dap, &ack);
108         }
109
110         return retval;
111 }
112
113 static int swd_queue_idcode_read(struct adiv5_dap *dap,
114                 uint8_t *ack, uint32_t *data)
115 {
116         int status = swd_queue_dp_read(dap, DP_IDCODE, data);
117         if (status < 0)
118                 return status;
119         *ack = status;
120         /* ?? */
121         return ERROR_OK;
122 }
123
124 static int (swd_queue_dp_write)(struct adiv5_dap *dap, unsigned reg,
125                 uint32_t data)
126 {
127         int retval;
128         /* REVISIT status return vs ack ... */
129         const struct swd_driver *swd = jtag_interface->swd;
130         assert(swd);
131
132         retval = swd_queue_dp_bankselect(dap, reg);
133         if (retval != ERROR_OK)
134                 return retval;
135
136         retval = swd->write_reg(swd_cmd(false,  false, reg), data);
137
138         if (retval != ERROR_OK) {
139                 /* fault response */
140                 uint8_t ack = retval & 0xff;
141                 swd_queue_ap_abort(dap, &ack);
142         }
143
144         return retval;
145 }
146
147 /** Select the AP register bank matching bits 7:4 of reg. */
148 static int swd_queue_ap_bankselect(struct adiv5_dap *dap, unsigned reg)
149 {
150         uint32_t select_ap_bank = reg & 0x000000F0;
151
152         if (select_ap_bank == dap->ap_bank_value)
153                 return ERROR_OK;
154
155         dap->ap_bank_value = select_ap_bank;
156         select_ap_bank |= dap->ap_current | dap->dp_bank_value;
157
158         return swd_queue_dp_write(dap, DP_SELECT, select_ap_bank);
159 }
160
161 static int (swd_queue_ap_read)(struct adiv5_dap *dap, unsigned reg,
162                 uint32_t *data)
163 {
164         /* REVISIT status return ... */
165         const struct swd_driver *swd = jtag_interface->swd;
166         assert(swd);
167
168         int retval = swd_queue_ap_bankselect(dap, reg);
169         if (retval != ERROR_OK)
170                 return retval;
171
172         retval = swd->read_reg(swd_cmd(true,  true, reg), data);
173
174         if (retval != ERROR_OK) {
175                 /* fault response */
176                 uint8_t ack = retval & 0xff;
177                 swd_queue_ap_abort(dap, &ack);
178         }
179
180         return retval;
181 }
182
183 static int (swd_queue_ap_write)(struct adiv5_dap *dap, unsigned reg,
184                 uint32_t data)
185 {
186         /* REVISIT status return ... */
187         const struct swd_driver *swd = jtag_interface->swd;
188         assert(swd);
189
190         int retval = swd_queue_ap_bankselect(dap, reg);
191         if (retval != ERROR_OK)
192                 return retval;
193
194         retval = swd->write_reg(swd_cmd(false,  true, reg), data);
195
196         if (retval != ERROR_OK) {
197                 /* fault response */
198                 uint8_t ack = retval & 0xff;
199                 swd_queue_ap_abort(dap, &ack);
200         }
201
202         return retval;
203 }
204
205 /** Executes all queued DAP operations. */
206 static int swd_run(struct adiv5_dap *dap)
207 {
208         /* for now the SWD interface hard-wires a zero-size queue.  */
209
210         /* FIXME but we still need to check and scrub
211          * any hardware errors ...
212          */
213         return ERROR_OK;
214 }
215
216 const struct dap_ops swd_dap_ops = {
217         .is_swd = true,
218
219         .queue_idcode_read = swd_queue_idcode_read,
220         .queue_dp_read = swd_queue_dp_read,
221         .queue_dp_write = swd_queue_dp_write,
222         .queue_ap_read = swd_queue_ap_read,
223         .queue_ap_write = swd_queue_ap_write,
224         .queue_ap_abort = swd_queue_ap_abort,
225         .run = swd_run,
226 };
227
228 /*
229  * This represents the bits which must be sent out on TMS/SWDIO to
230  * switch a DAP implemented using an SWJ-DP module into SWD mode.
231  * These bits are stored (and transmitted) LSB-first.
232  *
233  * See the DAP-Lite specification, section 2.2.5 for information
234  * about making the debug link select SWD or JTAG.  (Similar info
235  * is in a few other ARM documents.)
236  */
237 static const uint8_t jtag2swd_bitseq[] = {
238         /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
239          * putting both JTAG and SWD logic into reset state.
240          */
241         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
242         /* Switching sequence enables SWD and disables JTAG
243          * NOTE: bits in the DP's IDCODE may expose the need for
244          * an old/obsolete/deprecated sequence (0xb6 0xed).
245          */
246         0x9e, 0xe7,
247         /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high,
248          * putting both JTAG and SWD logic into reset state.
249          */
250         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
251 };
252
253 /**
254  * Put the debug link into SWD mode, if the target supports it.
255  * The link's initial mode may be either JTAG (for example,
256  * with SWJ-DP after reset) or SWD.
257  *
258  * @param target Enters SWD mode (if possible).
259  *
260  * Note that targets using the JTAG-DP do not support SWD, and that
261  * some targets which could otherwise support it may have have been
262  * configured to disable SWD signaling
263  *
264  * @return ERROR_OK or else a fault code.
265  */
266 int dap_to_swd(struct target *target)
267 {
268         struct arm *arm = target_to_arm(target);
269         int retval;
270
271         LOG_DEBUG("Enter SWD mode");
272
273         /* REVISIT it's ugly to need to make calls to a "jtag"
274          * subsystem if the link may not be in JTAG mode...
275          */
276
277         retval =  jtag_add_tms_seq(8 * sizeof(jtag2swd_bitseq),
278                         jtag2swd_bitseq, TAP_INVALID);
279         if (retval == ERROR_OK)
280                 retval = jtag_execute_queue();
281
282         /* set up the DAP's ops vector for SWD mode. */
283         arm->dap->ops = &swd_dap_ops;
284
285         return retval;
286 }
287
288 COMMAND_HANDLER(handle_swd_wcr)
289 {
290         int retval;
291         struct target *target = get_current_target(CMD_CTX);
292         struct arm *arm = target_to_arm(target);
293         struct adiv5_dap *dap = arm->dap;
294         uint32_t wcr;
295         unsigned trn, scale = 0;
296
297         switch (CMD_ARGC) {
298         /* no-args: just dump state */
299         case 0:
300                 /*retval = swd_queue_dp_read(dap, DP_WCR, &wcr); */
301                 retval = dap_queue_dp_read(dap, DP_WCR, &wcr);
302                 if (retval == ERROR_OK)
303                         dap->ops->run(dap);
304                 if (retval != ERROR_OK) {
305                         LOG_ERROR("can't read WCR?");
306                         return retval;
307                 }
308
309                 command_print(CMD_CTX,
310                         "turnaround=%" PRIu32 ", prescale=%" PRIu32,
311                         WCR_TO_TRN(wcr),
312                         WCR_TO_PRESCALE(wcr));
313         return ERROR_OK;
314
315         case 2:         /* TRN and prescale */
316                 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], scale);
317                 if (scale > 7) {
318                         LOG_ERROR("prescale %d is too big", scale);
319                         return ERROR_FAIL;
320                 }
321                 /* FALL THROUGH */
322
323         case 1:         /* TRN only */
324                 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], trn);
325                 if (trn < 1 || trn > 4) {
326                         LOG_ERROR("turnaround %d is invalid", trn);
327                         return ERROR_FAIL;
328                 }
329
330                 wcr = ((trn - 1) << 8) | scale;
331                 /* FIXME
332                  * write WCR ...
333                  * then, re-init adapter with new TRN
334                  */
335                 LOG_ERROR("can't yet modify WCR");
336                 return ERROR_FAIL;
337
338         default:        /* too many arguments */
339                 return ERROR_COMMAND_SYNTAX_ERROR;
340         }
341 }
342
343 static const struct command_registration swd_commands[] = {
344         {
345                 /*
346                  * Set up SWD and JTAG targets identically, unless/until
347                  * infrastructure improves ...  meanwhile, ignore all
348                  * JTAG-specific stuff like IR length for SWD.
349                  *
350                  * REVISIT can we verify "just one SWD DAP" here/early?
351                  */
352                 .name = "newdap",
353                 .jim_handler = jim_jtag_newtap,
354                 .mode = COMMAND_CONFIG,
355                 .help = "declare a new SWD DAP"
356         },
357         {
358                 .name = "wcr",
359                 .handler = handle_swd_wcr,
360                 .mode = COMMAND_ANY,
361                 .help = "display or update DAP's WCR register",
362                 .usage = "turnaround (1..4), prescale (0..7)",
363         },
364
365         /* REVISIT -- add a command for SWV trace on/off */
366         COMMAND_REGISTRATION_DONE
367 };
368
369 static const struct command_registration swd_handlers[] = {
370         {
371                 .name = "swd",
372                 .mode = COMMAND_ANY,
373                 .help = "SWD command group",
374                 .chain = swd_commands,
375         },
376         COMMAND_REGISTRATION_DONE
377 };
378
379 static int swd_select(struct command_context *ctx)
380 {
381         int retval;
382
383         retval = register_commands(ctx, NULL, swd_handlers);
384
385         if (retval != ERROR_OK)
386                 return retval;
387
388         const struct swd_driver *swd = jtag_interface->swd;
389
390          /* be sure driver is in SWD mode; start
391           * with hardware default TRN (1), it can be changed later
392           */
393         if (!swd || !swd->read_reg || !swd->write_reg || !swd->init) {
394                 LOG_DEBUG("no SWD driver?");
395                 return ERROR_FAIL;
396         }
397
398         retval = swd->init(1);
399         if (retval != ERROR_OK) {
400                 LOG_DEBUG("can't init SWD driver");
401                 return retval;
402         }
403
404         /* force DAP into SWD mode (not JTAG) */
405         /*retval = dap_to_swd(target);*/
406
407         if (ctx->current_target) {
408                 /* force DAP into SWD mode (not JTAG) */
409                 struct target *target = get_current_target(ctx);
410                 retval = dap_to_swd(target);
411         }
412
413         return retval;
414 }
415
416 static int swd_init(struct command_context *ctx)
417 {
418         struct target *target = get_current_target(ctx);
419         struct arm *arm = target_to_arm(target);
420         struct adiv5_dap *dap = arm->dap;
421         uint32_t idcode;
422         int status;
423
424         /* Force the DAP's ops vector for SWD mode.
425          * messy - is there a better way? */
426         arm->dap->ops = &swd_dap_ops;
427
428         /* FIXME validate transport config ... is the
429          * configured DAP present (check IDCODE)?
430          * Is *only* one DAP configured?
431          *
432          * MUST READ IDCODE
433          */
434
435  /* Note, debugport_init() does setup too */
436
437         uint8_t ack;
438
439         status = swd_queue_idcode_read(dap, &ack, &idcode);
440
441         if (status == ERROR_OK)
442                 LOG_INFO("SWD IDCODE %#8.8" PRIx32, idcode);
443
444         /* force clear all sticky faults */
445         swd_queue_ap_abort(dap, &ack);
446
447         /* this is a workaround to get polling working */
448         jtag_add_reset(0, 0);
449
450         return status;
451 }
452
453 static struct transport swd_transport = {
454         .name = "swd",
455         .select = swd_select,
456         .init = swd_init,
457 };
458
459 static void swd_constructor(void) __attribute__((constructor));
460 static void swd_constructor(void)
461 {
462         transport_register(&swd_transport);
463 }
464
465 /** Returns true if the current debug session
466  * is using SWD as its transport.
467  */
468 bool transport_is_swd(void)
469 {
470         return get_current_transport() == &swd_transport;
471 }