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

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)