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

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)