improve command handling examples
[openocd.git] / src / jtag / bitq.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
3 * chromy@asix.cz *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "bitq.h"
25 #include "interface.h"
26
27
28 struct bitq_interface* bitq_interface; /* low level bit queue interface */
29
30 /* state of input queue */
31 struct bitq_state {
32 struct jtag_command *cmd; /* command currently processed */
33 int field_idx; /* index of field currently being processed */
34 int bit_pos; /* position of bit curently being processed */
35 int status; /* processing status */
36 };
37 static struct bitq_state bitq_in_state;
38
39 static uint8_t* bitq_in_buffer; /* buffer dynamically reallocated as needed */
40 static int bitq_in_bufsize = 32; /* min. buffer size */
41
42 /*
43 * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
44 * also the buffer for incomming data is reallocated only if necessary
45 * no parameters, makes use of stored state information
46 */
47 void bitq_in_proc(void)
48 {
49 /* static information preserved between calls to increase performance */
50 static uint8_t* in_buff; /* pointer to buffer for scanned data */
51 static int in_idx; /* index of byte being scanned */
52 static uint8_t in_mask; /* mask of next bit to be scanned */
53
54 struct scan_field* field;
55 int tdo;
56
57 /* loop through the queue */
58 while (bitq_in_state.cmd)
59 {
60 /* only JTAG_SCAN command may return data */
61 if (bitq_in_state.cmd->type == JTAG_SCAN)
62 {
63 /* loop through the fields */
64 while (bitq_in_state.field_idx < bitq_in_state.cmd->cmd.scan->num_fields)
65 {
66 field = &bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
67 if (field->in_value)
68 {
69 if (bitq_in_state.bit_pos == 0)
70 {
71 /* initialize field scanning */
72 in_mask = 0x01;
73 in_idx = 0;
74 if (field->in_value)
75 in_buff = field->in_value;
76 else
77 {
78 /* buffer reallocation needed? */
79 if (field->num_bits > bitq_in_bufsize * 8)
80 {
81 /* buffer previously allocated? */
82 if (bitq_in_buffer != NULL)
83 {
84 /* free it */
85 free(bitq_in_buffer);
86 bitq_in_buffer = NULL;
87 }
88 /* double the buffer size until it fits */
89 while (field->num_bits > bitq_in_bufsize * 8)
90 bitq_in_bufsize *= 2;
91 }
92 /* if necessary, allocate buffer and check for malloc error */
93 if (bitq_in_buffer == NULL && (bitq_in_buffer = malloc(bitq_in_bufsize)) == NULL)
94 {
95 LOG_ERROR("malloc error");
96 exit(-1);
97 }
98 in_buff = (void*) bitq_in_buffer;
99 }
100 }
101
102 /* field scanning */
103 while (bitq_in_state.bit_pos < field->num_bits)
104 {
105 if ((tdo = bitq_interface->in()) < 0)
106 {
107 #ifdef _DEBUG_JTAG_IO_
108 LOG_DEBUG("bitq in EOF");
109 #endif
110 return;
111 }
112 if (in_mask == 0x01)
113 in_buff[in_idx] = 0;
114 if (tdo)
115 in_buff[in_idx] |= in_mask;
116 if (in_mask == 0x80)
117 {
118 in_mask = 0x01;
119 in_idx++;
120 }
121 else
122 in_mask <<= 1;
123 bitq_in_state.bit_pos++;
124 }
125 }
126
127 bitq_in_state.field_idx++; /* advance to next field */
128 bitq_in_state.bit_pos = 0; /* start next field from the first bit */
129 }
130 }
131 bitq_in_state.cmd = bitq_in_state.cmd->next; /* advance to next command */
132 bitq_in_state.field_idx = 0; /* preselect first field */
133 }
134 }
135
136
137 void bitq_io(int tms, int tdi, int tdo_req)
138 {
139 bitq_interface->out(tms, tdi, tdo_req);
140 /* check and process the input queue */
141 if (bitq_interface->in_rdy())
142 bitq_in_proc();
143 }
144
145
146 void bitq_end_state(tap_state_t state)
147 {
148 if (!tap_is_state_stable(state))
149 {
150 LOG_ERROR("BUG: %i is not a valid end state", state);
151 exit(-1);
152 }
153 tap_set_end_state(state);
154 }
155
156
157 void bitq_state_move(tap_state_t new_state)
158 {
159 int i = 0;
160 uint8_t tms_scan;
161
162 if (!tap_is_state_stable(tap_get_state()) || !tap_is_state_stable(new_state))
163 {
164 LOG_ERROR("TAP move from or to unstable state");
165 exit(-1);
166 }
167
168 tms_scan = tap_get_tms_path(tap_get_state(), new_state);
169 int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
170
171 for (i = 0; i < tms_count; i++)
172 {
173 bitq_io(tms_scan & 1, 0, 0);
174 tms_scan >>= 1;
175 }
176
177 tap_set_state(new_state);
178 }
179
180
181 void bitq_path_move(struct pathmove_command* cmd)
182 {
183 int i;
184
185 for (i = 0; i <= cmd->num_states; i++)
186 {
187 if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
188 bitq_io(0, 0, 0);
189 else if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
190 bitq_io(1, 0, 0);
191 else
192 {
193 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(
194 tap_get_state()), tap_state_name(cmd->path[i]));
195 exit(-1);
196 }
197
198 tap_set_state(cmd->path[i]);
199 }
200
201 tap_set_end_state(tap_get_state());
202 }
203
204
205 void bitq_runtest(int num_cycles)
206 {
207 int i;
208
209 /* only do a state_move when we're not already in IDLE */
210 if (tap_get_state() != TAP_IDLE)
211 bitq_state_move(TAP_IDLE);
212
213 /* execute num_cycles */
214 for (i = 0; i < num_cycles; i++)
215 bitq_io(0, 0, 0);
216
217 /* finish in end_state */
218 if (tap_get_state() != tap_get_end_state())
219 bitq_state_move(tap_get_end_state());
220 }
221
222
223 void bitq_scan_field(struct scan_field* field, int pause)
224 {
225 int bit_cnt;
226 int tdo_req;
227
228 uint8_t* out_ptr;
229 uint8_t out_mask;
230
231 if (field->in_value)
232 tdo_req = 1;
233 else
234 tdo_req = 0;
235
236 if (field->out_value == NULL)
237 {
238 /* just send zeros and request data from TDO */
239 for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--)
240 bitq_io(0, 0, tdo_req);
241
242 bitq_io(pause, 0, tdo_req);
243 }
244 else
245 {
246 /* send data, and optionally request TDO */
247 out_mask = 0x01;
248 out_ptr = field->out_value;
249 for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--)
250 {
251 bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req);
252 if (out_mask == 0x80)
253 {
254 out_mask = 0x01;
255 out_ptr++;
256 }
257 else
258 out_mask <<= 1;
259 }
260
261 bitq_io(pause, ((*out_ptr) & out_mask) != 0, tdo_req);
262 }
263
264 if (pause)
265 {
266 bitq_io(0, 0, 0);
267 if (tap_get_state() == TAP_IRSHIFT)
268 tap_set_state(TAP_IRPAUSE);
269 else if (tap_get_state() == TAP_DRSHIFT)
270 tap_set_state(TAP_DRPAUSE);
271 }
272 }
273
274
275 void bitq_scan(struct scan_command* cmd)
276 {
277 int i;
278
279 if (cmd->ir_scan)
280 bitq_state_move(TAP_IRSHIFT);
281 else
282 bitq_state_move(TAP_DRSHIFT);
283
284 for (i = 0; i < cmd->num_fields - 1; i++)
285 bitq_scan_field(&cmd->fields[i], 0);
286
287 bitq_scan_field(&cmd->fields[i], 1);
288 }
289
290
291 int bitq_execute_queue(void)
292 {
293 struct jtag_command* cmd = jtag_command_queue; /* currently processed command */
294
295 bitq_in_state.cmd = jtag_command_queue;
296 bitq_in_state.field_idx = 0;
297 bitq_in_state.bit_pos = 0;
298 bitq_in_state.status = ERROR_OK;
299
300 while (cmd)
301 {
302 switch (cmd->type)
303 {
304 case JTAG_RESET:
305 #ifdef _DEBUG_JTAG_IO_
306 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
307 #endif
308 if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
309 {
310 tap_set_state(TAP_RESET);
311 }
312 bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
313 if (bitq_interface->in_rdy())
314 bitq_in_proc();
315 break;
316
317 case JTAG_RUNTEST:
318 #ifdef _DEBUG_JTAG_IO_
319 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
320 #endif
321 bitq_end_state(cmd->cmd.runtest->end_state);
322 bitq_runtest(cmd->cmd.runtest->num_cycles);
323 break;
324
325 case JTAG_STATEMOVE:
326 #ifdef _DEBUG_JTAG_IO_
327 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
328 #endif
329 bitq_end_state(cmd->cmd.statemove->end_state);
330 bitq_state_move(tap_get_end_state()); /* uncoditional TAP move */
331 break;
332
333 case JTAG_PATHMOVE:
334 #ifdef _DEBUG_JTAG_IO_
335 LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
336 cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
337 #endif
338 bitq_path_move(cmd->cmd.pathmove);
339 break;
340
341 case JTAG_SCAN:
342 #ifdef _DEBUG_JTAG_IO_
343 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
344 if (cmd->cmd.scan->ir_scan)
345 LOG_DEBUG("scan ir");
346 else
347 LOG_DEBUG("scan dr");
348 #endif
349 bitq_end_state(cmd->cmd.scan->end_state);
350 bitq_scan(cmd->cmd.scan);
351 if (tap_get_state() != tap_get_end_state())
352 bitq_state_move(tap_get_end_state());
353 break;
354
355 case JTAG_SLEEP:
356 #ifdef _DEBUG_JTAG_IO_
357 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
358 #endif
359 bitq_interface->sleep(cmd->cmd.sleep->us);
360 if (bitq_interface->in_rdy())
361 bitq_in_proc();
362 break;
363
364 default:
365 LOG_ERROR("BUG: unknown JTAG command type encountered");
366 exit(-1);
367 }
368
369 cmd = cmd->next;
370 }
371
372 bitq_interface->flush();
373 bitq_in_proc();
374
375 if (bitq_in_state.cmd)
376 {
377 LOG_ERROR("missing data from bitq interface");
378 return ERROR_JTAG_QUEUE_FAILED;
379 }
380 if (bitq_interface->in() >= 0)
381 {
382 LOG_ERROR("extra data from bitq interface");
383 return ERROR_JTAG_QUEUE_FAILED;
384 }
385
386 return bitq_in_state.status;
387 }
388
389
390 void bitq_cleanup(void)
391 {
392 if (bitq_in_buffer != NULL)
393 {
394 free(bitq_in_buffer);
395 bitq_in_buffer = NULL;
396 }
397 }

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)