bitq: remove the remaining static variables
[openocd.git] / src / jtag / drivers / 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 <jtag/jtag.h>
25 #include "bitq.h"
26 #include <jtag/interface.h>
27
28
29 struct bitq_interface* bitq_interface; /* low level bit queue interface */
30
31 /* state of input queue */
32 struct bitq_state {
33 struct jtag_command *cmd; /* command currently processed */
34 int field_idx; /* index of field currently being processed */
35 int bit_pos; /* position of bit currently being processed */
36 int status; /* processing status */
37 };
38 static struct bitq_state bitq_in_state;
39
40 /*
41 * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
42 * no parameters, makes use of stored state information
43 */
44 void bitq_in_proc(void)
45 {
46 struct scan_field* 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 /* field scanning */
62 while (bitq_in_state.bit_pos < field->num_bits)
63 {
64 /* index of byte being scanned */
65 int in_idx = bitq_in_state.bit_pos / 8;
66 /* mask of next bit to be scanned */
67 uint8_t in_mask = 1 << (bitq_in_state.bit_pos % 8);
68
69 if ((tdo = bitq_interface->in()) < 0)
70 {
71 #ifdef _DEBUG_JTAG_IO_
72 LOG_DEBUG("bitq in EOF");
73 #endif
74 return;
75 }
76 if (in_mask == 0x01)
77 field->in_value[in_idx] = 0;
78 if (tdo)
79 field->in_value[in_idx] |= in_mask;
80 bitq_in_state.bit_pos++;
81 }
82 }
83
84 bitq_in_state.field_idx++; /* advance to next field */
85 bitq_in_state.bit_pos = 0; /* start next field from the first bit */
86 }
87 }
88 bitq_in_state.cmd = bitq_in_state.cmd->next; /* advance to next command */
89 bitq_in_state.field_idx = 0; /* preselect first field */
90 }
91 }
92
93
94 void bitq_io(int tms, int tdi, int tdo_req)
95 {
96 bitq_interface->out(tms, tdi, tdo_req);
97 /* check and process the input queue */
98 if (bitq_interface->in_rdy())
99 bitq_in_proc();
100 }
101
102
103 void bitq_end_state(tap_state_t state)
104 {
105 if (!tap_is_state_stable(state))
106 {
107 LOG_ERROR("BUG: %i is not a valid end state", state);
108 exit(-1);
109 }
110 tap_set_end_state(state);
111 }
112
113
114 void bitq_state_move(tap_state_t new_state)
115 {
116 int i = 0;
117 uint8_t tms_scan;
118
119 if (!tap_is_state_stable(tap_get_state()) || !tap_is_state_stable(new_state))
120 {
121 LOG_ERROR("TAP move from or to unstable state");
122 exit(-1);
123 }
124
125 tms_scan = tap_get_tms_path(tap_get_state(), new_state);
126 int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
127
128 for (i = 0; i < tms_count; i++)
129 {
130 bitq_io(tms_scan & 1, 0, 0);
131 tms_scan >>= 1;
132 }
133
134 tap_set_state(new_state);
135 }
136
137
138 void bitq_path_move(struct pathmove_command* cmd)
139 {
140 int i;
141
142 for (i = 0; i <= cmd->num_states; i++)
143 {
144 if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
145 bitq_io(0, 0, 0);
146 else if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
147 bitq_io(1, 0, 0);
148 else
149 {
150 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(
151 tap_get_state()), tap_state_name(cmd->path[i]));
152 exit(-1);
153 }
154
155 tap_set_state(cmd->path[i]);
156 }
157
158 tap_set_end_state(tap_get_state());
159 }
160
161
162 void bitq_runtest(int num_cycles)
163 {
164 int i;
165
166 /* only do a state_move when we're not already in IDLE */
167 if (tap_get_state() != TAP_IDLE)
168 bitq_state_move(TAP_IDLE);
169
170 /* execute num_cycles */
171 for (i = 0; i < num_cycles; i++)
172 bitq_io(0, 0, 0);
173
174 /* finish in end_state */
175 if (tap_get_state() != tap_get_end_state())
176 bitq_state_move(tap_get_end_state());
177 }
178
179
180 void bitq_scan_field(struct scan_field* field, int do_pause)
181 {
182 int bit_cnt;
183 int tdo_req;
184
185 const uint8_t* out_ptr;
186 uint8_t out_mask;
187
188 if (field->in_value)
189 tdo_req = 1;
190 else
191 tdo_req = 0;
192
193 if (field->out_value == NULL)
194 {
195 /* just send zeros and request data from TDO */
196 for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--)
197 bitq_io(0, 0, tdo_req);
198
199 bitq_io(do_pause, 0, tdo_req);
200 }
201 else
202 {
203 /* send data, and optionally request TDO */
204 out_mask = 0x01;
205 out_ptr = field->out_value;
206 for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--)
207 {
208 bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req);
209 if (out_mask == 0x80)
210 {
211 out_mask = 0x01;
212 out_ptr++;
213 }
214 else
215 out_mask <<= 1;
216 }
217
218 bitq_io(do_pause, ((*out_ptr) & out_mask) != 0, tdo_req);
219 }
220
221 if (do_pause)
222 {
223 bitq_io(0, 0, 0);
224 if (tap_get_state() == TAP_IRSHIFT)
225 tap_set_state(TAP_IRPAUSE);
226 else if (tap_get_state() == TAP_DRSHIFT)
227 tap_set_state(TAP_DRPAUSE);
228 }
229 }
230
231
232 void bitq_scan(struct scan_command* cmd)
233 {
234 int i;
235
236 if (cmd->ir_scan)
237 bitq_state_move(TAP_IRSHIFT);
238 else
239 bitq_state_move(TAP_DRSHIFT);
240
241 for (i = 0; i < cmd->num_fields - 1; i++)
242 bitq_scan_field(&cmd->fields[i], 0);
243
244 bitq_scan_field(&cmd->fields[i], 1);
245 }
246
247
248 int bitq_execute_queue(void)
249 {
250 struct jtag_command* cmd = jtag_command_queue; /* currently processed command */
251
252 bitq_in_state.cmd = jtag_command_queue;
253 bitq_in_state.field_idx = 0;
254 bitq_in_state.bit_pos = 0;
255 bitq_in_state.status = ERROR_OK;
256
257 while (cmd)
258 {
259 switch (cmd->type)
260 {
261 case JTAG_RESET:
262 #ifdef _DEBUG_JTAG_IO_
263 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
264 #endif
265 if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
266 {
267 tap_set_state(TAP_RESET);
268 }
269 bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
270 if (bitq_interface->in_rdy())
271 bitq_in_proc();
272 break;
273
274 case JTAG_RUNTEST:
275 #ifdef _DEBUG_JTAG_IO_
276 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
277 #endif
278 bitq_end_state(cmd->cmd.runtest->end_state);
279 bitq_runtest(cmd->cmd.runtest->num_cycles);
280 break;
281
282 case JTAG_TLR_RESET:
283 #ifdef _DEBUG_JTAG_IO_
284 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
285 #endif
286 bitq_end_state(cmd->cmd.statemove->end_state);
287 bitq_state_move(tap_get_end_state()); /* uncoditional TAP move */
288 break;
289
290 case JTAG_PATHMOVE:
291 #ifdef _DEBUG_JTAG_IO_
292 LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
293 cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
294 #endif
295 bitq_path_move(cmd->cmd.pathmove);
296 break;
297
298 case JTAG_SCAN:
299 #ifdef _DEBUG_JTAG_IO_
300 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
301 if (cmd->cmd.scan->ir_scan)
302 LOG_DEBUG("scan ir");
303 else
304 LOG_DEBUG("scan dr");
305 #endif
306 bitq_end_state(cmd->cmd.scan->end_state);
307 bitq_scan(cmd->cmd.scan);
308 if (tap_get_state() != tap_get_end_state())
309 bitq_state_move(tap_get_end_state());
310 break;
311
312 case JTAG_SLEEP:
313 #ifdef _DEBUG_JTAG_IO_
314 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
315 #endif
316 bitq_interface->sleep(cmd->cmd.sleep->us);
317 if (bitq_interface->in_rdy())
318 bitq_in_proc();
319 break;
320
321 default:
322 LOG_ERROR("BUG: unknown JTAG command type encountered");
323 exit(-1);
324 }
325
326 cmd = cmd->next;
327 }
328
329 bitq_interface->flush();
330 bitq_in_proc();
331
332 if (bitq_in_state.cmd)
333 {
334 LOG_ERROR("missing data from bitq interface");
335 return ERROR_JTAG_QUEUE_FAILED;
336 }
337 if (bitq_interface->in() >= 0)
338 {
339 LOG_ERROR("extra data from bitq interface");
340 return ERROR_JTAG_QUEUE_FAILED;
341 }
342
343 return bitq_in_state.status;
344 }
345
346
347 void bitq_cleanup(void)
348 {
349 }

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)