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

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)