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

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)