5a6c7ee38cb7764efe32b4b32a01871cfe556f73
[openocd.git] / src / jtag / drivers / versaloon / versaloon.c
1 /***************************************************************************
2 * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "versaloon_include.h"
28 #include "versaloon.h"
29 #include "versaloon_internal.h"
30 #include "usbtoxxx/usbtoxxx.h"
31
32 uint8_t *versaloon_buf;
33 uint8_t *versaloon_cmd_buf;
34 uint16_t versaloon_buf_size;
35
36 struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER];
37 uint16_t versaloon_pending_idx;
38
39 usb_dev_handle *versaloon_usb_device_handle;
40 static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT;
41
42 RESULT versaloon_init(void);
43 RESULT versaloon_fini(void);
44 RESULT versaloon_get_target_voltage(uint16_t *voltage);
45 RESULT versaloon_set_target_voltage(uint16_t voltage);
46 RESULT versaloon_delay_ms(uint16_t ms);
47 RESULT versaloon_delay_us(uint16_t us);
48
49 struct versaloon_interface_t versaloon_interface = {
50 .init = versaloon_init,
51 .fini = versaloon_fini,
52 { /* adaptors */
53 { /* target_voltage */
54 .get = versaloon_get_target_voltage,
55 .set = versaloon_set_target_voltage,
56 },
57 { /* gpio */
58 .init = usbtogpio_init,
59 .fini = usbtogpio_fini,
60 .config = usbtogpio_config,
61 .out = usbtogpio_out,
62 .in = usbtogpio_in,
63 },
64 { /* delay */
65 .delayms = versaloon_delay_ms,
66 .delayus = versaloon_delay_us,
67 },
68 { /* swd */
69 .init = usbtoswd_init,
70 .fini = usbtoswd_fini,
71 .config = usbtoswd_config,
72 .seqout = usbtoswd_seqout,
73 .seqin = usbtoswd_seqin,
74 .transact = usbtoswd_transact,
75 },
76 { /* jtag_raw */
77 .init = usbtojtagraw_init,
78 .fini = usbtojtagraw_fini,
79 .config = usbtojtagraw_config,
80 .execute = usbtojtagraw_execute,
81 },
82 .peripheral_commit = usbtoxxx_execute_command,
83 },
84 { /* usb_setting */
85 .vid = VERSALOON_VID,
86 .pid = VERSALOON_PID,
87 .ep_out = VERSALOON_OUTP,
88 .ep_in = VERSALOON_INP,
89 .interface = VERSALOON_IFACE,
90 .serialstring = NULL,
91 .buf_size = 256,
92 }
93 };
94
95 /* programmer_cmd */
96 static uint32_t versaloon_pending_id;
97 static versaloon_callback_t versaloon_callback;
98 static void *versaloon_extra_data;
99 static struct versaloon_want_pos_t *versaloon_want_pos;
100
101 void versaloon_set_pending_id(uint32_t id)
102 {
103 versaloon_pending_id = id;
104 }
105 void versaloon_set_callback(versaloon_callback_t callback)
106 {
107 versaloon_callback = callback;
108 }
109 void versaloon_set_extra_data(void *p)
110 {
111 versaloon_extra_data = p;
112 }
113
114 void versaloon_free_want_pos(void)
115 {
116 uint16_t i;
117 struct versaloon_want_pos_t *tmp, *free_tmp;
118
119 tmp = versaloon_want_pos;
120 while (tmp != NULL) {
121 free_tmp = tmp;
122 tmp = tmp->next;
123 free(free_tmp);
124 }
125 versaloon_want_pos = NULL;
126
127 for (i = 0; i < dimof(versaloon_pending); i++) {
128 tmp = versaloon_pending[i].pos;
129 while (tmp != NULL) {
130 free_tmp = tmp;
131 tmp = tmp->next;
132 free(free_tmp);
133 }
134 versaloon_pending[i].pos = NULL;
135 }
136 }
137
138 RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff)
139 {
140 struct versaloon_want_pos_t *new_pos = NULL;
141
142 new_pos = (struct versaloon_want_pos_t *)malloc(sizeof(*new_pos));
143 if (NULL == new_pos) {
144 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
145 return ERRCODE_NOT_ENOUGH_MEMORY;
146 }
147 new_pos->offset = offset;
148 new_pos->size = size;
149 new_pos->buff = buff;
150 new_pos->next = NULL;
151
152 if (NULL == versaloon_want_pos)
153 versaloon_want_pos = new_pos;
154 else {
155 struct versaloon_want_pos_t *tmp = versaloon_want_pos;
156
157 while (tmp->next != NULL)
158 tmp = tmp->next;
159 tmp->next = new_pos;
160 }
161
162 return ERROR_OK;
163 }
164
165 RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie,
166 uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect)
167 {
168 #if PARAM_CHECK
169 if (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER) {
170 LOG_BUG(ERRMSG_INVALID_INDEX, versaloon_pending_idx,
171 "versaloon pending data");
172 return ERROR_FAIL;
173 }
174 #endif
175
176 versaloon_pending[versaloon_pending_idx].type = type;
177 versaloon_pending[versaloon_pending_idx].cmd = cmd;
178 versaloon_pending[versaloon_pending_idx].actual_data_size = actual_szie;
179 versaloon_pending[versaloon_pending_idx].want_data_pos = want_pos;
180 versaloon_pending[versaloon_pending_idx].want_data_size = want_size;
181 versaloon_pending[versaloon_pending_idx].data_buffer = buffer;
182 versaloon_pending[versaloon_pending_idx].collect = collect;
183 versaloon_pending[versaloon_pending_idx].id = versaloon_pending_id;
184 versaloon_pending_id = 0;
185 versaloon_pending[versaloon_pending_idx].extra_data = versaloon_extra_data;
186 versaloon_extra_data = NULL;
187 versaloon_pending[versaloon_pending_idx].callback = versaloon_callback;
188 versaloon_callback = NULL;
189 versaloon_pending[versaloon_pending_idx].pos = versaloon_want_pos;
190 versaloon_want_pos = NULL;
191 versaloon_pending_idx++;
192
193 return ERROR_OK;
194 }
195
196 RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen)
197 {
198 int ret;
199
200 #if PARAM_CHECK
201 if (NULL == versaloon_buf) {
202 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
203 return ERRCODE_INVALID_BUFFER;
204 }
205 if ((0 == out_len) || (out_len > versaloon_interface.usb_setting.buf_size)) {
206 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
207 return ERRCODE_INVALID_PARAMETER;
208 }
209 #endif
210
211 ret = usb_bulk_write(versaloon_usb_device_handle,
212 versaloon_interface.usb_setting.ep_out, (char *)versaloon_buf,
213 out_len, versaloon_usb_to);
214 if (ret != out_len) {
215 LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING, "send usb data",
216 usb_strerror());
217 return ERRCODE_FAILURE_OPERATION;
218 }
219
220 if (inlen != NULL) {
221 ret = usb_bulk_read(versaloon_usb_device_handle,
222 versaloon_interface.usb_setting.ep_in, (char *)versaloon_buf,
223 versaloon_interface.usb_setting.buf_size, versaloon_usb_to);
224 if (ret > 0) {
225 *inlen = (uint16_t)ret;
226 return ERROR_OK;
227 } else {
228 LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING, "receive usb data",
229 usb_strerror());
230 return ERROR_FAIL;
231 }
232 } else
233 return ERROR_OK;
234 }
235
236 #define VERSALOON_RETRY_CNT 10
237 RESULT versaloon_init(void)
238 {
239 uint16_t ret = 0;
240 uint8_t retry;
241 uint32_t timeout_tmp;
242
243 /* malloc temporary buffer */
244 versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size);
245 if (NULL == versaloon_buf) {
246 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
247 return ERRCODE_NOT_ENOUGH_MEMORY;
248 }
249
250 /* connect to versaloon */
251 timeout_tmp = versaloon_usb_to;
252 /* not output error message when connectting */
253 /* 100ms delay when connect */
254 versaloon_usb_to = 100;
255 for (retry = 0; retry < VERSALOON_RETRY_CNT; retry++) {
256 versaloon_buf[0] = VERSALOON_GET_INFO;
257 if ((ERROR_OK == versaloon_send_command(1, &ret)) && (ret >= 3))
258 break;
259 }
260 versaloon_usb_to = timeout_tmp;
261 if (VERSALOON_RETRY_CNT == retry) {
262 versaloon_fini();
263 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
264 return ERRCODE_FAILURE_OPERATION;
265 }
266
267 versaloon_buf[ret] = 0;
268 versaloon_buf_size = versaloon_buf[0] + (versaloon_buf[1] << 8);
269 versaloon_interface.usb_setting.buf_size = versaloon_buf_size;
270 LOG_INFO("%s", versaloon_buf + 2);
271
272 /* free temporary buffer */
273 free(versaloon_buf);
274 versaloon_buf = NULL;
275
276 versaloon_buf = malloc(versaloon_interface.usb_setting.buf_size);
277 if (NULL == versaloon_buf) {
278 versaloon_fini();
279 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
280 return ERRCODE_NOT_ENOUGH_MEMORY;
281 }
282 versaloon_cmd_buf = malloc(versaloon_interface.usb_setting.buf_size - 3);
283 if (NULL == versaloon_cmd_buf) {
284 versaloon_fini();
285 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
286 return ERRCODE_NOT_ENOUGH_MEMORY;
287 }
288 if (ERROR_OK != usbtoxxx_init()) {
289 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "initialize usbtoxxx");
290 return ERROR_FAIL;
291 }
292 return versaloon_get_target_voltage(&ret);
293 }
294
295 RESULT versaloon_fini(void)
296 {
297 if (versaloon_usb_device_handle != NULL) {
298 usbtoxxx_fini();
299 versaloon_free_want_pos();
300
301 versaloon_usb_device_handle = NULL;
302
303 if (versaloon_buf != NULL) {
304 free(versaloon_buf);
305 versaloon_buf = NULL;
306 }
307 if (versaloon_cmd_buf != NULL) {
308 free(versaloon_cmd_buf);
309 versaloon_cmd_buf = NULL;
310 }
311 }
312
313 return ERROR_OK;
314 }
315
316 RESULT versaloon_set_target_voltage(uint16_t voltage)
317 {
318 usbtopwr_init(0);
319 usbtopwr_config(0);
320 usbtopwr_output(0, voltage);
321 usbtopwr_fini(0);
322
323 return usbtoxxx_execute_command();
324 }
325
326 RESULT versaloon_get_target_voltage(uint16_t *voltage)
327 {
328 uint16_t inlen;
329
330 #if PARAM_CHECK
331 if (NULL == versaloon_buf) {
332 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
333 return ERRCODE_INVALID_BUFFER;
334 }
335 if (NULL == voltage) {
336 LOG_BUG(ERRMSG_INVALID_PARAMETER, __func__);
337 return ERRCODE_INVALID_PARAMETER;
338 }
339 #endif
340
341 versaloon_buf[0] = VERSALOON_GET_TVCC;
342
343 if ((ERROR_OK != versaloon_send_command(1, &inlen)) || (inlen != 2)) {
344 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
345 return ERRCODE_FAILURE_OPERATION;
346 } else {
347 *voltage = versaloon_buf[0] + (versaloon_buf[1] << 8);
348 return ERROR_OK;
349 }
350 }
351
352 RESULT versaloon_delay_ms(uint16_t ms)
353 {
354 return usbtodelay_delay(ms | 0x8000);
355 }
356
357 RESULT versaloon_delay_us(uint16_t us)
358 {
359 return usbtodelay_delay(us & 0x7FFF);
360 }

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)