- added patch "remove error handler as planned"
[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 /* loop through the queue */
65 while (bitq_in_state.cmd) {
66 /* only JTAG_SCAN command may return data */
67 if (bitq_in_state.cmd->type==JTAG_SCAN) {
68 /* loop through the fields */
69 while (bitq_in_state.field_idx<bitq_in_state.cmd->cmd.scan->num_fields) {
70
71 field=&bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
72 if ( field->in_value || field->in_handler) {
73
74 if (bitq_in_state.bit_pos==0) {
75 /* initialize field scanning */
76 in_mask=0x01;
77 in_idx=0;
78 if (field->in_value) in_buff=field->in_value;
79 else {
80 /* buffer reallocation needed? */
81 if (field->num_bits>bitq_in_bufsize*8) {
82 /* buffer previously allocated? */
83 if (bitq_in_buffer!=NULL) {
84 /* free it */
85 free(bitq_in_buffer);
86 bitq_in_buffer=NULL;
87 }
88 /* double the buffer size until it fits */
89 while (field->num_bits>bitq_in_bufsize*8) bitq_in_bufsize*=2;
90 }
91 /* if necessary, allocate buffer and check for malloc error */
92 if (bitq_in_buffer==NULL && (bitq_in_buffer=malloc(bitq_in_bufsize))==NULL) {
93 ERROR("malloc error");
94 exit(-1);
95 }
96 in_buff=(void *)bitq_in_buffer;
97 }
98 }
99
100 /* field scanning */
101 while (bitq_in_state.bit_pos<field->num_bits) {
102 if ((tdo=bitq_interface->in())<0) {
103 #ifdef _DEBUG_JTAG_IO_
104 DEBUG("bitq in EOF");
105 #endif
106 return;
107 }
108 if (in_mask==0x01) in_buff[in_idx]=0;
109 if (tdo) in_buff[in_idx]|=in_mask;
110 if (in_mask==0x80) {
111 in_mask=0x01;
112 in_idx++;
113 }
114 else in_mask<<=1;
115 bitq_in_state.bit_pos++;
116 }
117
118
119 if (field->in_handler && bitq_in_state.status==ERROR_OK) {
120 bitq_in_state.status=(*field->in_handler)(in_buff, field->in_handler_priv, field);
121 }
122
123 }
124
125 bitq_in_state.field_idx++; /* advance to next field */
126 bitq_in_state.bit_pos=0; /* start next field from the first bit */
127 }
128
129 }
130 bitq_in_state.cmd=bitq_in_state.cmd->next; /* advance to next command */
131 bitq_in_state.field_idx=0; /* preselect first field */
132 }
133 }
134
135
136
137 void bitq_io(int tms, int tdi, int tdo_req)
138 {
139 bitq_interface->out(tms, tdi, tdo_req);
140 /* check and process the input queue */
141 if (bitq_interface->in_rdy()) bitq_in_proc();
142 }
143
144
145 void bitq_end_state(enum tap_state state)
146 {
147 if (state==-1) return;
148 if (tap_move_map[state]==-1) {
149 ERROR("BUG: %i is not a valid end state", state);
150 exit(-1);
151 }
152 end_state = state;
153 }
154
155
156 void bitq_state_move(enum tap_state new_state)
157 {
158 int i=0;
159 u8 tms_scan;
160
161 if (tap_move_map[cur_state]==-1 || tap_move_map[new_state]==-1) {
162 ERROR("TAP move from or to unstable state");
163 exit(-1);
164 }
165
166 tms_scan=TAP_MOVE(cur_state, new_state);
167
168 for (i=0; i<7; i++) {
169 bitq_io(tms_scan&1, 0, 0);
170 tms_scan>>=1;
171 }
172
173 cur_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 if (tap_transitions[cur_state].low == cmd->path[i]) bitq_io(0, 0, 0);
183 else if (tap_transitions[cur_state].high == cmd->path[i]) bitq_io(1, 0, 0);
184 else {
185 ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[i]]);
186 exit(-1);
187 }
188
189 cur_state = cmd->path[i];
190 }
191
192 end_state = cur_state;
193 }
194
195
196 void bitq_runtest(int num_cycles)
197 {
198 int i;
199
200 /* only do a state_move when we're not already in RTI */
201 if (cur_state != TAP_RTI) bitq_state_move(TAP_RTI);
202
203 /* execute num_cycles */
204 for (i = 0; i < num_cycles; i++)
205 bitq_io(0, 0, 0);
206
207 /* finish in end_state */
208 if (cur_state != end_state) bitq_state_move(end_state);
209 }
210
211
212 void bitq_scan_field(scan_field_t *field, int pause)
213 {
214 int bit_cnt;
215 int tdo_req;
216
217 u8 *out_ptr;
218 u8 out_mask;
219
220 if ( field->in_value || field->in_handler) tdo_req=1;
221 else tdo_req=0;
222
223 if (field->out_value==NULL) {
224 /* just send zeros and request data from TDO */
225 for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--)
226 bitq_io(0, 0, tdo_req);
227 bitq_io(pause, 0, tdo_req);
228 }
229 else {
230 /* send data, and optionally request TDO */
231 out_mask=0x01;
232 out_ptr=field->out_value;
233 for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--) {
234 bitq_io(0, ((*out_ptr)&out_mask)!=0, tdo_req);
235 if (out_mask==0x80) {
236 out_mask=0x01;
237 out_ptr++;
238 }
239 else out_mask<<=1;
240 }
241 bitq_io(pause, ((*out_ptr)&out_mask)!=0, tdo_req);
242 }
243
244 if (pause) {
245 bitq_io(0,0,0);
246 if (cur_state==TAP_SI) cur_state=TAP_PI;
247 else if (cur_state==TAP_SD) cur_state=TAP_PD;
248 }
249 }
250
251
252 void bitq_scan(scan_command_t *cmd)
253 {
254 int i;
255
256 if (cmd->ir_scan) bitq_state_move(TAP_SI);
257 else bitq_state_move(TAP_SD);
258
259 for (i=0; i < cmd->num_fields-1; i++)
260 bitq_scan_field(&cmd->fields[i], 0);
261 bitq_scan_field(&cmd->fields[i], 1);
262 }
263
264
265 int bitq_execute_queue(void)
266 {
267 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
268
269 bitq_in_state.cmd = jtag_command_queue;
270 bitq_in_state.field_idx = 0;
271 bitq_in_state.bit_pos = 0;
272 bitq_in_state.status = ERROR_OK;
273
274 while (cmd) {
275
276 switch (cmd->type) {
277
278 case JTAG_END_STATE:
279 #ifdef _DEBUG_JTAG_IO_
280 DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
281 #endif
282 bitq_end_state(cmd->cmd.end_state->end_state);
283 break;
284
285 case JTAG_RESET:
286 #ifdef _DEBUG_JTAG_IO_
287 DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
288 #endif
289 bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
290 if (bitq_interface->in_rdy()) bitq_in_proc();
291 break;
292
293 case JTAG_RUNTEST:
294 #ifdef _DEBUG_JTAG_IO_
295 DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
296 #endif
297 bitq_end_state(cmd->cmd.runtest->end_state);
298 bitq_runtest(cmd->cmd.runtest->num_cycles);
299 break;
300
301 case JTAG_STATEMOVE:
302 #ifdef _DEBUG_JTAG_IO_
303 DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
304 #endif
305 bitq_end_state(cmd->cmd.statemove->end_state);
306 bitq_state_move(end_state); /* uncoditional TAP move */
307 break;
308
309 case JTAG_PATHMOVE:
310 #ifdef _DEBUG_JTAG_IO_
311 DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
312 #endif
313 bitq_path_move(cmd->cmd.pathmove);
314 break;
315
316 case JTAG_SCAN:
317 #ifdef _DEBUG_JTAG_IO_
318 DEBUG("scan end in %i", cmd->cmd.scan->end_state);
319 if (cmd->cmd.scan->ir_scan) DEBUG("scan ir");
320 else DEBUG("scan dr");
321 #endif
322 bitq_end_state(cmd->cmd.scan->end_state);
323 bitq_scan(cmd->cmd.scan);
324 if (cur_state != end_state) bitq_state_move(end_state);
325 break;
326
327 case JTAG_SLEEP:
328 #ifdef _DEBUG_JTAG_IO_
329 DEBUG("sleep %i", cmd->cmd.sleep->us);
330 #endif
331 bitq_interface->sleep(cmd->cmd.sleep->us);
332 if (bitq_interface->in_rdy()) bitq_in_proc();
333 break;
334
335 default:
336 ERROR("BUG: unknown JTAG command type encountered");
337 exit(-1);
338 }
339
340 cmd = cmd->next;
341 }
342
343 bitq_interface->flush();
344 bitq_in_proc();
345
346 if (bitq_in_state.cmd) {
347 ERROR("missing data from bitq interface");
348 return ERROR_JTAG_QUEUE_FAILED;
349 }
350 if (bitq_interface->in()>=0) {
351 ERROR("extra data from bitq interface");
352 return ERROR_JTAG_QUEUE_FAILED;
353 }
354
355 return bitq_in_state.status;
356 }
357
358
359 void bitq_cleanup(void)
360 {
361 if (bitq_in_buffer!=NULL)
362 {
363 free(bitq_in_buffer);
364 bitq_in_buffer=NULL;
365 }
366 }

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)