- added support for Asix Presto JTAG interface (thanks to Pavel Chromy and Asix for...
[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 /* project specific includes */
27 #include "log.h"
28 #include "types.h"
29 #include "jtag.h"
30 #include "configuration.h"
31
32 /* system includes */
33 #include <string.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36
37 #include <sys/time.h>
38 #include <time.h>
39
40
41 bitq_interface_t *bitq_interface; /* low level bit queue interface */
42
43 bitq_state_t bitq_in_state; /* state of input queue */
44
45 u8 *bitq_in_buffer; /* buffer dynamically reallocated as needed */
46 unsigned long bitq_in_bufsize=32; /* min. buffer size */
47
48
49 /*
50 * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
51 * also the buffer for incomming data is reallocated only if necessary
52 * no parameters, makes use of stored state information
53 */
54 void bitq_in_proc(void)
55 {
56 /* static information preserved between calls to increase performance */
57 static u8 *in_buff; /* pointer to buffer for scanned data */
58 static int in_idx; /* index of byte being scanned */
59 static u8 in_mask; /* mask of next bit to be scanned */
60
61 scan_field_t *field;
62 int tdo;
63
64 int result;
65
66 /* loop through the queue */
67 while (bitq_in_state.cmd) {
68 /* only JTAG_SCAN command may return data */
69 if (bitq_in_state.cmd->type==JTAG_SCAN) {
70 /* loop through the fields */
71 while (bitq_in_state.field_idx<bitq_in_state.cmd->cmd.scan->num_fields) {
72
73 field=&bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
74 if (field->in_check_value || field->in_value || field->in_handler) {
75
76 if (bitq_in_state.bit_pos==0) {
77 /* initialize field scanning */
78 in_mask=0x01;
79 in_idx=0;
80 if (field->in_value) in_buff=field->in_value;
81 else {
82 /* buffer reallocation needed? */
83 if (field->num_bits>bitq_in_bufsize*8) {
84 /* buffer previously allocated? */
85 if (bitq_in_buffer!=NULL) {
86 /* free it */
87 free(bitq_in_buffer);
88 bitq_in_buffer=NULL;
89 }
90 /* double the buffer size until it fits */
91 while (field->num_bits>bitq_in_bufsize*8) bitq_in_bufsize*=2;
92 }
93 /* if necessary, allocate buffer and check for malloc error */
94 if (bitq_in_buffer==NULL && (bitq_in_buffer=malloc(bitq_in_bufsize))==NULL) {
95 ERROR("malloc error");
96 exit(-1);
97 }
98 in_buff=(void *)bitq_in_buffer;
99 }
100 }
101
102 /* field scanning */
103 while (bitq_in_state.bit_pos<field->num_bits) {
104 if ((tdo=bitq_interface->in())<0) {
105 #ifdef _DEBUG_JTAG_IO_
106 DEBUG("bitq in EOF");
107 #endif
108 return;
109 }
110 if (in_mask==0x01) in_buff[in_idx]=0;
111 if (tdo) in_buff[in_idx]|=in_mask;
112 if (in_mask==0x80) {
113 in_mask=0x01;
114 in_idx++;
115 }
116 else in_mask<<=1;
117 bitq_in_state.bit_pos++;
118 }
119
120 if (field->in_check_value) {
121 /* match scanned in value */
122 for (in_idx=0; in_idx*8<field->num_bits; in_idx++) {
123 if (field->in_check_mask) in_mask=field->in_check_mask[in_idx];
124 else in_mask=0xff;
125 if (field->num_bits-in_idx*8<8) in_mask>>=8-(field->num_bits-in_idx*8);
126 if (field->in_check_value[in_idx]&in_mask!=in_buff[in_idx]&in_mask) {
127 char *captured_char = buf_to_str(in_buff, (field->num_bits > 64) ? 64 : field->num_bits, 16);
128 char *in_check_value_char = buf_to_str(field->in_check_value, (field->num_bits > 64) ? 64 : field->num_bits, 16);
129 char *in_check_mask_char = buf_to_str(field->in_check_mask, (field->num_bits > 64) ? 64 : field->num_bits, 16);
130 /* TODO: error reporting */
131 WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char);
132 bitq_in_state.status=ERROR_JTAG_QUEUE_FAILED;
133 free(captured_char);
134 free(in_check_value_char);
135 free(in_check_mask_char);
136 break; /* leave the comparison loop upon first mismatch */
137 }
138 }
139 }
140
141 if (field->in_handler && bitq_in_state.status==ERROR_OK) {
142 bitq_in_state.status=(*field->in_handler)(in_buff, field->in_handler_priv);
143 }
144
145 }
146
147 bitq_in_state.field_idx++; /* advance to next field */
148 bitq_in_state.bit_pos=0; /* start next field from the first bit */
149 }
150
151 }
152 bitq_in_state.cmd=bitq_in_state.cmd->next; /* advance to next command */
153 bitq_in_state.field_idx=0; /* preselect first field */
154 }
155 }
156
157
158
159 void bitq_io(int tms, int tdi, int tdo_req)
160 {
161 bitq_interface->out(tms, tdi, tdo_req);
162 /* check and process the input queue */
163 if (bitq_interface->in_rdy()) bitq_in_proc();
164 }
165
166
167 void bitq_end_state(enum tap_state state)
168 {
169 if (state==-1) return;
170 if (tap_move_map[state]==-1) {
171 ERROR("BUG: %i is not a valid end state", state);
172 exit(-1);
173 }
174 end_state = state;
175 }
176
177
178 void bitq_state_move(enum tap_state new_state)
179 {
180 int i=0;
181 u8 tms_scan;
182
183 if (tap_move_map[cur_state]==-1 || tap_move_map[new_state]==-1) {
184 ERROR("TAP move from or to unstable state");
185 exit(-1);
186 }
187
188 tms_scan=TAP_MOVE(cur_state, new_state);
189
190 for (i=0; i<7; i++) {
191 bitq_io(tms_scan&1, 0, 0);
192 tms_scan>>=1;
193 }
194
195 cur_state = new_state;
196 }
197
198
199 void bitq_path_move(pathmove_command_t *cmd)
200 {
201 int i;
202
203 for (i=0; i<=cmd->num_states; i++) {
204 if (tap_transitions[cur_state].low == cmd->path[i]) bitq_io(0, 0, 0);
205 else if (tap_transitions[cur_state].high == cmd->path[i]) bitq_io(1, 0, 0);
206 else {
207 ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[i]]);
208 exit(-1);
209 }
210
211 cur_state = cmd->path[i];
212 }
213
214 end_state = cur_state;
215 }
216
217
218 void bitq_runtest(int num_cycles)
219 {
220 int i;
221
222 /* only do a state_move when we're not already in RTI */
223 if (cur_state != TAP_RTI) bitq_state_move(TAP_RTI);
224
225 /* execute num_cycles */
226 for (i = 0; i < num_cycles; i++)
227 bitq_io(0, 0, 0);
228
229 /* finish in end_state */
230 if (cur_state != end_state) bitq_state_move(end_state);
231 }
232
233
234 void bitq_scan_field(scan_field_t *field, int pause)
235 {
236 int bit_cnt;
237 int tdo_req;
238
239 u8 *out_ptr;
240 u8 out_mask;
241
242 if (field->in_check_value || field->in_value || field->in_handler) tdo_req=1;
243 else tdo_req=0;
244
245 if (field->out_value==NULL) {
246 /* just send zeros and request data from TDO */
247 for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--)
248 bitq_io(0, 0, tdo_req);
249 bitq_io(pause, 0, tdo_req);
250 }
251 else {
252 /* send data, and optionally request TDO */
253 out_mask=0x01;
254 out_ptr=field->out_value;
255 for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--) {
256 bitq_io(0, ((*out_ptr)&out_mask)!=0, tdo_req);
257 if (out_mask==0x80) {
258 out_mask=0x01;
259 out_ptr++;
260 }
261 else out_mask<<=1;
262 }
263 bitq_io(pause, ((*out_ptr)&out_mask)!=0, tdo_req);
264 }
265
266 if (pause) {
267 bitq_io(0,0,0);
268 if (cur_state==TAP_SI) cur_state=TAP_PI;
269 else if (cur_state==TAP_SD) cur_state=TAP_PD;
270 }
271 }
272
273
274 void bitq_scan(scan_command_t *cmd)
275 {
276 int i;
277
278 if (cmd->ir_scan) bitq_state_move(TAP_SI);
279 else bitq_state_move(TAP_SD);
280
281 for (i=0; i < cmd->num_fields-1; i++)
282 bitq_scan_field(&cmd->fields[i], 0);
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_END_STATE:
301 #ifdef _DEBUG_JTAG_IO_
302 DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
303 #endif
304 bitq_end_state(cmd->cmd.end_state->end_state);
305 break;
306
307 case JTAG_RESET:
308 #ifdef _DEBUG_JTAG_IO_
309 DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
310 #endif
311 bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
312 if (bitq_interface->in_rdy()) bitq_in_proc();
313 break;
314
315 case JTAG_RUNTEST:
316 #ifdef _DEBUG_JTAG_IO_
317 DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
318 #endif
319 bitq_end_state(cmd->cmd.runtest->end_state);
320 bitq_runtest(cmd->cmd.runtest->num_cycles);
321 break;
322
323 case JTAG_STATEMOVE:
324 #ifdef _DEBUG_JTAG_IO_
325 DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
326 #endif
327 bitq_end_state(cmd->cmd.statemove->end_state);
328 bitq_state_move(end_state); /* uncoditional TAP move */
329 break;
330
331 case JTAG_PATHMOVE:
332 #ifdef _DEBUG_JTAG_IO_
333 DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, 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 DEBUG("scan end in %i", cmd->cmd.scan->end_state);
341 if (cmd->cmd.scan->ir_scan) DEBUG("scan ir");
342 else DEBUG("scan dr");
343 #endif
344 bitq_end_state(cmd->cmd.scan->end_state);
345 bitq_scan(cmd->cmd.scan);
346 if (cur_state != end_state) bitq_state_move(end_state);
347 break;
348
349 case JTAG_SLEEP:
350 #ifdef _DEBUG_JTAG_IO_
351 DEBUG("sleep %i", cmd->cmd.sleep->us);
352 #endif
353 bitq_interface->sleep(cmd->cmd.sleep->us);
354 if (bitq_interface->in_rdy()) bitq_in_proc();
355 break;
356
357 default:
358 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 ERROR("missing data from bitq interface");
370 return ERROR_JTAG_QUEUE_FAILED;
371 }
372 if (bitq_interface->in()>=0) {
373 ERROR("extra data from bitq interface");
374 return ERROR_JTAG_QUEUE_FAILED;
375 }
376
377 return bitq_in_state.status;
378 }
379
380
381 void bitq_cleanup(void)
382 {
383 if (bitq_in_buffer!=NULL)
384 {
385 free(bitq_in_buffer);
386 bitq_in_buffer=NULL;
387 }
388 }

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)