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