bde1dfb5ee9279814b20dc88b08a9302c6f5f563
[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 }
62 INIT_LIST_HEAD(&dap->cmd_journal);
63 INIT_LIST_HEAD(&dap->cmd_pool);
64 }
65
66 const char *adiv5_dap_name(struct adiv5_dap *self)
67 {
68 struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
69 return obj->name;
70 }
71
72 const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self)
73 {
74 struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
75 return obj->swd;
76 }
77
78 struct adiv5_dap *adiv5_get_dap(struct arm_dap_object *obj)
79 {
80 return &obj->dap;
81 }
82 struct adiv5_dap *dap_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
83 {
84 struct arm_dap_object *obj = NULL;
85 const char *name;
86 bool found = false;
87
88 name = Jim_GetString(o, NULL);
89
90 list_for_each_entry(obj, &all_dap, lh) {
91 if (!strcmp(name, obj->name)) {
92 found = true;
93 break;
94 }
95 }
96
97 if (found)
98 return &obj->dap;
99 return NULL;
100 }
101
102 static int dap_init_all(void)
103 {
104 struct arm_dap_object *obj;
105 int retval;
106
107 LOG_DEBUG("Initializing all DAPs ...");
108
109 list_for_each_entry(obj, &all_dap, lh) {
110 struct adiv5_dap *dap = &obj->dap;
111
112 /* with hla, dap is just a dummy */
113 if (transport_is_hla())
114 continue;
115
116 /* skip taps that are disabled */
117 if (!dap->tap->enabled)
118 continue;
119
120 if (transport_is_swd()) {
121 dap->ops = &swd_dap_ops;
122 obj->swd = adapter_driver->swd_ops;
123 } else if (transport_is_dapdirect_swd()) {
124 dap->ops = adapter_driver->dap_swd_ops;
125 } else if (transport_is_dapdirect_jtag()) {
126 dap->ops = adapter_driver->dap_jtag_ops;
127 } else
128 dap->ops = &jtag_dp_ops;
129
130 retval = dap->ops->connect(dap);
131 if (retval != ERROR_OK)
132 return retval;
133 }
134
135 return ERROR_OK;
136 }
137
138 int dap_cleanup_all(void)
139 {
140 struct arm_dap_object *obj, *tmp;
141 struct adiv5_dap *dap;
142
143 list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
144 dap = &obj->dap;
145 if (dap->ops && dap->ops->quit)
146 dap->ops->quit(dap);
147
148 free(obj->name);
149 free(obj);
150 }
151
152 return ERROR_OK;
153 }
154
155 enum dap_cfg_param {
156 CFG_CHAIN_POSITION,
157 CFG_IGNORE_SYSPWRUPACK,
158 CFG_DP_ID,
159 CFG_INSTANCE_ID,
160 };
161
162 static const struct jim_nvp nvp_config_opts[] = {
163 { .name = "-chain-position", .value = CFG_CHAIN_POSITION },
164 { .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK },
165 { .name = "-dp-id", .value = CFG_DP_ID },
166 { .name = "-instance-id", .value = CFG_INSTANCE_ID },
167 { .name = NULL, .value = -1 }
168 };
169
170 static int dap_configure(struct jim_getopt_info *goi, struct arm_dap_object *dap)
171 {
172 struct jim_nvp *n;
173 int e;
174
175 /* parse config ... */
176 while (goi->argc > 0) {
177 Jim_SetEmptyResult(goi->interp);
178
179 e = jim_getopt_nvp(goi, nvp_config_opts, &n);
180 if (e != JIM_OK) {
181 jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
182 return e;
183 }
184 switch (n->value) {
185 case CFG_CHAIN_POSITION: {
186 Jim_Obj *o_t;
187 e = jim_getopt_obj(goi, &o_t);
188 if (e != JIM_OK)
189 return e;
190
191 struct jtag_tap *tap;
192 tap = jtag_tap_by_jim_obj(goi->interp, o_t);
193 if (!tap) {
194 Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
195 return JIM_ERR;
196 }
197 dap->dap.tap = tap;
198 /* loop for more */
199 break;
200 }
201 case CFG_IGNORE_SYSPWRUPACK:
202 dap->dap.ignore_syspwrupack = true;
203 break;
204 case CFG_DP_ID: {
205 jim_wide w;
206 e = jim_getopt_wide(goi, &w);
207 if (e != JIM_OK) {
208 Jim_SetResultFormatted(goi->interp,
209 "create %s: bad parameter %s",
210 dap->name, n->name);
211 return JIM_ERR;
212 }
213 if (w < 0 || w > DP_TARGETSEL_DPID_MASK) {
214 Jim_SetResultFormatted(goi->interp,
215 "create %s: %s out of range",
216 dap->name, n->name);
217 return JIM_ERR;
218 }
219 dap->dap.multidrop_targetsel =
220 (dap->dap.multidrop_targetsel & DP_TARGETSEL_INSTANCEID_MASK)
221 | (w & DP_TARGETSEL_DPID_MASK);
222 dap->dap.multidrop_dp_id_valid = true;
223 break;
224 }
225 case CFG_INSTANCE_ID: {
226 jim_wide w;
227 e = jim_getopt_wide(goi, &w);
228 if (e != JIM_OK) {
229 Jim_SetResultFormatted(goi->interp,
230 "create %s: bad parameter %s",
231 dap->name, n->name);
232 return JIM_ERR;
233 }
234 if (w < 0 || w > 15) {
235 Jim_SetResultFormatted(goi->interp,
236 "create %s: %s out of range",
237 dap->name, n->name);
238 return JIM_ERR;
239 }
240 dap->dap.multidrop_targetsel =
241 (dap->dap.multidrop_targetsel & DP_TARGETSEL_DPID_MASK)
242 | ((w << DP_TARGETSEL_INSTANCEID_SHIFT) & DP_TARGETSEL_INSTANCEID_MASK);
243 dap->dap.multidrop_instance_id_valid = true;
244 break;
245 }
246 default:
247 break;
248 }
249 }
250
251 return JIM_OK;
252 }
253
254 static int dap_create(struct jim_getopt_info *goi)
255 {
256 struct command_context *cmd_ctx;
257 static struct arm_dap_object *dap;
258 Jim_Obj *new_cmd;
259 Jim_Cmd *cmd;
260 const char *cp;
261 int e;
262
263 cmd_ctx = current_command_context(goi->interp);
264 assert(cmd_ctx);
265
266 if (goi->argc < 3) {
267 Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
268 return JIM_ERR;
269 }
270 /* COMMAND */
271 jim_getopt_obj(goi, &new_cmd);
272 /* does this command exist? */
273 cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_NONE);
274 if (cmd) {
275 cp = Jim_GetString(new_cmd, NULL);
276 Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
277 return JIM_ERR;
278 }
279
280 /* Create it */
281 dap = calloc(1, sizeof(struct arm_dap_object));
282 if (!dap)
283 return JIM_ERR;
284
285 dap_instance_init(&dap->dap);
286
287 cp = Jim_GetString(new_cmd, NULL);
288 dap->name = strdup(cp);
289
290 e = dap_configure(goi, dap);
291 if (e != JIM_OK)
292 goto err;
293
294 if (!dap->dap.tap) {
295 Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
296 e = JIM_ERR;
297 goto err;
298 }
299
300 struct command_registration dap_commands[] = {
301 {
302 .name = cp,
303 .mode = COMMAND_ANY,
304 .help = "dap instance command group",
305 .usage = "",
306 .chain = dap_instance_commands,
307 },
308 COMMAND_REGISTRATION_DONE
309 };
310
311 /* don't expose the instance commands when using hla */
312 if (transport_is_hla())
313 dap_commands[0].chain = NULL;
314
315 e = register_commands_with_data(cmd_ctx, NULL, dap_commands, dap);
316 if (e != ERROR_OK) {
317 e = JIM_ERR;
318 goto err;
319 }
320
321 list_add_tail(&dap->lh, &all_dap);
322
323 return JIM_OK;
324
325 err:
326 free(dap->name);
327 free(dap);
328 return e;
329 }
330
331 static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
332 {
333 struct jim_getopt_info goi;
334 jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
335 if (goi.argc < 2) {
336 Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
337 "<name> [<dap_options> ...]");
338 return JIM_ERR;
339 }
340 return dap_create(&goi);
341 }
342
343 static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
344 {
345 struct arm_dap_object *obj;
346
347 if (argc != 1) {
348 Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
349 return JIM_ERR;
350 }
351 Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
352 list_for_each_entry(obj, &all_dap, lh) {
353 Jim_ListAppendElement(interp, Jim_GetResult(interp),
354 Jim_NewStringObj(interp, obj->name, -1));
355 }
356 return JIM_OK;
357 }
358
359 COMMAND_HANDLER(handle_dap_init)
360 {
361 return dap_init_all();
362 }
363
364 COMMAND_HANDLER(handle_dap_info_command)
365 {
366 struct target *target = get_current_target(CMD_CTX);
367 struct arm *arm = target_to_arm(target);
368 struct adiv5_dap *dap = arm->dap;
369 uint32_t apsel;
370
371 if (!dap) {
372 LOG_ERROR("DAP instance not available. Probably a HLA target...");
373 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
374 }
375
376 switch (CMD_ARGC) {
377 case 0:
378 apsel = dap->apsel;
379 break;
380 case 1:
381 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
382 if (apsel > DP_APSEL_MAX)
383 return ERROR_COMMAND_SYNTAX_ERROR;
384 break;
385 default:
386 return ERROR_COMMAND_SYNTAX_ERROR;
387 }
388
389 return dap_info_command(CMD, &dap->ap[apsel]);
390 }
391
392 static const struct command_registration dap_subcommand_handlers[] = {
393 {
394 .name = "create",
395 .mode = COMMAND_ANY,
396 .jim_handler = jim_dap_create,
397 .usage = "name '-chain-position' name",
398 .help = "Creates a new DAP instance",
399 },
400 {
401 .name = "names",
402 .mode = COMMAND_ANY,
403 .jim_handler = jim_dap_names,
404 .usage = "",
405 .help = "Lists all registered DAP instances by name",
406 },
407 {
408 .name = "init",
409 .mode = COMMAND_ANY,
410 .handler = handle_dap_init,
411 .usage = "",
412 .help = "Initialize all registered DAP instances"
413 },
414 {
415 .name = "info",
416 .handler = handle_dap_info_command,
417 .mode = COMMAND_EXEC,
418 .help = "display ROM table for MEM-AP of current target "
419 "(default currently selected AP)",
420 .usage = "[ap_num]",
421 },
422 COMMAND_REGISTRATION_DONE
423 };
424
425 static const struct command_registration dap_commands[] = {
426 {
427 .name = "dap",
428 .mode = COMMAND_CONFIG,
429 .help = "DAP commands",
430 .chain = dap_subcommand_handlers,
431 .usage = "",
432 },
433 COMMAND_REGISTRATION_DONE
434 };
435
436 int dap_register_commands(struct command_context *cmd_ctx)
437 {
438 return register_commands(cmd_ctx, NULL, dap_commands);
439 }

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)