debug feature: jtagtcpip, improve performance
[openocd.git] / src / jtag / zy1000 / jtag_minidriver.h
1 /***************************************************************************
2 * Copyright (C) 2007-2009 by Øyvind Harboe *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 /* used to test manual mode */
21 #define TEST_MANUAL() 0
22 #define VERBOSE(a)
23
24 #if BUILD_ECOSBOARD
25
26 #include <cyg/hal/hal_io.h> // low level i/o
27 #include <cyg/hal/hal_intr.h> // low level i/o
28
29 #if 0
30 int diag_printf(const char *fmt, ...);
31 #define ZY1000_POKE(a, b) HAL_WRITE_UINT32(a, b); diag_printf("poke 0x%08x,0x%08x\n", a, b)
32 #define ZY1000_PEEK(a, b) HAL_READ_UINT32(a, b); diag_printf("peek 0x%08x = 0x%08x\n", a, b)
33 #else
34 #define ZY1000_PEEK(a, b) HAL_READ_UINT32(a, b)
35 #define ZY1000_POKE(a, b) HAL_WRITE_UINT32(a, b)
36 #endif
37
38 #else
39
40 /* redirect this to TCP/IP */
41 #define ZY1000_JTAG_BASE 0
42 extern void zy1000_tcpout(uint32_t address, uint32_t data);
43 extern uint32_t zy1000_tcpin(uint32_t address);
44 #define ZY1000_PEEK(a, b) b=zy1000_tcpin(a)
45 #define ZY1000_POKE(a, b) zy1000_tcpout(a, b)
46
47 #endif
48
49
50
51 #if BUILD_ECOSBOARD
52 // FIFO empty?
53 static __inline__ void waitIdle(void)
54 {
55 uint32_t empty;
56 do
57 {
58 ZY1000_PEEK(ZY1000_JTAG_BASE + 0x10, empty);
59 } while ((empty & 0x100) == 0);
60 }
61 #else
62 extern void waitIdle(void);
63 #endif
64
65 static __inline__ void waitQueue(void)
66 {
67 // waitIdle();
68 }
69
70 static __inline__ void sampleShiftRegister(void)
71 {
72 #if 0
73 uint32_t dummy;
74 waitIdle();
75 ZY1000_PEEK(ZY1000_JTAG_BASE + 0xc, dummy);
76 #endif
77 }
78
79 static __inline__ void setCurrentState(enum tap_state state)
80 {
81 uint32_t a;
82 a = state;
83 int repeat = 0;
84 if (state == TAP_RESET)
85 {
86 // The FPGA nor we know the current state of the CPU TAP
87 // controller. This will move it to TAP for sure.
88 //
89 // 5 should be enough here, 7 is what OpenOCD uses
90 repeat = 7;
91 }
92 waitQueue();
93 sampleShiftRegister();
94 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | a);
95
96 }
97
98 /*
99 * Enter state and cause repeat transitions *out* of that state. So if the endState != state, then
100 * the transition from state to endState counts as a transition out of state.
101 */
102 static __inline__ void shiftValueInner(const enum tap_state state, const enum tap_state endState, int repeat, uint32_t value)
103 {
104 uint32_t a,b;
105 a = state;
106 b = endState;
107 waitQueue();
108 sampleShiftRegister();
109 ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value);
110 #if 1
111 #if TEST_MANUAL()
112 if ((state == TAP_DRSHIFT) && (endState != TAP_DRSHIFT))
113 {
114 int i;
115 setCurrentState(state);
116 for (i = 0; i < repeat; i++)
117 {
118 int tms;
119 tms = 0;
120 if ((i == repeat-1) && (state != endState))
121 {
122 tms = 1;
123 }
124 /* shift out value */
125 waitIdle();
126 ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, (((value >> i)&1) << 1) | tms);
127 }
128 waitIdle();
129 ZY1000_POKE(ZY1000_JTAG_BASE + 0x28, 0);
130 waitIdle();
131 //ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRSHIFT); // set this state and things break => expected
132 ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_DRPAUSE); // set this and things will work => expected. Not setting this is not sufficient to make things break.
133 setCurrentState(endState);
134 } else
135 {
136 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
137 }
138 #else
139 /* fast version */
140 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
141 #endif
142 #else
143 /* maximum debug version */
144 if ((repeat > 0) && ((state == TAP_DRSHIFT)||(state == TAP_SI)))
145 {
146 int i;
147 /* sample shift register for every bit. */
148 for (i = 0; i < repeat-1; i++)
149 {
150 sampleShiftRegister();
151 ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> i);
152 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | a);
153 }
154 sampleShiftRegister();
155 ZY1000_POKE(ZY1000_JTAG_BASE + 0xc, value >> (repeat-1));
156 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (1 << 8) | (a << 4) | b);
157 } else
158 {
159 sampleShiftRegister();
160 ZY1000_POKE(ZY1000_JTAG_BASE + 0x8, (repeat << 8) | (a << 4) | b);
161 }
162 sampleShiftRegister();
163 #endif
164 }
165
166
167
168 static __inline__ void interface_jtag_add_dr_out_core(struct jtag_tap *target_tap,
169 int num_fields,
170 const int *num_bits,
171 const uint32_t *value,
172 enum tap_state end_state)
173 {
174 enum tap_state pause_state = TAP_DRSHIFT;
175
176 struct jtag_tap *tap, *nextTap;
177 for (tap = jtag_tap_next_enabled(NULL); tap!= NULL; tap = nextTap)
178 {
179 nextTap = jtag_tap_next_enabled(tap);
180 if (nextTap == NULL)
181 {
182 pause_state = end_state;
183 }
184 if (tap == target_tap)
185 {
186 int j;
187 for (j = 0; j < (num_fields-1); j++)
188 {
189 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[j], value[j]);
190 }
191 shiftValueInner(TAP_DRSHIFT, pause_state, num_bits[j], value[j]);
192 } else
193 {
194 /* program the scan field to 1 bit length, and ignore it's value */
195 shiftValueInner(TAP_DRSHIFT, pause_state, 1, 0);
196 }
197 }
198 }
199
200 static __inline__ void interface_jtag_add_dr_out(struct jtag_tap *target_tap,
201 int num_fields,
202 const int *num_bits,
203 const uint32_t *value,
204 enum tap_state end_state)
205 {
206
207 int singletap = (jtag_tap_next_enabled(jtag_tap_next_enabled(NULL)) == NULL);
208 if ((singletap) && (num_fields == 3))
209 {
210 /* used by embeddedice_write_reg_inner() */
211 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[0], value[0]);
212 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[1], value[1]);
213 shiftValueInner(TAP_DRSHIFT, end_state, num_bits[2], value[2]);
214 } else if ((singletap) && (num_fields == 2))
215 {
216 /* used by arm7 code */
217 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, num_bits[0], value[0]);
218 shiftValueInner(TAP_DRSHIFT, end_state, num_bits[1], value[1]);
219 } else
220 {
221 interface_jtag_add_dr_out_core(target_tap, num_fields, num_bits, value, end_state);
222 }
223 }
224
225 #define interface_jtag_add_callback(callback, in) callback(in)
226
227 #define interface_jtag_add_callback4(callback, in, data1, data2, data3) jtag_set_error(callback(in, data1, data2, data3))

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)