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

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)