openocd: fix SPDX tag format for files .c
[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 = 0;
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 = 1;
86
87 field->num_bits = tap->ir_length;
88 field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
89 field->in_value = NULL; /* do not collect input for tap's in bypass */
90 }
91
92 /* update device information */
93 buf_cpy(field->out_value, tap->cur_instr, tap->ir_length);
94
95 field++;
96 }
97 /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
98 assert(field == out_fields + num_taps);
99
100 return ERROR_OK;
101 }
102
103 /**
104 * see jtag_add_dr_scan()
105 *
106 */
107 int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields,
108 const struct scan_field *in_fields, tap_state_t state)
109 {
110 /* count devices in bypass */
111
112 size_t bypass_devices = 0;
113
114 for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
115 if (tap->bypass)
116 bypass_devices++;
117 }
118
119 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
120 struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
121 struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
122
123 jtag_queue_command(cmd);
124
125 cmd->type = JTAG_SCAN;
126 cmd->cmd.scan = scan;
127
128 scan->ir_scan = false;
129 scan->num_fields = in_num_fields + bypass_devices;
130 scan->fields = out_fields;
131 scan->end_state = state;
132
133 struct scan_field *field = out_fields; /* keep track where we insert data */
134
135 /* loop over all enabled TAPs */
136
137 for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
138 /* if TAP is not bypassed insert matching input fields */
139
140 if (!tap->bypass) {
141 assert(active == tap);
142 #ifndef NDEBUG
143 /* remember initial position for assert() */
144 struct scan_field *start_field = field;
145 #endif /* NDEBUG */
146
147 for (int j = 0; j < in_num_fields; j++) {
148 jtag_scan_field_clone(field, in_fields + j);
149
150 field++;
151 }
152
153 assert(field > start_field); /* must have at least one input field per not bypassed TAP */
154 }
155
156 /* if a TAP is bypassed, generated a dummy bit*/
157 else {
158 field->num_bits = 1;
159 field->out_value = NULL;
160 field->in_value = NULL;
161
162 field++;
163 }
164 }
165
166 assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */
167
168 return ERROR_OK;
169 }
170
171 static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits,
172 uint8_t *in_bits, tap_state_t state, bool ir_scan)
173 {
174 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
175 struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
176 struct scan_field *out_fields = cmd_queue_alloc(sizeof(struct scan_field));
177
178 jtag_queue_command(cmd);
179
180 cmd->type = JTAG_SCAN;
181 cmd->cmd.scan = scan;
182
183 scan->ir_scan = ir_scan;
184 scan->num_fields = 1;
185 scan->fields = out_fields;
186 scan->end_state = state;
187
188 out_fields->num_bits = num_bits;
189 out_fields->out_value = buf_cpy(out_bits, cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
190 out_fields->in_value = in_bits;
191
192 return ERROR_OK;
193 }
194
195 int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
196 {
197 return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false);
198 }
199
200 int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
201 {
202 return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true);
203 }
204
205 int interface_jtag_add_tlr(void)
206 {
207 tap_state_t state = TAP_RESET;
208
209 /* allocate memory for a new list member */
210 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
211
212 jtag_queue_command(cmd);
213
214 cmd->type = JTAG_TLR_RESET;
215
216 cmd->cmd.statemove = cmd_queue_alloc(sizeof(struct statemove_command));
217 cmd->cmd.statemove->end_state = state;
218
219 return ERROR_OK;
220 }
221
222 int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
223 {
224 struct jtag_command *cmd;
225
226 cmd = cmd_queue_alloc(sizeof(struct jtag_command));
227 if (!cmd)
228 return ERROR_FAIL;
229
230 cmd->type = JTAG_TMS;
231 cmd->cmd.tms = cmd_queue_alloc(sizeof(*cmd->cmd.tms));
232 if (!cmd->cmd.tms)
233 return ERROR_FAIL;
234
235 /* copy the bits; our caller doesn't guarantee they'll persist */
236 cmd->cmd.tms->num_bits = num_bits;
237 cmd->cmd.tms->bits = buf_cpy(seq,
238 cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
239 if (!cmd->cmd.tms->bits)
240 return ERROR_FAIL;
241
242 jtag_queue_command(cmd);
243
244 return ERROR_OK;
245 }
246
247 int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
248 {
249 /* allocate memory for a new list member */
250 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
251
252 jtag_queue_command(cmd);
253
254 cmd->type = JTAG_PATHMOVE;
255
256 cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command));
257 cmd->cmd.pathmove->num_states = num_states;
258 cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
259
260 for (int i = 0; i < num_states; i++)
261 cmd->cmd.pathmove->path[i] = path[i];
262
263 return ERROR_OK;
264 }
265
266 int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
267 {
268 /* allocate memory for a new list member */
269 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
270
271 jtag_queue_command(cmd);
272
273 cmd->type = JTAG_RUNTEST;
274
275 cmd->cmd.runtest = cmd_queue_alloc(sizeof(struct runtest_command));
276 cmd->cmd.runtest->num_cycles = num_cycles;
277 cmd->cmd.runtest->end_state = state;
278
279 return ERROR_OK;
280 }
281
282 int interface_jtag_add_clocks(int num_cycles)
283 {
284 /* allocate memory for a new list member */
285 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
286
287 jtag_queue_command(cmd);
288
289 cmd->type = JTAG_STABLECLOCKS;
290
291 cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(struct stableclocks_command));
292 cmd->cmd.stableclocks->num_cycles = num_cycles;
293
294 return ERROR_OK;
295 }
296
297 int interface_jtag_add_reset(int req_trst, int req_srst)
298 {
299 /* allocate memory for a new list member */
300 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
301
302 jtag_queue_command(cmd);
303
304 cmd->type = JTAG_RESET;
305
306 cmd->cmd.reset = cmd_queue_alloc(sizeof(struct reset_command));
307 cmd->cmd.reset->trst = req_trst;
308 cmd->cmd.reset->srst = req_srst;
309
310 return ERROR_OK;
311 }
312
313 int interface_jtag_add_sleep(uint32_t us)
314 {
315 /* allocate memory for a new list member */
316 struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
317
318 jtag_queue_command(cmd);
319
320 cmd->type = JTAG_SLEEP;
321
322 cmd->cmd.sleep = cmd_queue_alloc(sizeof(struct sleep_command));
323 cmd->cmd.sleep->us = us;
324
325 return ERROR_OK;
326 }
327
328 /* add callback to end of queue */
329 void interface_jtag_add_callback4(jtag_callback_t callback,
330 jtag_callback_data_t data0, jtag_callback_data_t data1,
331 jtag_callback_data_t data2, jtag_callback_data_t data3)
332 {
333 struct jtag_callback_entry *entry = cmd_queue_alloc(sizeof(struct jtag_callback_entry));
334
335 entry->next = NULL;
336 entry->callback = callback;
337 entry->data0 = data0;
338 entry->data1 = data1;
339 entry->data2 = data2;
340 entry->data3 = data3;
341
342 if (!jtag_callback_queue_head) {
343 jtag_callback_queue_head = entry;
344 jtag_callback_queue_tail = entry;
345 } else {
346 jtag_callback_queue_tail->next = entry;
347 jtag_callback_queue_tail = entry;
348 }
349 }
350
351 int interface_jtag_execute_queue(void)
352 {
353 static int reentry;
354
355 assert(reentry == 0);
356 reentry++;
357
358 int retval = default_interface_jtag_execute_queue();
359 if (retval == ERROR_OK) {
360 struct jtag_callback_entry *entry;
361 for (entry = jtag_callback_queue_head; entry; entry = entry->next) {
362 retval = entry->callback(entry->data0, entry->data1, entry->data2, entry->data3);
363 if (retval != ERROR_OK)
364 break;
365 }
366 }
367
368 jtag_command_queue_reset();
369 jtag_callback_queue_reset();
370
371 reentry--;
372
373 return retval;
374 }
375
376 static int jtag_convert_to_callback4(jtag_callback_data_t data0,
377 jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
378 {
379 ((jtag_callback1_t)data1)(data0);
380 return ERROR_OK;
381 }
382
383 void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
384 {
385 jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
386 }
387
388 void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
389 {
390 interface_jtag_add_callback(f, data0);
391 }
392
393 void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
394 jtag_callback_data_t data1, jtag_callback_data_t data2,
395 jtag_callback_data_t data3)
396 {
397 interface_jtag_add_callback4(f, data0, data1, data2, data3);
398 }

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)