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

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)