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

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)