Add OpenULINK firmware
[openocd.git] / src / jtag / drivers / OpenULINK / src / jtag.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Martin Schmoelzer *
3 * <martin.schmoelzer@student.tuwien.ac.at> *
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
21 #include "jtag.h"
22
23 #include "io.h"
24 #include "msgtypes.h"
25 #include "common.h"
26
27 #include <stdbool.h>
28
29 /** Delay value for SCAN operations with less than maximum TCK frequency */
30 u8 delay_scan = 0;
31
32 /** Delay value for CLOCK_TCK operations */
33 u8 delay_tck = 0;
34
35 /** Delay value for CLOCK_TMS operations with less than maximum frequency */
36 u8 delay_tms = 0;
37
38 /**
39 * Perform JTAG SCAN-IN operation at maximum TCK frequency.
40 *
41 * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
42 * stored in the EP2 IN buffer.
43 *
44 * @param out_offset offset in OUT2BUF where payload data starts
45 */
46 void jtag_scan_in(u8 out_offset, u8 in_offset)
47 {
48 u8 scan_size_bytes, bits_last_byte;
49 u8 tms_count_start, tms_count_end;
50 u8 tms_sequence_start, tms_sequence_end;
51 u8 tdo_data, i, j;
52
53 u8 outb_buffer;
54
55 /* Get parameters from OUT2BUF */
56 scan_size_bytes = OUT2BUF[out_offset];
57 bits_last_byte = OUT2BUF[out_offset + 1];
58 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
59 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
60 tms_sequence_start = OUT2BUF[out_offset + 3];
61 tms_sequence_end = OUT2BUF[out_offset + 4];
62
63 if (tms_count_start > 0) {
64 jtag_clock_tms(tms_count_start, tms_sequence_start);
65 }
66
67 outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
68
69 /* Shift all bytes except the last byte */
70 for (i = 0; i < scan_size_bytes - 1; i++) {
71 tdo_data = 0;
72
73 for (j = 0; j < 8; j++) {
74 OUTB = outb_buffer; /* TCK changes here */
75 OUTB = (outb_buffer | PIN_TCK);
76 tdo_data = tdo_data >> 1;
77
78 if (GET_TDO()) {
79 tdo_data |= 0x80;
80 }
81 }
82
83 /* Copy TDO data to IN2BUF */
84 IN2BUF[i + in_offset] = tdo_data;
85 }
86
87 tdo_data = 0;
88
89 /* Shift the last byte */
90 for (j = 0; j < bits_last_byte; j++) {
91 /* Assert TMS signal if requested and this is the last bit */
92 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
93 outb_buffer |= PIN_TMS;
94 tms_count_end--;
95 tms_sequence_end = tms_sequence_end >> 1;
96 }
97
98 OUTB = outb_buffer; /* TCK change here */
99 OUTB = (outb_buffer | PIN_TCK);
100 tdo_data = tdo_data >> 1;
101
102 if (GET_TDO()) {
103 tdo_data |= 0x80;
104 }
105 }
106 tdo_data = tdo_data >> (8 - bits_last_byte);
107
108 /* Copy TDO data to IN2BUF */
109 IN2BUF[i + in_offset] = tdo_data;
110
111 /* Move to correct end state */
112 if (tms_count_end > 0) {
113 jtag_clock_tms(tms_count_end, tms_sequence_end);
114 }
115 }
116
117 /**
118 * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
119 *
120 * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
121 * data is not sampled.
122 * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
123 *
124 * @param out_offset offset in OUT2BUF where payload data starts
125 */
126 void jtag_scan_out(u8 out_offset)
127 {
128 u8 scan_size_bytes, bits_last_byte;
129 u8 tms_count_start, tms_count_end;
130 u8 tms_sequence_start, tms_sequence_end;
131 u8 tdi_data, i, j;
132
133 u8 outb_buffer;
134
135 /* Get parameters from OUT2BUF */
136 scan_size_bytes = OUT2BUF[out_offset];
137 bits_last_byte = OUT2BUF[out_offset + 1];
138 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
139 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
140 tms_sequence_start = OUT2BUF[out_offset + 3];
141 tms_sequence_end = OUT2BUF[out_offset + 4];
142
143 if (tms_count_start > 0) {
144 jtag_clock_tms(tms_count_start, tms_sequence_start);
145 }
146
147 outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
148
149 /* Shift all bytes except the last byte */
150 for (i = 0; i < scan_size_bytes - 1; i++) {
151 tdi_data = OUT2BUF[i + out_offset + 5];
152
153 for (j = 0; j < 8; j++) {
154 if (tdi_data & 0x01) {
155 outb_buffer |= PIN_TDI;
156 }
157 else {
158 outb_buffer &= ~PIN_TDI;
159 }
160
161 OUTB = outb_buffer; /* TDI and TCK change here */
162 tdi_data = tdi_data >> 1;
163 OUTB = (outb_buffer | PIN_TCK);
164 }
165 }
166
167 tdi_data = OUT2BUF[i + out_offset + 5];
168
169 /* Shift the last byte */
170 for (j = 0; j < bits_last_byte; j++) {
171 if (tdi_data & 0x01) {
172 outb_buffer |= PIN_TDI;
173 }
174 else {
175 outb_buffer &= ~PIN_TDI;
176 }
177
178 /* Assert TMS signal if requested and this is the last bit */
179 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
180 outb_buffer |= PIN_TMS;
181 tms_count_end--;
182 tms_sequence_end = tms_sequence_end >> 1;
183 }
184
185 OUTB = outb_buffer; /* TDI and TCK change here */
186 tdi_data = tdi_data >> 1;
187 OUTB = (outb_buffer | PIN_TCK);
188 }
189
190 /* Move to correct end state */
191 if (tms_count_end > 0) {
192 jtag_clock_tms(tms_count_end, tms_sequence_end);
193 }
194 }
195
196 /**
197 * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
198 *
199 * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
200 * data is sampled and stored in the EP2 IN buffer.
201 * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
202 *
203 * @param out_offset offset in OUT2BUF where payload data starts
204 */
205 void jtag_scan_io(u8 out_offset, u8 in_offset)
206 {
207 u8 scan_size_bytes, bits_last_byte;
208 u8 tms_count_start, tms_count_end;
209 u8 tms_sequence_start, tms_sequence_end;
210 u8 tdi_data, tdo_data, i, j;
211
212 u8 outb_buffer;
213
214 /* Get parameters from OUT2BUF */
215 scan_size_bytes = OUT2BUF[out_offset];
216 bits_last_byte = OUT2BUF[out_offset + 1];
217 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
218 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
219 tms_sequence_start = OUT2BUF[out_offset + 3];
220 tms_sequence_end = OUT2BUF[out_offset + 4];
221
222 if (tms_count_start > 0) {
223 jtag_clock_tms(tms_count_start, tms_sequence_start);
224 }
225
226 outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
227
228 /* Shift all bytes except the last byte */
229 for (i = 0; i < scan_size_bytes - 1; i++) {
230 tdi_data = OUT2BUF[i + out_offset + 5];
231 tdo_data = 0;
232
233 for (j = 0; j < 8; j++) {
234 if (tdi_data & 0x01) {
235 outb_buffer |= PIN_TDI;
236 }
237 else {
238 outb_buffer &= ~PIN_TDI;
239 }
240
241 OUTB = outb_buffer; /* TDI and TCK change here */
242 tdi_data = tdi_data >> 1;
243 OUTB = (outb_buffer | PIN_TCK);
244 tdo_data = tdo_data >> 1;
245
246 if (GET_TDO()) {
247 tdo_data |= 0x80;
248 }
249 }
250
251 /* Copy TDO data to IN2BUF */
252 IN2BUF[i + in_offset] = tdo_data;
253 }
254
255 tdi_data = OUT2BUF[i + out_offset + 5];
256 tdo_data = 0;
257
258 /* Shift the last byte */
259 for (j = 0; j < bits_last_byte; j++) {
260 if (tdi_data & 0x01) {
261 outb_buffer |= PIN_TDI;
262 }
263 else {
264 outb_buffer &= ~PIN_TDI;
265 }
266
267 /* Assert TMS signal if requested and this is the last bit */
268 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
269 outb_buffer |= PIN_TMS;
270 tms_count_end--;
271 tms_sequence_end = tms_sequence_end >> 1;
272 }
273
274 OUTB = outb_buffer; /* TDI and TCK change here */
275 tdi_data = tdi_data >> 1;
276 OUTB = (outb_buffer | PIN_TCK);
277 tdo_data = tdo_data >> 1;
278
279 if (GET_TDO()) {
280 tdo_data |= 0x80;
281 }
282 }
283 tdo_data = tdo_data >> (8 - bits_last_byte);
284
285 /* Copy TDO data to IN2BUF */
286 IN2BUF[i + in_offset] = tdo_data;
287
288 /* Move to correct end state */
289 if (tms_count_end > 0) {
290 jtag_clock_tms(tms_count_end, tms_sequence_end);
291 }
292 }
293
294 /**
295 * Generate TCK clock cycles.
296 *
297 * @param count number of TCK clock cyclces to generate.
298 */
299 void jtag_clock_tck(u16 count)
300 {
301 u16 i;
302 u8 j;
303
304 for ( i = 0; i < count; i++ ) {
305 SET_TCK_LOW();
306 for(j = 0; j < delay_tck; j++);
307
308 SET_TCK_HIGH();
309 for(j = 0; j < delay_tck; j++);
310 }
311 }
312
313 /**
314 * Perform TAP-FSM state transitions at maximum TCK frequency.
315 *
316 * @param count the number of state transitions to perform.
317 * @param sequence the TMS pin levels for each state transition, starting with
318 * the least-significant bit.
319 */
320 void jtag_clock_tms(u8 count, u8 sequence)
321 {
322 volatile u8 outb_buffer;
323 u8 i;
324
325 outb_buffer = OUTB & ~(PIN_TCK);
326
327 for ( i = 0; i < count; i++ ) {
328 /* Set TMS pin according to sequence parameter */
329 if ( sequence & 0x1 ) {
330 outb_buffer |= PIN_TMS;
331 }
332 else {
333 outb_buffer &= ~PIN_TMS;
334 }
335
336 OUTB = outb_buffer;
337 sequence = sequence >> 1;
338 OUTB = outb_buffer | PIN_TCK;
339 }
340 }
341
342 /**
343 * Perform TAP-FSM state transitions at less than maximum TCK frequency.
344 *
345 * @param count the number of state transitions to perform.
346 * @param sequence the TMS pin levels for each state transition, starting with
347 * the least-significant bit.
348 */
349 void jtag_slow_clock_tms(u8 count, u8 sequence)
350 {
351
352 }
353
354 /**
355 * Get current JTAG signal states.
356 *
357 * @return a 16-bit integer where the most-significant byte contains the state
358 * of the JTAG input signals and the least-significant byte cotains the state
359 * of the JTAG output signals.
360 */
361 u16 jtag_get_signals(void)
362 {
363 u8 input_signal_state, output_signal_state;
364
365 input_signal_state = 0;
366 output_signal_state = 0;
367
368 /* Get states of input pins */
369 if (GET_TDO()) {
370 input_signal_state |= SIGNAL_TDO;
371 }
372 if (GET_BRKOUT()) {
373 input_signal_state |= SIGNAL_BRKOUT;
374 }
375 if (GET_TRAP()) {
376 input_signal_state |= SIGNAL_TRAP;
377 }
378 if (GET_RTCK()) {
379 /* Using RTCK this way would be extremely slow,
380 * implemented only for the sake of completeness */
381 input_signal_state |= SIGNAL_RTCK;
382 }
383
384 /* Get states of output pins */
385 output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT;
386
387 return ((u16)input_signal_state << 8) | ((u16)output_signal_state);
388 }
389
390 /**
391 * Set state of JTAG output signals.
392 *
393 * @param low signals which should be de-asserted.
394 * @param high signals which should be asserted.
395 */
396 void jtag_set_signals(u8 low, u8 high)
397 {
398 OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
399 OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
400 }
401
402 /**
403 * Configure TCK delay parameters.
404 *
405 * @param scan number of delay cycles in shift operations.
406 * @param tck number of delay cycles in clock_tck operations.
407 * @param tms number of delay cycles in clock_tms operations.
408 */
409 void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms)
410 {
411 delay_scan = scan;
412 delay_tck = tck;
413 delay_tms = tms;
414 }

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)