Audit and eliminate redundant #include directives from src/jtag.
[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
26
27 bitq_interface_t* bitq_interface; /* low level bit queue interface */
28
29 static bitq_state_t bitq_in_state; /* state of input queue */
30
31 static u8* bitq_in_buffer; /* buffer dynamically reallocated as needed */
32 static int bitq_in_bufsize = 32; /* min. buffer size */
33
34 /*
35 * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
36 * also the buffer for incomming data is reallocated only if necessary
37 * no parameters, makes use of stored state information
38 */
39 void bitq_in_proc(void)
40 {
41 /* static information preserved between calls to increase performance */
42 static u8* in_buff; /* pointer to buffer for scanned data */
43 static int in_idx; /* index of byte being scanned */
44 static u8 in_mask; /* mask of next bit to be scanned */
45
46 scan_field_t* field;
47 int tdo;
48
49 /* loop through the queue */
50 while (bitq_in_state.cmd)
51 {
52 /* only JTAG_SCAN command may return data */
53 if (bitq_in_state.cmd->type==JTAG_SCAN)
54 {
55 /* loop through the fields */
56 while (bitq_in_state.field_idx<bitq_in_state.cmd->cmd.scan->num_fields)
57 {
58 field = &bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
59 if (field->in_value)
60 {
61 if (bitq_in_state.bit_pos==0)
62 {
63 /* initialize field scanning */
64 in_mask = 0x01;
65 in_idx = 0;
66 if (field->in_value)
67 in_buff = field->in_value;
68 else
69 {
70 /* buffer reallocation needed? */
71 if (field->num_bits>bitq_in_bufsize * 8)
72 {
73 /* buffer previously allocated? */
74 if (bitq_in_buffer!=NULL)
75 {
76 /* free it */
77 free(bitq_in_buffer);
78 bitq_in_buffer = NULL;
79 }
80 /* double the buffer size until it fits */
81 while (field->num_bits>bitq_in_bufsize * 8)
82 bitq_in_bufsize *= 2;
83 }
84 /* if necessary, allocate buffer and check for malloc error */
85 if (bitq_in_buffer==NULL && ( bitq_in_buffer = malloc(bitq_in_bufsize) )==NULL)
86 {
87 LOG_ERROR("malloc error");
88 exit(-1);
89 }
90 in_buff = (void*) bitq_in_buffer;
91 }
92 }
93
94 /* field scanning */
95 while (bitq_in_state.bit_pos<field->num_bits)
96 {
97 if ( ( tdo = bitq_interface->in() )<0 )
98 {
99 #ifdef _DEBUG_JTAG_IO_
100 LOG_DEBUG("bitq in EOF");
101 #endif
102 return;
103 }
104 if (in_mask==0x01)
105 in_buff[in_idx] = 0;
106 if (tdo)
107 in_buff[in_idx] |= in_mask;
108 if (in_mask==0x80)
109 {
110 in_mask = 0x01;
111 in_idx++;
112 }
113 else
114 in_mask <<= 1;
115 bitq_in_state.bit_pos++;
116 }
117 }
118
119 bitq_in_state.field_idx++; /* advance to next field */
120 bitq_in_state.bit_pos = 0; /* start next field from the first bit */
121 }
122 }
123 bitq_in_state.cmd = bitq_in_state.cmd->next; /* advance to next command */
124 bitq_in_state.field_idx = 0; /* preselect first field */
125 }
126 }
127
128
129 void bitq_io(int tms, int tdi, int tdo_req)
130 {
131 bitq_interface->out(tms, tdi, tdo_req);
132 /* check and process the input queue */
133 if ( bitq_interface->in_rdy() )
134 bitq_in_proc();
135 }
136
137
138 void bitq_end_state(tap_state_t state)
139 {
140 if (state==TAP_INVALID)
141 return;
142
143 if (!tap_is_state_stable(state))
144 {
145 LOG_ERROR("BUG: %i is not a valid end state", state);
146 exit(-1);
147 }
148 tap_set_end_state(state);
149 }
150
151
152 void bitq_state_move(tap_state_t new_state)
153 {
154 int i = 0;
155 u8 tms_scan;
156
157 if (!tap_is_state_stable(tap_get_state()) || !tap_is_state_stable(new_state))
158 {
159 LOG_ERROR("TAP move from or to unstable state");
160 exit(-1);
161 }
162
163 tms_scan = tap_get_tms_path(tap_get_state(), new_state);
164
165 for (i = 0; i<7; i++)
166 {
167 bitq_io(tms_scan & 1, 0, 0);
168 tms_scan >>= 1;
169 }
170
171 tap_set_state(new_state);
172 }
173
174
175 void bitq_path_move(pathmove_command_t* cmd)
176 {
177 int i;
178
179 for (i = 0; i<=cmd->num_states; i++)
180 {
181 if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
182 bitq_io(0, 0, 0);
183 else if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
184 bitq_io(1, 0, 0);
185 else
186 {
187 LOG_ERROR( "BUG: %s -> %s isn't a valid TAP transition", tap_state_name(
188 tap_get_state() ), tap_state_name(cmd->path[i]) );
189 exit(-1);
190 }
191
192 tap_set_state(cmd->path[i]);
193 }
194
195 tap_set_end_state( tap_get_state() );
196 }
197
198
199 void bitq_runtest(int num_cycles)
200 {
201 int i;
202
203 /* only do a state_move when we're not already in IDLE */
204 if (tap_get_state() != TAP_IDLE)
205 bitq_state_move(TAP_IDLE);
206
207 /* execute num_cycles */
208 for (i = 0; i < num_cycles; i++)
209 bitq_io(0, 0, 0);
210
211 /* finish in end_state */
212 if ( tap_get_state() != tap_get_end_state() )
213 bitq_state_move( tap_get_end_state() );
214 }
215
216
217 void bitq_scan_field(scan_field_t* field, int pause)
218 {
219 int bit_cnt;
220 int tdo_req;
221
222 u8* out_ptr;
223 u8 out_mask;
224
225 if (field->in_value)
226 tdo_req = 1;
227 else
228 tdo_req = 0;
229
230 if (field->out_value==NULL)
231 {
232 /* just send zeros and request data from TDO */
233 for (bit_cnt = field->num_bits; bit_cnt>1; bit_cnt--)
234 bitq_io(0, 0, tdo_req);
235
236 bitq_io(pause, 0, tdo_req);
237 }
238 else
239 {
240 /* send data, and optionally request TDO */
241 out_mask = 0x01;
242 out_ptr = field->out_value;
243 for (bit_cnt = field->num_bits; bit_cnt>1; bit_cnt--)
244 {
245 bitq_io(0, ( (*out_ptr) & out_mask )!=0, tdo_req);
246 if (out_mask==0x80)
247 {
248 out_mask = 0x01;
249 out_ptr++;
250 }
251 else
252 out_mask <<= 1;
253 }
254
255 bitq_io(pause, ( (*out_ptr) & out_mask )!=0, tdo_req);
256 }
257
258 if (pause)
259 {
260 bitq_io(0, 0, 0);
261 if (tap_get_state()==TAP_IRSHIFT)
262 tap_set_state(TAP_IRPAUSE);
263 else if (tap_get_state()==TAP_DRSHIFT)
264 tap_set_state(TAP_DRPAUSE);
265 }
266 }
267
268
269 void bitq_scan(scan_command_t* cmd)
270 {
271 int i;
272
273 if (cmd->ir_scan)
274 bitq_state_move(TAP_IRSHIFT);
275 else
276 bitq_state_move(TAP_DRSHIFT);
277
278 for (i = 0; i < cmd->num_fields - 1; i++)
279 bitq_scan_field(&cmd->fields[i], 0);
280
281 bitq_scan_field(&cmd->fields[i], 1);
282 }
283
284
285 int bitq_execute_queue(void)
286 {
287 jtag_command_t* cmd = jtag_command_queue; /* currently processed command */
288
289 bitq_in_state.cmd = jtag_command_queue;
290 bitq_in_state.field_idx = 0;
291 bitq_in_state.bit_pos = 0;
292 bitq_in_state.status = ERROR_OK;
293
294 while (cmd)
295 {
296 switch (cmd->type)
297 {
298 case JTAG_END_STATE:
299 #ifdef _DEBUG_JTAG_IO_
300 LOG_DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
301 #endif
302 bitq_end_state(cmd->cmd.end_state->end_state);
303 break;
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_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_STATEMOVE:
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)