ULINK driver: Remove typedefs in OpenULINK firmware: Use typedefs from stdint.h ...
[openocd.git] / src / jtag / drivers / OpenULINK / src / protocol.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 "protocol.h"
22 #include "jtag.h"
23 #include "delay.h"
24 #include "usb.h"
25 #include "io.h"
26 #include "msgtypes.h"
27
28 #include "reg_ezusb.h"
29
30 /**
31 * @file Implementation of the OpenULINK communication protocol.
32 *
33 * The OpenULINK protocol uses one OUT and one IN endpoint. These two endpoints
34 * are configured to use the maximum packet size for full-speed transfers,
35 * 64 bytes. Commands always start with a command ID (see msgtypes.h for
36 * command ID definitions) and contain zero or more payload data bytes in both
37 * transfer directions (IN and OUT). The payload
38 *
39 * Almost all commands contain a fixed number of payload data bytes. The number
40 * of payload data bytes for the IN and OUT direction does not need to be the
41 * same.
42 *
43 * Multiple commands may be sent in one EP2 Bulk-OUT packet. Because the
44 * OpenULINK firmware does not perform bounds checking for EP2 Bulk-IN packets,
45 * the host MUST ensure that the commands sent in the OUT packet require a
46 * maximum of 64 bytes of IN data.
47 */
48
49 /** Index in EP2 Bulk-OUT data buffer that contains the current command ID */
50 volatile uint8_t cmd_id_index;
51
52 /** Number of data bytes already in EP2 Bulk-IN buffer */
53 volatile uint8_t payload_index_in;
54
55 /**
56 * Execute a SET_LEDS command.
57 */
58 void execute_set_led_command(void)
59 {
60 uint8_t led_state = OUT2BUF[cmd_id_index + 1];
61
62 if (led_state & RUN_LED_ON) {
63 SET_RUN_LED();
64 }
65
66 if (led_state & COM_LED_ON) {
67 SET_COM_LED();
68 }
69
70 if (led_state & RUN_LED_OFF) {
71 CLEAR_RUN_LED();
72 }
73
74 if (led_state & COM_LED_OFF) {
75 CLEAR_COM_LED();
76 }
77 }
78
79 /**
80 * Executes one command and updates global command indexes.
81 *
82 * @param index the index of the Bulk EP2-OUT data buffer at which the
83 * command ID is stored.
84 * @return true if this command was the last command.
85 * @return false if there are more commands within the current contents of the
86 * Bulk EP2-OUT data buffer.
87 */
88 bool execute_command(void)
89 {
90 uint8_t usb_out_bytecount, usb_in_bytecount;
91 uint16_t signal_state;
92 uint16_t count;
93
94 /* Most commands do not transfer IN data. To save code space, we write 0 to
95 * usb_in_bytecount here, then modify it in the switch statement below where
96 * neccessary */
97 usb_in_bytecount = 0;
98
99 switch (OUT2BUF[cmd_id_index] /* Command ID */) {
100 case CMD_SCAN_IN:
101 usb_out_bytecount = 5;
102 usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
103 jtag_scan_in(cmd_id_index + 1, payload_index_in);
104 break;
105 case CMD_SCAN_OUT:
106 usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5;
107 jtag_scan_out(cmd_id_index + 1);
108 break;
109 case CMD_SCAN_IO:
110 usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
111 usb_out_bytecount = usb_in_bytecount + 5;
112 jtag_scan_io(cmd_id_index + 1, payload_index_in);
113 break;
114 case CMD_CLOCK_TMS:
115 usb_out_bytecount = 2;
116 jtag_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
117 break;
118 case CMD_CLOCK_TCK:
119 usb_out_bytecount = 2;
120 count = (uint16_t)OUT2BUF[cmd_id_index + 1];
121 count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
122 jtag_clock_tck(count);
123 break;
124 case CMD_SLOW_SCAN_IN:
125 usb_out_bytecount = 5;
126 usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
127 jtag_slow_scan_in(cmd_id_index + 1, payload_index_in);
128 break;
129 case CMD_SLOW_SCAN_OUT:
130 usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5;
131 jtag_slow_scan_out(cmd_id_index + 1);
132 break;
133 case CMD_SLOW_SCAN_IO:
134 usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
135 usb_out_bytecount = usb_in_bytecount + 5;
136 jtag_slow_scan_io(cmd_id_index + 1, payload_index_in);
137 break;
138 case CMD_SLOW_CLOCK_TMS:
139 usb_out_bytecount = 2;
140 jtag_slow_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
141 break;
142 case CMD_SLOW_CLOCK_TCK:
143 usb_out_bytecount = 2;
144 count = (uint16_t)OUT2BUF[cmd_id_index + 1];
145 count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
146 jtag_slow_clock_tck(count);
147 break;
148 case CMD_SLEEP_US:
149 usb_out_bytecount = 2;
150 count = (uint16_t)OUT2BUF[cmd_id_index + 1];
151 count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
152 delay_us(count);
153 break;
154 case CMD_SLEEP_MS:
155 usb_out_bytecount = 2;
156 count = (uint16_t)OUT2BUF[cmd_id_index + 1];
157 count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
158 delay_ms(count);
159 break;
160 case CMD_GET_SIGNALS:
161 usb_out_bytecount = 0;
162 usb_in_bytecount = 2;
163 signal_state = jtag_get_signals();
164 IN2BUF[payload_index_in] = (signal_state >> 8) & 0x00FF;
165 IN2BUF[payload_index_in + 1] = signal_state & 0x00FF;
166 break;
167 case CMD_SET_SIGNALS:
168 usb_out_bytecount = 2;
169 jtag_set_signals(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
170 break;
171 case CMD_CONFIGURE_TCK_FREQ:
172 usb_out_bytecount = 5;
173 jtag_configure_tck_delay(
174 OUT2BUF[cmd_id_index + 1], /* scan_in */
175 OUT2BUF[cmd_id_index + 2], /* scan_out */
176 OUT2BUF[cmd_id_index + 3], /* scan_io */
177 OUT2BUF[cmd_id_index + 4], /* clock_tck */
178 OUT2BUF[cmd_id_index + 5]); /* clock_tms */
179 break;
180 case CMD_SET_LEDS:
181 usb_out_bytecount = 1;
182 execute_set_led_command();
183 break;
184 case CMD_TEST:
185 usb_out_bytecount = 1;
186 /* Do nothing... This command is only used to test if the device is ready
187 * to accept new commands */
188 break;
189 default:
190 /* Should never be reached */
191 usb_out_bytecount = 0;
192 break;
193 }
194
195 /* Update EP2 Bulk-IN data byte count */
196 payload_index_in += usb_in_bytecount;
197
198 /* Determine if this was the last command */
199 if ((cmd_id_index + usb_out_bytecount + 1) >= OUT2BC) {
200 return true;
201 }
202 else {
203 /* Not the last command, update cmd_id_index */
204 cmd_id_index += (usb_out_bytecount + 1);
205 return false;
206 }
207 }
208
209 /**
210 * Forever wait for commands and execute them as they arrive.
211 */
212 void command_loop(void)
213 {
214 bool last_command;
215
216 while (1) {
217 cmd_id_index = 0;
218 payload_index_in = 0;
219
220 /* Wait until host sends EP2 Bulk-OUT packet */
221 while (!EP2_out);
222 EP2_out = 0;
223
224 /* Turn on COM LED to indicate command execution */
225 SET_COM_LED();
226
227 /* Execute the commands */
228 last_command = false;
229 while (last_command == false) {
230 last_command = execute_command();
231 }
232
233 CLEAR_COM_LED();
234
235 /* Send back EP2 Bulk-IN packet if required */
236 if (payload_index_in > 0) {
237 IN2BC = payload_index_in;
238 while (!EP2_in);
239 EP2_in = 0;
240 }
241
242 /* Re-arm EP2-OUT after command execution */
243 OUT2BC = 0;
244 }
245 }

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)