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

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)