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

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)