OpenOCD
OpenULINK/src/jtag.c
Go to the documentation of this file.
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, see <http://www.gnu.org/licenses/>. *
17  ***************************************************************************/
18 
19 #include "jtag.h"
20 
21 #include "io.h"
22 #include "msgtypes.h"
23 #include "common.h"
24 
25 #include <stdbool.h>
26 
28 uint8_t delay_scan_in;
29 
32 
34 uint8_t delay_scan_io;
35 
37 uint8_t delay_tck;
38 
40 uint8_t delay_tms;
41 
52 void jtag_scan_in(uint8_t out_offset, uint8_t in_offset)
53 {
54  uint8_t scan_size_bytes, bits_last_byte;
55  uint8_t tms_count_start, tms_count_end;
56  uint8_t tms_sequence_start, tms_sequence_end;
57  uint8_t tdo_data, i, j;
58 
59  uint8_t outb_buffer;
60 
61  /* Get parameters from OUT2BUF */
62  scan_size_bytes = OUT2BUF[out_offset];
63  bits_last_byte = OUT2BUF[out_offset + 1];
64  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
65  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
66  tms_sequence_start = OUT2BUF[out_offset + 3];
67  tms_sequence_end = OUT2BUF[out_offset + 4];
68 
69  if (tms_count_start > 0)
70  jtag_clock_tms(tms_count_start, tms_sequence_start);
71 
72  outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
73 
74  /* Shift all bytes except the last byte */
75  for (i = 0; i < scan_size_bytes - 1; i++) {
76  tdo_data = 0;
77 
78  for (j = 0; j < 8; j++) {
79  OUTB = outb_buffer; /* TCK changes here */
80  tdo_data = tdo_data >> 1;
81  OUTB = (outb_buffer | PIN_TCK);
82 
83  if (GET_TDO())
84  tdo_data |= 0x80;
85  }
86 
87  /* Copy TDO data to IN2BUF */
88  IN2BUF[i + in_offset] = tdo_data;
89  }
90 
91  tdo_data = 0;
92 
93  /* Shift the last byte */
94  for (j = 0; j < bits_last_byte; j++) {
95  /* Assert TMS signal if requested and this is the last bit */
96  if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
97  outb_buffer |= PIN_TMS;
98  tms_count_end--;
99  tms_sequence_end = tms_sequence_end >> 1;
100  }
101 
102  OUTB = outb_buffer; /* TCK changes here */
103  tdo_data = tdo_data >> 1;
104  OUTB = (outb_buffer | PIN_TCK);
105 
106  if (GET_TDO())
107  tdo_data |= 0x80;
108  }
109  tdo_data = tdo_data >> (8 - bits_last_byte);
110 
111  /* Copy TDO data to IN2BUF */
112  IN2BUF[i + in_offset] = tdo_data;
113 
114  /* Move to correct end state */
115  if (tms_count_end > 0)
116  jtag_clock_tms(tms_count_end, tms_sequence_end);
117 }
118 
129 void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset)
130 {
131  uint8_t scan_size_bytes, bits_last_byte;
132  uint8_t tms_count_start, tms_count_end;
133  uint8_t tms_sequence_start, tms_sequence_end;
134  uint8_t tdo_data, i, j, k;
135 
136  uint8_t outb_buffer;
137 
138  /* Get parameters from OUT2BUF */
139  scan_size_bytes = OUT2BUF[out_offset];
140  bits_last_byte = OUT2BUF[out_offset + 1];
141  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
142  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
143  tms_sequence_start = OUT2BUF[out_offset + 3];
144  tms_sequence_end = OUT2BUF[out_offset + 4];
145 
146  if (tms_count_start > 0)
147  jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
148 
149  outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
150 
151  /* Shift all bytes except the last byte */
152  for (i = 0; i < scan_size_bytes - 1; i++) {
153  tdo_data = 0;
154 
155  for (j = 0; j < 8; j++) {
156  OUTB = outb_buffer; /* TCK changes here */
157  for (k = 0; k < delay_scan_in; k++)
158  ;
159  tdo_data = tdo_data >> 1;
160 
161  OUTB = (outb_buffer | PIN_TCK);
162  for (k = 0; k < delay_scan_in; k++)
163  ;
164 
165  if (GET_TDO())
166  tdo_data |= 0x80;
167  }
168 
169  /* Copy TDO data to IN2BUF */
170  IN2BUF[i + in_offset] = tdo_data;
171  }
172 
173  tdo_data = 0;
174 
175  /* Shift the last byte */
176  for (j = 0; j < bits_last_byte; j++) {
177  /* Assert TMS signal if requested and this is the last bit */
178  if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
179  outb_buffer |= PIN_TMS;
180  tms_count_end--;
181  tms_sequence_end = tms_sequence_end >> 1;
182  }
183 
184  OUTB = outb_buffer; /* TCK changes here */
185  for (k = 0; k < delay_scan_in; k++)
186  ;
187  tdo_data = tdo_data >> 1;
188 
189  OUTB = (outb_buffer | PIN_TCK);
190  for (k = 0; k < delay_scan_in; k++)
191  ;
192 
193  if (GET_TDO())
194  tdo_data |= 0x80;
195  }
196  tdo_data = tdo_data >> (8 - bits_last_byte);
197 
198  /* Copy TDO data to IN2BUF */
199  IN2BUF[i + in_offset] = tdo_data;
200 
201  /* Move to correct end state */
202  if (tms_count_end > 0)
203  jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
204 }
205 
217 void jtag_scan_out(uint8_t out_offset)
218 {
219  uint8_t scan_size_bytes, bits_last_byte;
220  uint8_t tms_count_start, tms_count_end;
221  uint8_t tms_sequence_start, tms_sequence_end;
222  uint8_t tdi_data, i, j;
223 
224  uint8_t outb_buffer;
225 
226  /* Get parameters from OUT2BUF */
227  scan_size_bytes = OUT2BUF[out_offset];
228  bits_last_byte = OUT2BUF[out_offset + 1];
229  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
230  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
231  tms_sequence_start = OUT2BUF[out_offset + 3];
232  tms_sequence_end = OUT2BUF[out_offset + 4];
233 
234  if (tms_count_start > 0)
235  jtag_clock_tms(tms_count_start, tms_sequence_start);
236 
237  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
238 
239  /* Shift all bytes except the last byte */
240  for (i = 0; i < scan_size_bytes - 1; i++) {
241  tdi_data = OUT2BUF[i + out_offset + 5];
242 
243  for (j = 0; j < 8; j++) {
244  if (tdi_data & 0x01)
245  outb_buffer |= PIN_TDI;
246  else
247  outb_buffer &= ~PIN_TDI;
248 
249  OUTB = outb_buffer; /* TDI and TCK change here */
250  tdi_data = tdi_data >> 1;
251  OUTB = (outb_buffer | PIN_TCK);
252  }
253  }
254 
255  tdi_data = OUT2BUF[i + out_offset + 5];
256 
257  /* Shift the last byte */
258  for (j = 0; j < bits_last_byte; j++) {
259  if (tdi_data & 0x01)
260  outb_buffer |= PIN_TDI;
261  else
262  outb_buffer &= ~PIN_TDI;
263 
264  /* Assert TMS signal if requested and this is the last bit */
265  if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
266  outb_buffer |= PIN_TMS;
267  tms_count_end--;
268  tms_sequence_end = tms_sequence_end >> 1;
269  }
270 
271  OUTB = outb_buffer; /* TDI and TCK change here */
272  tdi_data = tdi_data >> 1;
273  OUTB = (outb_buffer | PIN_TCK);
274  }
275 
276  /* Move to correct end state */
277  if (tms_count_end > 0)
278  jtag_clock_tms(tms_count_end, tms_sequence_end);
279 }
280 
292 void jtag_slow_scan_out(uint8_t out_offset)
293 {
294  uint8_t scan_size_bytes, bits_last_byte;
295  uint8_t tms_count_start, tms_count_end;
296  uint8_t tms_sequence_start, tms_sequence_end;
297  uint8_t tdi_data, i, j, k;
298 
299  uint8_t outb_buffer;
300 
301  /* Get parameters from OUT2BUF */
302  scan_size_bytes = OUT2BUF[out_offset];
303  bits_last_byte = OUT2BUF[out_offset + 1];
304  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
305  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
306  tms_sequence_start = OUT2BUF[out_offset + 3];
307  tms_sequence_end = OUT2BUF[out_offset + 4];
308 
309  if (tms_count_start > 0)
310  jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
311 
312  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
313 
314  /* Shift all bytes except the last byte */
315  for (i = 0; i < scan_size_bytes - 1; i++) {
316  tdi_data = OUT2BUF[i + out_offset + 5];
317 
318  for (j = 0; j < 8; j++) {
319  if (tdi_data & 0x01)
320  outb_buffer |= PIN_TDI;
321  else
322  outb_buffer &= ~PIN_TDI;
323 
324  OUTB = outb_buffer; /* TDI and TCK change here */
325  for (k = 0; k < delay_scan_out; k++)
326  ;
327  tdi_data = tdi_data >> 1;
328 
329  OUTB = (outb_buffer | PIN_TCK);
330  for (k = 0; k < delay_scan_out; k++)
331  ;
332  }
333  }
334 
335  tdi_data = OUT2BUF[i + out_offset + 5];
336 
337  /* Shift the last byte */
338  for (j = 0; j < bits_last_byte; j++) {
339  if (tdi_data & 0x01)
340  outb_buffer |= PIN_TDI;
341  else
342  outb_buffer &= ~PIN_TDI;
343 
344  /* Assert TMS signal if requested and this is the last bit */
345  if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
346  outb_buffer |= PIN_TMS;
347  tms_count_end--;
348  tms_sequence_end = tms_sequence_end >> 1;
349  }
350 
351  OUTB = outb_buffer; /* TDI and TCK change here */
352  for (k = 0; k < delay_scan_out; k++)
353  ;
354  tdi_data = tdi_data >> 1;
355 
356  OUTB = (outb_buffer | PIN_TCK);
357  for (k = 0; k < delay_scan_out; k++)
358  ;
359  }
360 
361  /* Move to correct end state */
362  if (tms_count_end > 0)
363  jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
364 }
365 
377 void jtag_scan_io(uint8_t out_offset, uint8_t in_offset)
378 {
379  uint8_t scan_size_bytes, bits_last_byte;
380  uint8_t tms_count_start, tms_count_end;
381  uint8_t tms_sequence_start, tms_sequence_end;
382  uint8_t tdi_data, tdo_data, i, j;
383 
384  uint8_t outb_buffer;
385 
386  /* Get parameters from OUT2BUF */
387  scan_size_bytes = OUT2BUF[out_offset];
388  bits_last_byte = OUT2BUF[out_offset + 1];
389  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
390  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
391  tms_sequence_start = OUT2BUF[out_offset + 3];
392  tms_sequence_end = OUT2BUF[out_offset + 4];
393 
394  if (tms_count_start > 0)
395  jtag_clock_tms(tms_count_start, tms_sequence_start);
396 
397  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
398 
399  /* Shift all bytes except the last byte */
400  for (i = 0; i < scan_size_bytes - 1; i++) {
401  tdi_data = OUT2BUF[i + out_offset + 5];
402  tdo_data = 0;
403 
404  for (j = 0; j < 8; j++) {
405  if (tdi_data & 0x01)
406  outb_buffer |= PIN_TDI;
407  else
408  outb_buffer &= ~PIN_TDI;
409 
410  OUTB = outb_buffer; /* TDI and TCK change here */
411  tdi_data = tdi_data >> 1;
412  OUTB = (outb_buffer | PIN_TCK);
413  tdo_data = tdo_data >> 1;
414 
415  if (GET_TDO())
416  tdo_data |= 0x80;
417  }
418 
419  /* Copy TDO data to IN2BUF */
420  IN2BUF[i + in_offset] = tdo_data;
421  }
422 
423  tdi_data = OUT2BUF[i + out_offset + 5];
424  tdo_data = 0;
425 
426  /* Shift the last byte */
427  for (j = 0; j < bits_last_byte; j++) {
428  if (tdi_data & 0x01)
429  outb_buffer |= PIN_TDI;
430  else
431  outb_buffer &= ~PIN_TDI;
432 
433  /* Assert TMS signal if requested and this is the last bit */
434  if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
435  outb_buffer |= PIN_TMS;
436  tms_count_end--;
437  tms_sequence_end = tms_sequence_end >> 1;
438  }
439 
440  OUTB = outb_buffer; /* TDI and TCK change here */
441  tdi_data = tdi_data >> 1;
442  OUTB = (outb_buffer | PIN_TCK);
443  tdo_data = tdo_data >> 1;
444 
445  if (GET_TDO())
446  tdo_data |= 0x80;
447  }
448  tdo_data = tdo_data >> (8 - bits_last_byte);
449 
450  /* Copy TDO data to IN2BUF */
451  IN2BUF[i + in_offset] = tdo_data;
452 
453  /* Move to correct end state */
454  if (tms_count_end > 0)
455  jtag_clock_tms(tms_count_end, tms_sequence_end);
456 }
457 
469 void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset)
470 {
471  uint8_t scan_size_bytes, bits_last_byte;
472  uint8_t tms_count_start, tms_count_end;
473  uint8_t tms_sequence_start, tms_sequence_end;
474  uint8_t tdi_data, tdo_data, i, j, k;
475 
476  uint8_t outb_buffer;
477 
478  /* Get parameters from OUT2BUF */
479  scan_size_bytes = OUT2BUF[out_offset];
480  bits_last_byte = OUT2BUF[out_offset + 1];
481  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
482  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
483  tms_sequence_start = OUT2BUF[out_offset + 3];
484  tms_sequence_end = OUT2BUF[out_offset + 4];
485 
486  if (tms_count_start > 0)
487  jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
488 
489  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
490 
491  /* Shift all bytes except the last byte */
492  for (i = 0; i < scan_size_bytes - 1; i++) {
493  tdi_data = OUT2BUF[i + out_offset + 5];
494  tdo_data = 0;
495 
496  for (j = 0; j < 8; j++) {
497  if (tdi_data & 0x01)
498  outb_buffer |= PIN_TDI;
499  else
500  outb_buffer &= ~PIN_TDI;
501 
502  OUTB = outb_buffer; /* TDI and TCK change here */
503  for (k = 0; k < delay_scan_io; k++)
504  ;
505  tdi_data = tdi_data >> 1;
506 
507  OUTB = (outb_buffer | PIN_TCK);
508  for (k = 0; k < delay_scan_io; k++)
509  ;
510  tdo_data = tdo_data >> 1;
511 
512  if (GET_TDO())
513  tdo_data |= 0x80;
514  }
515 
516  /* Copy TDO data to IN2BUF */
517  IN2BUF[i + in_offset] = tdo_data;
518  }
519 
520  tdi_data = OUT2BUF[i + out_offset + 5];
521  tdo_data = 0;
522 
523  /* Shift the last byte */
524  for (j = 0; j < bits_last_byte; j++) {
525  if (tdi_data & 0x01)
526  outb_buffer |= PIN_TDI;
527  else
528  outb_buffer &= ~PIN_TDI;
529 
530  /* Assert TMS signal if requested and this is the last bit */
531  if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
532  outb_buffer |= PIN_TMS;
533  tms_count_end--;
534  tms_sequence_end = tms_sequence_end >> 1;
535  }
536 
537  OUTB = outb_buffer; /* TDI and TCK change here */
538  for (k = 0; k < delay_scan_io; k++)
539  ;
540  tdi_data = tdi_data >> 1;
541 
542  OUTB = (outb_buffer | PIN_TCK);
543  for (k = 0; k < delay_scan_io; k++)
544  ;
545  tdo_data = tdo_data >> 1;
546 
547  if (GET_TDO())
548  tdo_data |= 0x80;
549  }
550  tdo_data = tdo_data >> (8 - bits_last_byte);
551 
552  /* Copy TDO data to IN2BUF */
553  IN2BUF[i + in_offset] = tdo_data;
554 
555  /* Move to correct end state */
556  if (tms_count_end > 0)
557  jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
558 }
559 
567 void jtag_clock_tck(uint16_t count)
568 {
569  uint16_t i;
570  uint8_t outb_buffer = OUTB & ~(PIN_TCK);
571 
572  for (i = 0; i < count; i++) {
573  OUTB = outb_buffer;
574  OUTB = outb_buffer | PIN_TCK;
575  }
576 }
577 
586 {
587  uint16_t i;
588  uint8_t j;
589  uint8_t outb_buffer = OUTB & ~(PIN_TCK);
590 
591  for (i = 0; i < count; i++) {
592  OUTB = outb_buffer;
593  for (j = 0; j < delay_tck; j++)
594  ;
595  OUTB = outb_buffer | PIN_TCK;
596  for (j = 0; j < delay_tck; j++)
597  ;
598  }
599 }
600 
610 void jtag_clock_tms(uint8_t count, uint8_t sequence)
611 {
612  uint8_t outb_buffer = OUTB & ~(PIN_TCK);
613  uint8_t i;
614 
615  for (i = 0; i < count; i++) {
616  /* Set TMS pin according to sequence parameter */
617  if (sequence & 0x1)
618  outb_buffer |= PIN_TMS;
619  else
620  outb_buffer &= ~PIN_TMS;
621 
622  OUTB = outb_buffer;
623  sequence = sequence >> 1;
624  OUTB = outb_buffer | PIN_TCK;
625  }
626 }
627 
637 void jtag_slow_clock_tms(uint8_t count, uint8_t sequence)
638 {
639  uint8_t outb_buffer = OUTB & ~(PIN_TCK);
640  uint8_t i, j;
641 
642  for (i = 0; i < count; i++) {
643  /* Set TMS pin according to sequence parameter */
644  if (sequence & 0x1)
645  outb_buffer |= PIN_TMS;
646  else
647  outb_buffer &= ~PIN_TMS;
648 
649  OUTB = outb_buffer;
650  for (j = 0; j < delay_tms; j++)
651  ;
652  sequence = sequence >> 1;
653  OUTB = outb_buffer | PIN_TCK;
654  for (j = 0; j < delay_tms; j++)
655  ;
656  }
657 }
658 
666 uint16_t jtag_get_signals(void)
667 {
668  uint8_t input_signal_state, output_signal_state;
669 
670  input_signal_state = 0;
671  output_signal_state = 0;
672 
673  /* Get states of input pins */
674  if (GET_TDO())
675  input_signal_state |= SIGNAL_TDO;
676  if (GET_BRKOUT())
677  input_signal_state |= SIGNAL_BRKOUT;
678  if (GET_TRAP())
679  input_signal_state |= SIGNAL_TRAP;
680  if (GET_RTCK()) {
681  /* Using RTCK this way would be extremely slow,
682  * implemented only for the sake of completeness */
683  input_signal_state |= SIGNAL_RTCK;
684  }
685 
686  /* Get states of output pins */
687  output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT;
688 
689  return ((uint16_t)input_signal_state << 8) | ((uint16_t)output_signal_state);
690 }
691 
698 void jtag_set_signals(uint8_t low, uint8_t high)
699 {
700  OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
701  OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
702 }
703 
713 void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
714  uint8_t scan_io, uint8_t tck, uint8_t tms)
715 {
716  delay_scan_in = scan_in;
717  delay_scan_out = scan_out;
718  delay_scan_io = scan_io;
719  delay_tck = tck;
720  delay_tms = tms;
721 }
Definition: osbdm.c:28
static struct ublast_lowlevel low
#define GET_TRAP()
Definition: io.h:96
#define SIGNAL_BRKOUT
Definition: msgtypes.h:170
#define GET_TDO()
Definition: io.h:94
Definition of the commands supported by the OpenULINK firmware.
#define PIN_TDI
Definition: io.h:61
#define PIN_TMS
Definition: io.h:62
#define SIGNAL_RTCK
Definition: msgtypes.h:172
#define SIGNAL_TDO
Definition: msgtypes.h:169
#define GET_BRKOUT()
Definition: io.h:95
#define MASK_PORTB_DIRECTION_OUT
Definition: io.h:71
#define GET_RTCK()
Definition: io.h:97
#define SIGNAL_TRAP
Definition: msgtypes.h:171
static int count
Definition: helper/log.c:62
#define PIN_TCK
Definition: io.h:63