Finish JTAG header file modularization; command factoring follows.
[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 (state==TAP_INVALID)
142 return;
143
144 if (!tap_is_state_stable(state))
145 {
146 LOG_ERROR("BUG: %i is not a valid end state", state);
147 exit(-1);
148 }
149 tap_set_end_state(state);
150 }
151
152
153 void bitq_state_move(tap_state_t new_state)
154 {
155 int i = 0;
156 u8 tms_scan;
157
158 if (!tap_is_state_stable(tap_get_state()) || !tap_is_state_stable(new_state))
159 {
160 LOG_ERROR("TAP move from or to unstable state");
161 exit(-1);
162 }
163
164 tms_scan = tap_get_tms_path(tap_get_state(), new_state);
165 int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
166
167 for (i = 0; i<tms_count; i++)
168 {
169 bitq_io(tms_scan & 1, 0, 0);
170 tms_scan >>= 1;
171 }
172
173 tap_set_state(new_state);
174 }
175
176
177 void bitq_path_move(pathmove_command_t* cmd)
178 {
179 int i;
180
181 for (i = 0; i<=cmd->num_states; i++)
182 {
183 if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
184 bitq_io(0, 0, 0);
185 else if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
186 bitq_io(1, 0, 0);
187 else
188 {
189 LOG_ERROR( "BUG: %s -> %s isn't a valid TAP transition", tap_state_name(
190 tap_get_state() ), tap_state_name(cmd->path[i]) );
191 exit(-1);
192 }
193
194 tap_set_state(cmd->path[i]);
195 }
196
197 tap_set_end_state( tap_get_state() );
198 }
199
200
201 void bitq_runtest(int num_cycles)
202 {
203 int i;
204
205 /* only do a state_move when we're not already in IDLE */
206 if (tap_get_state() != TAP_IDLE)
207 bitq_state_move(TAP_IDLE);
208
209 /* execute num_cycles */
210 for (i = 0; i < num_cycles; i++)
211 bitq_io(0, 0, 0);
212
213 /* finish in end_state */
214 if ( tap_get_state() != tap_get_end_state() )
215 bitq_state_move( tap_get_end_state() );
216 }
217
218
219 void bitq_scan_field(scan_field_t* field, int pause)
220 {
221 int bit_cnt;
222 int tdo_req;
223
224 u8* out_ptr;
225 u8 out_mask;
226
227 if (field->in_value)
228 tdo_req = 1;
229 else
230 tdo_req = 0;
231
232 if (field->out_value==NULL)
233 {
234 /* just send zeros and request data from TDO */
235 for (bit_cnt = field->num_bits; bit_cnt>1; bit_cnt--)
236 bitq_io(0, 0, tdo_req);
237
238 bitq_io(pause, 0, tdo_req);
239 }
240 else
241 {
242 /* send data, and optionally request TDO */
243 out_mask = 0x01;
244 out_ptr = field->out_value;
245 for (bit_cnt = field->num_bits; bit_cnt>1; bit_cnt--)
246 {
247 bitq_io(0, ( (*out_ptr) & out_mask )!=0, tdo_req);
248 if (out_mask==0x80)
249 {
250 out_mask = 0x01;
251 out_ptr++;
252 }
253 else
254 out_mask <<= 1;
255 }
256
257 bitq_io(pause, ( (*out_ptr) & out_mask )!=0, tdo_req);
258 }
259
260 if (pause)
261 {
262 bitq_io(0, 0, 0);
263 if (tap_get_state()==TAP_IRSHIFT)
264 tap_set_state(TAP_IRPAUSE);
265 else if (tap_get_state()==TAP_DRSHIFT)
266 tap_set_state(TAP_DRPAUSE);
267 }
268 }
269
270
271 void bitq_scan(scan_command_t* cmd)
272 {
273 int i;
274
275 if (cmd->ir_scan)
276 bitq_state_move(TAP_IRSHIFT);
277 else
278 bitq_state_move(TAP_DRSHIFT);
279
280 for (i = 0; i < cmd->num_fields - 1; i++)
281 bitq_scan_field(&cmd->fields[i], 0);
282
283 bitq_scan_field(&cmd->fields[i], 1);
284 }
285
286
287 int bitq_execute_queue(void)
288 {
289 jtag_command_t* cmd = jtag_command_queue; /* currently processed command */
290
291 bitq_in_state.cmd = jtag_command_queue;
292 bitq_in_state.field_idx = 0;
293 bitq_in_state.bit_pos = 0;
294 bitq_in_state.status = ERROR_OK;
295
296 while (cmd)
297 {
298 switch (cmd->type)
299 {
300 case JTAG_RESET:
301 #ifdef _DEBUG_JTAG_IO_
302 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
303 #endif
304 if ( (cmd->cmd.reset->trst == 1) || ( cmd->cmd.reset->srst && (jtag_reset_config & RESET_SRST_PULLS_TRST) ) )
305 {
306 tap_set_state(TAP_RESET);
307 }
308 bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
309 if ( bitq_interface->in_rdy() )
310 bitq_in_proc();
311 break;
312
313 case JTAG_RUNTEST:
314 #ifdef _DEBUG_JTAG_IO_
315 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
316 #endif
317 bitq_end_state(cmd->cmd.runtest->end_state);
318 bitq_runtest(cmd->cmd.runtest->num_cycles);
319 break;
320
321 case JTAG_STATEMOVE:
322 #ifdef _DEBUG_JTAG_IO_
323 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
324 #endif
325 bitq_end_state(cmd->cmd.statemove->end_state);
326 bitq_state_move( tap_get_end_state() ); /* uncoditional TAP move */
327 break;
328
329 case JTAG_PATHMOVE:
330 #ifdef _DEBUG_JTAG_IO_
331 LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
332 cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
333 #endif
334 bitq_path_move(cmd->cmd.pathmove);
335 break;
336
337 case JTAG_SCAN:
338 #ifdef _DEBUG_JTAG_IO_
339 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
340 if (cmd->cmd.scan->ir_scan)
341 LOG_DEBUG("scan ir");
342 else
343 LOG_DEBUG("scan dr");
344 #endif
345 bitq_end_state(cmd->cmd.scan->end_state);
346 bitq_scan(cmd->cmd.scan);
347 if ( tap_get_state() != tap_get_end_state() )
348 bitq_state_move( tap_get_end_state() );
349 break;
350
351 case JTAG_SLEEP:
352 #ifdef _DEBUG_JTAG_IO_
353 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
354 #endif
355 bitq_interface->sleep(cmd->cmd.sleep->us);
356 if ( bitq_interface->in_rdy() )
357 bitq_in_proc();
358 break;
359
360 default:
361 LOG_ERROR("BUG: unknown JTAG command type encountered");
362 exit(-1);
363 }
364
365 cmd = cmd->next;
366 }
367
368 bitq_interface->flush();
369 bitq_in_proc();
370
371 if (bitq_in_state.cmd)
372 {
373 LOG_ERROR("missing data from bitq interface");
374 return ERROR_JTAG_QUEUE_FAILED;
375 }
376 if (bitq_interface->in()>=0)
377 {
378 LOG_ERROR("extra data from bitq interface");
379 return ERROR_JTAG_QUEUE_FAILED;
380 }
381
382 return bitq_in_state.status;
383 }
384
385
386 void bitq_cleanup(void)
387 {
388 if (bitq_in_buffer!=NULL)
389 {
390 free(bitq_in_buffer);
391 bitq_in_buffer = NULL;
392 }
393 }

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)