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

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)