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

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)