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

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)