46e054e69578745a30d30d66d57322ce328583ad
[openocd.git] / src / target / arm_dap.c
1 /***************************************************************************
2 * Copyright (C) 2016 by Matthias Welwarsky *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdlib.h>
25 #include <stdint.h>
26 #include "target/arm_adi_v5.h"
27 #include "target/arm.h"
28 #include "helper/list.h"
29 #include "helper/command.h"
30 #include "transport/transport.h"
31 #include "jtag/interface.h"
32
33 static LIST_HEAD(all_dap);
34
35 extern const struct dap_ops swd_dap_ops;
36 extern const struct dap_ops jtag_dp_ops;
37 extern struct adapter_driver *adapter_driver;
38
39 /* DAP command support */
40 struct arm_dap_object {
41 struct list_head lh;
42 struct adiv5_dap dap;
43 char *name;
44 const struct swd_driver *swd;
45 };
46
47 static void dap_instance_init(struct adiv5_dap *dap)
48 {
49 int i;
50 /* Set up with safe defaults */
51 for (i = 0; i <= DP_APSEL_MAX; i++) {
52 dap->ap[i].dap = dap;
53 dap->ap[i].ap_num = i;
54 /* memaccess_tck max is 255 */
55 dap->ap[i].memaccess_tck = 255;
56 /* Number of bits for tar autoincrement, impl. dep. at least 10 */
57 dap->ap[i].tar_autoincr_block = (1<<10);
58 /* default CSW value */
59 dap->ap[i].csw_default = CSW_AHB_DEFAULT;
60 dap->ap[i].cfg_reg = MEM_AP_REG_CFG_INVALID; /* mem_ap configuration reg (large physical addr, etc.) */
61 dap->ap[i].refcount = 0;
62 dap->ap[i].config_ap_never_release = false;
63 }
64 INIT_LIST_HEAD(&dap->cmd_journal);
65 INIT_LIST_HEAD(&dap->cmd_pool);
66 }
67
68 const char *adiv5_dap_name(struct adiv5_dap *self)
69 {
70 struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
71 return obj->name;
72 }
73
74 const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self)
75 {
76 struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
77 return obj->swd;
78 }
79
80 struct adiv5_dap *adiv5_get_dap(struct arm_dap_object *obj)
81 {
82 return &obj->dap;
83 }
84 struct adiv5_dap *dap_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
85 {
86 struct arm_dap_object *obj = NULL;
87 const char *name;
88 bool found = false;
89
90 name = Jim_GetString(o, NULL);
91
92 list_for_each_entry(obj, &all_dap, lh) {
93 if (!strcmp(name, obj->name)) {
94 found = true;
95 break;
96 }
97 }
98
99 if (found)
100 return &obj->dap;
101 return NULL;
102 }
103
104 static int dap_init_all(void)
105 {
106 struct arm_dap_object *obj;
107 int retval;
108
109 LOG_DEBUG("Initializing all DAPs ...");
110
111 list_for_each_entry(obj, &all_dap, lh) {
112 struct adiv5_dap *dap = &obj->dap;
113
114 /* with hla, dap is just a dummy */
115 if (transport_is_hla())
116 continue;
117
118 /* skip taps that are disabled */
119 if (!dap->tap->enabled)
120 continue;
121
122 if (transport_is_swd()) {
123 dap->ops = &swd_dap_ops;
124 obj->swd = adapter_driver->swd_ops;
125 } else if (transport_is_dapdirect_swd()) {
126 dap->ops = adapter_driver->dap_swd_ops;
127 } else if (transport_is_dapdirect_jtag()) {
128 dap->ops = adapter_driver->dap_jtag_ops;
129 } else
130 dap->ops = &jtag_dp_ops;
131
132 retval = dap->ops->connect(dap);
133 if (retval != ERROR_OK)
134 return retval;
135 }
136
137 return ERROR_OK;
138 }
139
140 int dap_cleanup_all(void)
141 {
142 struct arm_dap_object *obj, *tmp;
143 struct adiv5_dap *dap;
144
145 list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
146 dap = &obj->dap;
147 for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) {
148 if (dap->ap[i].refcount != 0)
149 LOG_ERROR("BUG: refcount AP#%u still %u at exit", i, dap->ap[i].refcount);
150 }
151 if (dap->ops && dap->ops->quit)
152 dap->ops->quit(dap);
153
154 free(obj->name);
155 free(obj);
156 }
157
158 return ERROR_OK;
159 }
160
161 enum dap_cfg_param {
162 CFG_CHAIN_POSITION,
163 CFG_IGNORE_SYSPWRUPACK,
164 CFG_DP_ID,
165 CFG_INSTANCE_ID,
166 };
167
168 static const struct jim_nvp nvp_config_opts[] = {
169 { .name = "-chain-position", .value = CFG_CHAIN_POSITION },
170 { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK },
171 { .name = "-dp-id", .value = CFG_DP_ID },
172 { .name = "-instance-id", .value = CFG_INSTANCE_ID },
173 { .name = NULL, .value = -1 }
174 };
175
176 static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap)
177 {
178 struct jim_nvp *n;
179 int e;
180
181 /* parse config ... */
182 while (goi->argc > 0) {
183 Jim_SetEmptyResult(goi->interp);
184
185 e = jim_getopt_nvp(goi, nvp_config_opts, &n);
186 if (e != JIM_OK) {
187 jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
188 return e;
189 }
190 switch (n->value) {
191 case CFG_CHAIN_POSITION: {
192 Jim_Obj *o_t;
193 e = jim_getopt_obj(goi, &o_t);
194 if (e != JIM_OK)
195 return e;
196
197 struct jtag_tap *tap;
198 tap = jtag_tap_by_jim_obj(goi->interp, o_t);
199 if (!tap) {
200 Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
201 return JIM_ERR;
202 }
203 dap->dap.tap = tap;
204 /* loop for more */
205 break;
206 }
207 case CFG_IGNORE_SYSPWRUPACK:
208 dap->dap.ignore_syspwrupack = true;
209 break;
210 case CFG_DP_ID: {
211 jim_wide w;
212 e = jim_getopt_wide(goi, &w);
213 if (e != JIM_OK) {
214 Jim_SetResultFormatted(goi->interp,
215 "create %s: bad parameter %s",
216 dap->name, n->name);
217 return JIM_ERR;
218 }
219 if (w < 0 || w > DP_TARGETSEL_DPID_MASK) {
220 Jim_SetResultFormatted(goi->interp,
221 "create %s: %s out of range",
222 dap->name, n->name);
223 return JIM_ERR;
224 }
225 dap->dap.multidrop_targetsel =
226 (dap->dap.multidrop_targetsel & DP_TARGETSEL_INSTANCEID_MASK)
227 | (w & DP_TARGETSEL_DPID_MASK);
228 dap->dap.multidrop_dp_id_valid = true;
229 break;
230 }
231 case CFG_INSTANCE_ID: {
232 jim_wide w;
233 e = jim_getopt_wide(goi, &w);
234 if (e != JIM_OK) {
235 Jim_SetResultFormatted(goi->interp,
236 "create %s: bad parameter %s",
237 dap->name, n->name);
238 return JIM_ERR;
239 }
240 if (w < 0 || w > 15) {
241 Jim_SetResultFormatted(goi->interp,
242 "create %s: %s out of range",
243 dap->name, n->name);
244 return JIM_ERR;
245 }
246 dap->dap.multidrop_targetsel =
247 (dap->dap.multidrop_targetsel & DP_TARGETSEL_DPID_MASK)
248 | ((w << DP_TARGETSEL_INSTANCEID_SHIFT) & DP_TARGETSEL_INSTANCEID_MASK);
249 dap->dap.multidrop_instance_id_valid = true;
250 break;
251 }
252 default:
253 break;
254 }
255 }
256
257 return JIM_OK;
258 }
259
260 static int dap_check_config(struct adiv5_dap *dap)
261 {
262 if (transport_is_jtag() || transport_is_dapdirect_jtag() || transport_is_hla())
263 return ERROR_OK;
264
265 struct arm_dap_object *obj;
266 bool new_multidrop = dap_is_multidrop(dap);
267 bool had_multidrop = new_multidrop;
268 uint32_t targetsel = dap->multidrop_targetsel;
269 unsigned int non_multidrop_count = had_multidrop ? 0 : 1;
270
271 list_for_each_entry(obj, &all_dap, lh) {
272 struct adiv5_dap *dap_it = &obj->dap;
273
274 if (transport_is_swd()) {
275 if (dap_is_multidrop(dap_it)) {
276 had_multidrop = true;
277 if (new_multidrop && dap_it->multidrop_targetsel == targetsel) {
278 uint32_t dp_id = targetsel & DP_TARGETSEL_DPID_MASK;
279 uint32_t instance_id = targetsel >> DP_TARGETSEL_INSTANCEID_SHIFT;
280 LOG_ERROR("%s and %s have the same multidrop selectors -dp-id 0x%08"
281 PRIx32 " and -instance-id 0x%" PRIx32,
282 obj->name, adiv5_dap_name(dap),
283 dp_id, instance_id);
284 return ERROR_FAIL;
285 }
286 } else {
287 non_multidrop_count++;
288 }
289 } else if (transport_is_dapdirect_swd()) {
290 non_multidrop_count++;
291 }
292 }
293
294 if (non_multidrop_count > 1) {
295 LOG_ERROR("Two or more SWD non multidrop DAPs are not supported");
296 return ERROR_FAIL;
297 }
298 if (had_multidrop && non_multidrop_count) {
299 LOG_ERROR("Mixing of SWD multidrop DAPs and non multidrop DAPs is not supported");
300 return ERROR_FAIL;
301 }
302
303 return ERROR_OK;
304 }
305
306 static int dap_create(struct jim_getopt_info *goi)
307 {
308 struct command_context *cmd_ctx;
309 static struct arm_dap_object *dap;
310 Jim_Obj *new_cmd;
311 Jim_Cmd *cmd;
312 const char *cp;
313 int e;
314
315 cmd_ctx = current_command_context(goi->interp);
316 assert(cmd_ctx);
317
318 if (goi->argc < 3) {
319 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
320 return JIM_ERR;
321 }
322 /* COMMAND */
323 jim_getopt_obj(goi, &new_cmd);
324 /* does this command exist? */
325 cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
326 if (cmd) {
327 cp = Jim_GetString(new_cmd, NULL);
328 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
329 return JIM_ERR;
330 }
331
332 /* Create it */
333 dap = calloc(1, sizeof(struct arm_dap_object));
334 if (!dap)
335 return JIM_ERR;
336
337 dap_instance_init(&dap->dap);
338
339 cp = Jim_GetString(new_cmd, NULL);
340 dap->name = strdup(cp);
341
342 e = dap_configure(goi, dap);
343 if (e != JIM_OK)
344 goto err;
345
346 if (!dap->dap.tap) {
347 Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
348 e = JIM_ERR;
349 goto err;
350 }
351
352 e = dap_check_config(&dap->dap);
353 if (e != ERROR_OK) {
354 e = JIM_ERR;
355 goto err;
356 }
357
358 struct command_registration dap_create_commands[] = {
359 {
360 .name = cp,
361 .mode = COMMAND_ANY,
362 .help = "dap instance command group",
363 .usage = "",
364 .chain = dap_instance_commands,
365 },
366 COMMAND_REGISTRATION_DONE
367 };
368
369 /* don't expose the instance commands when using hla */
370 if (transport_is_hla())
371 dap_create_commands[0].chain = NULL;
372
373 e = register_commands_with_data(cmd_ctx, NULL, dap_create_commands, dap);
374 if (e != ERROR_OK) {
375 e = JIM_ERR;
376 goto err;
377 }
378
379 list_add_tail(&dap->lh, &all_dap);
380
381 return JIM_OK;
382
383 err:
384 free(dap->name);
385 free(dap);
386 return e;
387 }
388
389 static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
390 {
391 struct jim_getopt_info goi;
392 jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
393 if (goi.argc < 2) {
394 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
395 "<name> [<dap_options> ...]");
396 return JIM_ERR;
397 }
398 return dap_create(&goi);
399 }
400
401 static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
402 {
403 struct arm_dap_object *obj;
404
405 if (argc != 1) {
406 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
407 return JIM_ERR;
408 }
409 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
410 list_for_each_entry(obj, &all_dap, lh) {
411 Jim_ListAppendElement(interp, Jim_GetResult(interp),
412 Jim_NewStringObj(interp, obj->name, -1));
413 }
414 return JIM_OK;
415 }
416
417 COMMAND_HANDLER(handle_dap_init)
418 {
419 return dap_init_all();
420 }
421
422 COMMAND_HANDLER(handle_dap_info_command)
423 {
424 struct target *target = get_current_target(CMD_CTX);
425 struct arm *arm = target_to_arm(target);
426 struct adiv5_dap *dap = arm->dap;
427 uint32_t apsel;
428
429 if (!dap) {
430 LOG_ERROR("DAP instance not available. Probably a HLA target...");
431 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
432 }
433
434 switch (CMD_ARGC) {
435 case 0:
436 apsel = dap->apsel;
437 break;
438 case 1:
439 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
440 if (apsel > DP_APSEL_MAX)
441 return ERROR_COMMAND_SYNTAX_ERROR;
442 break;
443 default:
444 return ERROR_COMMAND_SYNTAX_ERROR;
445 }
446
447 struct adiv5_ap *ap = dap_get_ap(dap, apsel);
448 if (!ap) {
449 command_print(CMD, "Cannot get AP");
450 return ERROR_FAIL;
451 }
452 int retval = dap_info_command(CMD, ap);
453 dap_put_ap(ap);
454 return retval;
455 }
456
457 static const struct command_registration dap_subcommand_handlers[] = {
458 {
459 .name = "create",
460 .mode = COMMAND_ANY,
461 .jim_handler = jim_dap_create,
462 .usage = "name '-chain-position' name",
463 .help = "Creates a new DAP instance",
464 },
465 {
466 .name = "names",
467 .mode = COMMAND_ANY,
468 .jim_handler = jim_dap_names,
469 .usage = "",
470 .help = "Lists all registered DAP instances by name",
471 },
472 {
473 .name = "init",
474 .mode = COMMAND_ANY,
475 .handler = handle_dap_init,
476 .usage = "",
477 .help = "Initialize all registered DAP instances"
478 },
479 {
480 .name = "info",
481 .handler = handle_dap_info_command,
482 .mode = COMMAND_EXEC,
483 .help = "display ROM table for MEM-AP of current target "
484 "(default currently selected AP)",
485 .usage = "[ap_num]",
486 },
487 COMMAND_REGISTRATION_DONE
488 };
489
490 static const struct command_registration dap_commands[] = {
491 {
492 .name = "dap",
493 .mode = COMMAND_CONFIG,
494 .help = "DAP commands",
495 .chain = dap_subcommand_handlers,
496 .usage = "",
497 },
498 COMMAND_REGISTRATION_DONE
499 };
500
501 int dap_register_commands(struct command_context *cmd_ctx)
502 {
503 return register_commands(cmd_ctx, NULL, dap_commands);
504 }

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)