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