drivers/cmsis-dap: speed up sending multiple HID requests
[openocd.git] / src / jtag / drivers / driver.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007-2010 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * Copyright (C) 2009 SoftPLC Corporation *
9 * http://softplc.com *
10 * dick@softplc.com *
11 * *
12 * Copyright (C) 2009 Zachary T Welch *
13 * zw@superlucidity.net *
14 * *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
19 * *
20 * This program is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
23 * GNU General Public License for more details. *
24 * *
25 * You should have received a copy of the GNU General Public License *
26 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
27 ***************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <jtag/jtag.h>
34 #include <jtag/interface.h>
35 #include <jtag/commands.h>
36 #include <jtag/minidriver.h>
37 #include <helper/command.h>
38
39 struct jtag_callback_entry {
40 struct jtag_callback_entry *next;
41
42 jtag_callback_t callback;
43 jtag_callback_data_t data0;
44 jtag_callback_data_t data1;
45 jtag_callback_data_t data2;
46 jtag_callback_data_t data3;
47 };
48
49 static struct jtag_callback_entry *jtag_callback_queue_head;
50 static struct jtag_callback_entry *jtag_callback_queue_tail;
51
52 static void jtag_callback_queue_reset(void)
53 {
54 jtag_callback_queue_head = NULL;
55 jtag_callback_queue_tail = NULL;
56 }
57
58 /**
59 * see jtag_add_ir_scan()
60 *
61 */
62 int interface_jtag_add_ir_scan(struct jtag_tap *active,
63 const struct scan_field *in_fields, tap_state_t state)
64 {
65 size_t num_taps = jtag_tap_count_enabled();
66
67 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
68 struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
69 struct scan_field *out_fields = cmd_queue_alloc(num_taps * sizeof(struct scan_field));
70
71 jtag_queue_command(cmd);
72
73 cmd->type = JTAG_SCAN;
74 cmd->cmd.scan = scan;
75
76 scan->ir_scan = true;
77 scan->num_fields = num_taps; /* one field per device */
78 scan->fields = out_fields;
79 scan->end_state = state;
80
81 struct scan_field *field = out_fields; /* keep track where we insert data */
82
83 /* loop over all enabled TAPs */
84
85 for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) {
86 /* search the input field list for fields for the current TAP */
87
88 if (tap == active) {
89 /* if TAP is listed in input fields, copy the value */
90 tap->bypass = 0;
91
92 jtag_scan_field_clone(field, in_fields);
93 } else {
94 /* if a TAP isn't listed in input fields, set it to BYPASS */
95
96 tap->bypass = 1;
97
98 field->num_bits = tap->ir_length;
99 field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
100 field->in_value = NULL; /* do not collect input for tap's in bypass */
101 }
102
103 /* update device information */
104 buf_cpy(field->out_value, tap->cur_instr, tap->ir_length);
105
106 field++;
107 }
108 /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
109 assert(field == out_fields + num_taps);
110
111 return ERROR_OK;
112 }
113
114 /**
115 * see jtag_add_dr_scan()
116 *
117 */
118 int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields,
119 const struct scan_field *in_fields, tap_state_t state)
120 {
121 /* count devices in bypass */
122
123 size_t bypass_devices = 0;
124
125 for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) {
126 if (tap->bypass)
127 bypass_devices++;
128 }
129
130 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
131 struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
132 struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
133
134 jtag_queue_command(cmd);
135
136 cmd->type = JTAG_SCAN;
137 cmd->cmd.scan = scan;
138
139 scan->ir_scan = false;
140 scan->num_fields = in_num_fields + bypass_devices;
141 scan->fields = out_fields;
142 scan->end_state = state;
143
144 struct scan_field *field = out_fields; /* keep track where we insert data */
145
146 /* loop over all enabled TAPs */
147
148 for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap != NULL; tap = jtag_tap_next_enabled(tap)) {
149 /* if TAP is not bypassed insert matching input fields */
150
151 if (!tap->bypass) {
152 assert(active == tap);
153 #ifndef NDEBUG
154 /* remember initial position for assert() */
155 struct scan_field *start_field = field;
156 #endif /* NDEBUG */
157
158 for (int j = 0; j < in_num_fields; j++) {
159 jtag_scan_field_clone(field, in_fields + j);
160
161 field++;
162 }
163
164 assert(field > start_field); /* must have at least one input field per not bypassed TAP */
165 }
166
167 /* if a TAP is bypassed, generated a dummy bit*/
168 else {
169 field->num_bits = 1;
170 field->out_value = NULL;
171 field->in_value = NULL;
172
173 field++;
174 }
175 }
176
177 assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */
178
179 return ERROR_OK;
180 }
181
182 static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits,
183 uint8_t *in_bits, tap_state_t state, bool ir_scan)
184 {
185 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
186 struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
187 struct scan_field *out_fields = cmd_queue_alloc(sizeof(struct scan_field));
188
189 jtag_queue_command(cmd);
190
191 cmd->type = JTAG_SCAN;
192 cmd->cmd.scan = scan;
193
194 scan->ir_scan = ir_scan;
195 scan->num_fields = 1;
196 scan->fields = out_fields;
197 scan->end_state = state;
198
199 out_fields->num_bits = num_bits;
200 out_fields->out_value = buf_cpy(out_bits, cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
201 out_fields->in_value = in_bits;
202
203 return ERROR_OK;
204 }
205
206 int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
207 {
208 return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false);
209 }
210
211 int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
212 {
213 return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true);
214 }
215
216 int interface_jtag_add_tlr(void)
217 {
218 tap_state_t state = TAP_RESET;
219
220 /* allocate memory for a new list member */
221 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
222
223 jtag_queue_command(cmd);
224
225 cmd->type = JTAG_TLR_RESET;
226
227 cmd->cmd.statemove = cmd_queue_alloc(sizeof(struct statemove_command));
228 cmd->cmd.statemove->end_state = state;
229
230 return ERROR_OK;
231 }
232
233 int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
234 {
235 struct jtag_command *cmd;
236
237 cmd = cmd_queue_alloc(sizeof(struct jtag_command));
238 if (cmd == NULL)
239 return ERROR_FAIL;
240
241 cmd->type = JTAG_TMS;
242 cmd->cmd.tms = cmd_queue_alloc(sizeof(*cmd->cmd.tms));
243 if (!cmd->cmd.tms)
244 return ERROR_FAIL;
245
246 /* copy the bits; our caller doesn't guarantee they'll persist */
247 cmd->cmd.tms->num_bits = num_bits;
248 cmd->cmd.tms->bits = buf_cpy(seq,
249 cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
250 if (!cmd->cmd.tms->bits)
251 return ERROR_FAIL;
252
253 jtag_queue_command(cmd);
254
255 return ERROR_OK;
256 }
257
258 int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
259 {
260 /* allocate memory for a new list member */
261 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
262
263 jtag_queue_command(cmd);
264
265 cmd->type = JTAG_PATHMOVE;
266
267 cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command));
268 cmd->cmd.pathmove->num_states = num_states;
269 cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
270
271 for (int i = 0; i < num_states; i++)
272 cmd->cmd.pathmove->path[i] = path[i];
273
274 return ERROR_OK;
275 }
276
277 int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
278 {
279 /* allocate memory for a new list member */
280 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
281
282 jtag_queue_command(cmd);
283
284 cmd->type = JTAG_RUNTEST;
285
286 cmd->cmd.runtest = cmd_queue_alloc(sizeof(struct runtest_command));
287 cmd->cmd.runtest->num_cycles = num_cycles;
288 cmd->cmd.runtest->end_state = state;
289
290 return ERROR_OK;
291 }
292
293 int interface_jtag_add_clocks(int num_cycles)
294 {
295 /* allocate memory for a new list member */
296 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
297
298 jtag_queue_command(cmd);
299
300 cmd->type = JTAG_STABLECLOCKS;
301
302 cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(struct stableclocks_command));
303 cmd->cmd.stableclocks->num_cycles = num_cycles;
304
305 return ERROR_OK;
306 }
307
308 int interface_jtag_add_reset(int req_trst, int req_srst)
309 {
310 /* allocate memory for a new list member */
311 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
312
313 jtag_queue_command(cmd);
314
315 cmd->type = JTAG_RESET;
316
317 cmd->cmd.reset = cmd_queue_alloc(sizeof(struct reset_command));
318 cmd->cmd.reset->trst = req_trst;
319 cmd->cmd.reset->srst = req_srst;
320
321 return ERROR_OK;
322 }
323
324 int interface_jtag_add_sleep(uint32_t us)
325 {
326 /* allocate memory for a new list member */
327 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
328
329 jtag_queue_command(cmd);
330
331 cmd->type = JTAG_SLEEP;
332
333 cmd->cmd.sleep = cmd_queue_alloc(sizeof(struct sleep_command));
334 cmd->cmd.sleep->us = us;
335
336 return ERROR_OK;
337 }
338
339 /* add callback to end of queue */
340 void interface_jtag_add_callback4(jtag_callback_t callback,
341 jtag_callback_data_t data0, jtag_callback_data_t data1,
342 jtag_callback_data_t data2, jtag_callback_data_t data3)
343 {
344 struct jtag_callback_entry *entry = cmd_queue_alloc(sizeof(struct jtag_callback_entry));
345
346 entry->next = NULL;
347 entry->callback = callback;
348 entry->data0 = data0;
349 entry->data1 = data1;
350 entry->data2 = data2;
351 entry->data3 = data3;
352
353 if (jtag_callback_queue_head == NULL) {
354 jtag_callback_queue_head = entry;
355 jtag_callback_queue_tail = entry;
356 } else {
357 jtag_callback_queue_tail->next = entry;
358 jtag_callback_queue_tail = entry;
359 }
360 }
361
362 int interface_jtag_execute_queue(void)
363 {
364 static int reentry;
365
366 assert(reentry == 0);
367 reentry++;
368
369 int retval = default_interface_jtag_execute_queue();
370 if (retval == ERROR_OK) {
371 struct jtag_callback_entry *entry;
372 for (entry = jtag_callback_queue_head; entry != NULL; entry = entry->next) {
373 retval = entry->callback(entry->data0, entry->data1, entry->data2, entry->data3);
374 if (retval != ERROR_OK)
375 break;
376 }
377 }
378
379 jtag_command_queue_reset();
380 jtag_callback_queue_reset();
381
382 reentry--;
383
384 return retval;
385 }
386
387 static int jtag_convert_to_callback4(jtag_callback_data_t data0,
388 jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
389 {
390 ((jtag_callback1_t)data1)(data0);
391 return ERROR_OK;
392 }
393
394 void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
395 {
396 jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
397 }
398
399 void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
400 {
401 interface_jtag_add_callback(f, data0);
402 }
403
404 void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
405 jtag_callback_data_t data1, jtag_callback_data_t data2,
406 jtag_callback_data_t data3)
407 {
408 interface_jtag_add_callback4(f, data0, data1, data2, data3);
409 }

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)