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

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)