aaf55b0a531b6010d8133efadfedc5855a90b62a
[openocd.git] / src / jtag / drivers / stlink_usb.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Mathias Kuester *
3 * Mathias Kuester <kesmtp@freenet.de> *
4 * *
5 * This code is based on https://github.com/texane/stlink *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 /* project specific includes */
28 #include <helper/binarybuffer.h>
29 #include <jtag/interface.h>
30 #include <jtag/stlink/stlink_layout.h>
31 #include <jtag/stlink/stlink_interface.h>
32 #include <target/target.h>
33
34 #include "libusb_common.h"
35
36 #define ENDPOINT_IN 0x80
37 #define ENDPOINT_OUT 0x00
38
39 #define STLINK_RX_EP (1|ENDPOINT_IN)
40 #define STLINK_TX_EP (2|ENDPOINT_OUT)
41 #define STLINK_CMD_SIZE (16)
42 #define STLINK_TX_SIZE (4*128)
43 #define STLINK_RX_SIZE (4*128)
44
45 /** */
46 struct stlink_usb_handle_s {
47 /** */
48 struct jtag_libusb_device_handle *fd;
49 /** */
50 struct libusb_transfer *trans;
51 /** */
52 uint8_t txbuf[STLINK_TX_SIZE];
53 /** */
54 uint8_t rxbuf[STLINK_RX_SIZE];
55 };
56
57 #define STLINK_OK 0x80
58 #define STLINK_FALSE 0x81
59 #define STLINK_CORE_RUNNING 0x80
60 #define STLINK_CORE_HALTED 0x81
61 #define STLINK_CORE_STAT_UNKNOWN -1
62
63 #define STLINK_GET_VERSION 0xf1
64 #define STLINK_GET_CURRENT_MODE 0xf5
65
66 #define STLINK_DEBUG_COMMAND 0xF2
67 #define STLINK_DFU_COMMAND 0xF3
68 #define STLINK_DFU_EXIT 0x07
69
70 #define STLINK_DEV_DFU_MODE 0x00
71 #define STLINK_DEV_MASS_MODE 0x01
72 #define STLINK_DEV_DEBUG_MODE 0x02
73 #define STLINK_DEV_UNKNOWN_MODE -1
74
75 #define STLINK_DEBUG_ENTER 0x20
76 #define STLINK_DEBUG_EXIT 0x21
77 #define STLINK_DEBUG_READCOREID 0x22
78
79 #define STLINK_DEBUG_GETSTATUS 0x01
80 #define STLINK_DEBUG_FORCEDEBUG 0x02
81 #define STLINK_DEBUG_RESETSYS 0x03
82 #define STLINK_DEBUG_READALLREGS 0x04
83 #define STLINK_DEBUG_READREG 0x05
84 #define STLINK_DEBUG_WRITEREG 0x06
85 #define STLINK_DEBUG_READMEM_32BIT 0x07
86 #define STLINK_DEBUG_WRITEMEM_32BIT 0x08
87 #define STLINK_DEBUG_RUNCORE 0x09
88 #define STLINK_DEBUG_STEPCORE 0x0a
89 #define STLINK_DEBUG_SETFP 0x0b
90 #define STLINK_DEBUG_WRITEMEM_8BIT 0x0d
91 #define STLINK_DEBUG_CLEARFP 0x0e
92 #define STLINK_DEBUG_WRITEDEBUGREG 0x0f
93 #define STLINK_DEBUG_ENTER_SWD 0xa3
94 #define STLINK_DEBUG_ENTER_JTAG 0x00
95
96 #define STLINK_SWD_ENTER 0x30
97 #define STLINK_SWD_READCOREID 0x32
98
99 /** */
100 int stlink_usb_recv(void *handle, uint8_t *txbuf, int txsize, uint8_t *rxbuf,
101 int rxsize)
102 {
103 struct stlink_usb_handle_s *h;
104
105 assert(handle != NULL);
106
107 h = (struct stlink_usb_handle_s *)handle;
108
109 if (jtag_libusb_bulk_write(h->fd, STLINK_TX_EP, (char *)txbuf, txsize,
110 1000) != txsize) {
111 return ERROR_FAIL;
112 }
113 if (rxsize && rxbuf) {
114 if (jtag_libusb_bulk_read(h->fd, STLINK_RX_EP, (char *)rxbuf,
115 rxsize, 1000) != rxsize) {
116 return ERROR_FAIL;
117 }
118 }
119 return ERROR_OK;
120 }
121
122 /** */
123 void stlink_usb_init_buffer(void *handle)
124 {
125 struct stlink_usb_handle_s *h;
126
127 assert(handle != NULL);
128
129 h = (struct stlink_usb_handle_s *)handle;
130
131 memset(h->txbuf, 0, STLINK_CMD_SIZE);
132 }
133
134 /** */
135 int stlink_usb_version(void *handle)
136 {
137 int res;
138 uint16_t v;
139 struct stlink_usb_handle_s *h;
140
141 assert(handle != NULL);
142
143 h = (struct stlink_usb_handle_s *)handle;
144
145 stlink_usb_init_buffer(handle);
146
147 h->txbuf[0] = STLINK_GET_VERSION;
148
149 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 6);
150
151 if (res != ERROR_OK)
152 return res;
153
154 v = (h->rxbuf[0] << 8) | h->rxbuf[1];
155
156 LOG_DEBUG("STLINK v%d", (v >> 12) & 0x0f);
157 LOG_DEBUG("JTAG v%d", (v >> 6) & 0x3f);
158 LOG_DEBUG("SWIM v%d", v & 0x3f);
159 LOG_DEBUG("VID %04X", buf_get_u32(h->rxbuf, 16, 16));
160 LOG_DEBUG("PID %04X", buf_get_u32(h->rxbuf, 32, 16));
161
162 return ERROR_OK;
163 }
164
165 /** */
166 int stlink_usb_current_mode(void *handle, uint8_t *mode)
167 {
168 int res;
169 struct stlink_usb_handle_s *h;
170
171 assert(handle != NULL);
172
173 h = (struct stlink_usb_handle_s *)handle;
174
175 stlink_usb_init_buffer(handle);
176
177 h->txbuf[0] = STLINK_GET_CURRENT_MODE;
178
179 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2);
180
181 if (res != ERROR_OK)
182 return res;
183
184 *mode = h->rxbuf[0];
185
186 return ERROR_OK;
187 }
188
189 /** */
190 int stlink_usb_dfu_mode_leave(void *handle)
191 {
192 int res;
193 struct stlink_usb_handle_s *h;
194
195 assert(handle != NULL);
196
197 h = (struct stlink_usb_handle_s *)handle;
198
199 stlink_usb_init_buffer(handle);
200
201 h->txbuf[0] = STLINK_DFU_COMMAND;
202 h->txbuf[1] = STLINK_DFU_EXIT;
203
204 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0);
205
206 if (res != ERROR_OK)
207 return res;
208
209 return ERROR_OK;
210 }
211
212 /** */
213 int stlink_usb_swd_mode_enter(void *handle)
214 {
215 int res;
216 struct stlink_usb_handle_s *h;
217
218 assert(handle != NULL);
219
220 h = (struct stlink_usb_handle_s *)handle;
221
222 stlink_usb_init_buffer(handle);
223
224 h->txbuf[0] = STLINK_DEBUG_COMMAND;
225 h->txbuf[1] = STLINK_DEBUG_ENTER;
226 h->txbuf[2] = STLINK_DEBUG_ENTER_SWD;
227
228 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0);
229 if (res != ERROR_OK)
230 return res;
231
232 return ERROR_OK;
233 }
234
235 /** */
236 int stlink_usb_debug_mode_leave(void *handle)
237 {
238 int res;
239 struct stlink_usb_handle_s *h;
240
241 assert(handle != NULL);
242
243 h = (struct stlink_usb_handle_s *)handle;
244
245 stlink_usb_init_buffer(handle);
246
247 h->txbuf[0] = STLINK_DEBUG_COMMAND;
248 h->txbuf[1] = STLINK_DEBUG_EXIT;
249
250 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0);
251 if (res != ERROR_OK)
252 return res;
253
254 return ERROR_OK;
255 }
256
257 /** */
258 int stlink_usb_init_mode(void *handle)
259 {
260 int res;
261 uint8_t mode;
262
263 assert(handle != NULL);
264
265 res = stlink_usb_current_mode(handle, &mode);
266
267 if (res != ERROR_OK)
268 return res;
269
270 LOG_DEBUG("MODE: %02X", mode);
271
272 if (mode == STLINK_DEV_DFU_MODE) {
273 res = stlink_usb_dfu_mode_leave(handle);
274
275 if (res != ERROR_OK)
276 return res;
277 }
278
279 res = stlink_usb_current_mode(handle, &mode);
280
281 if (res != ERROR_OK)
282 return res;
283
284 LOG_DEBUG("MODE: %02X", mode);
285
286 if (mode != STLINK_DEV_DEBUG_MODE) {
287 res = stlink_usb_swd_mode_enter(handle);
288
289 if (res != ERROR_OK)
290 return res;
291 }
292
293 res = stlink_usb_current_mode(handle, &mode);
294
295 if (res != ERROR_OK)
296 return res;
297
298 LOG_DEBUG("MODE: %02X", mode);
299
300 return ERROR_OK;
301 }
302
303 /** */
304 int stlink_usb_idcode(void *handle, uint32_t *idcode)
305 {
306 int res;
307 struct stlink_usb_handle_s *h;
308
309 assert(handle != NULL);
310
311 h = (struct stlink_usb_handle_s *)handle;
312
313 stlink_usb_init_buffer(handle);
314
315 h->txbuf[0] = STLINK_DEBUG_COMMAND;
316 h->txbuf[1] = STLINK_DEBUG_READCOREID;
317
318 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 4);
319
320 if (res != ERROR_OK)
321 return res;
322
323 *idcode = le_to_h_u32(h->rxbuf);
324
325 LOG_DEBUG("IDCODE: %08X", *idcode);
326
327 return ERROR_OK;
328 }
329
330 /** */
331 enum target_state stlink_usb_state(void *handle)
332 {
333 int res;
334 struct stlink_usb_handle_s *h;
335
336 assert(handle != NULL);
337
338 h = (struct stlink_usb_handle_s *)handle;
339
340 stlink_usb_init_buffer(handle);
341
342 h->txbuf[0] = STLINK_DEBUG_COMMAND;
343 h->txbuf[1] = STLINK_DEBUG_GETSTATUS;
344
345 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2);
346
347 if (res != ERROR_OK)
348 return TARGET_UNKNOWN;
349
350 if (h->rxbuf[0] == STLINK_CORE_RUNNING)
351 return TARGET_RUNNING;
352 if (h->rxbuf[0] == STLINK_CORE_HALTED)
353 return TARGET_HALTED;
354
355 return TARGET_UNKNOWN;
356 }
357
358 /** */
359 int stlink_usb_reset(void *handle)
360 {
361 int res;
362 struct stlink_usb_handle_s *h;
363
364 assert(handle != NULL);
365
366 h = (struct stlink_usb_handle_s *)handle;
367
368 stlink_usb_init_buffer(handle);
369
370 h->txbuf[0] = STLINK_DEBUG_COMMAND;
371 h->txbuf[1] = STLINK_DEBUG_RESETSYS;
372
373 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2);
374
375 if (res != ERROR_OK)
376 return res;
377
378 LOG_DEBUG("RESET: %08X", h->rxbuf[0]);
379
380 return ERROR_OK;
381 }
382
383 /** */
384 int stlink_usb_run(void *handle)
385 {
386 int res;
387 struct stlink_usb_handle_s *h;
388
389 assert(handle != NULL);
390
391 h = (struct stlink_usb_handle_s *)handle;
392
393 stlink_usb_init_buffer(handle);
394
395 h->txbuf[0] = STLINK_DEBUG_COMMAND;
396 h->txbuf[1] = STLINK_DEBUG_RUNCORE;
397
398 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2);
399
400 if (res != ERROR_OK)
401 return res;
402
403 return ERROR_OK;
404 }
405
406 /** */
407 int stlink_usb_halt(void *handle)
408 {
409 int res;
410 struct stlink_usb_handle_s *h;
411
412 assert(handle != NULL);
413
414 h = (struct stlink_usb_handle_s *)handle;
415
416 stlink_usb_init_buffer(handle);
417
418 h->txbuf[0] = STLINK_DEBUG_COMMAND;
419 h->txbuf[1] = STLINK_DEBUG_FORCEDEBUG;
420
421 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2);
422
423 if (res != ERROR_OK)
424 return res;
425
426 return ERROR_OK;
427 }
428
429 /** */
430 int stlink_usb_step(void *handle)
431 {
432 int res;
433 struct stlink_usb_handle_s *h;
434
435 assert(handle != NULL);
436
437 h = (struct stlink_usb_handle_s *)handle;
438
439 stlink_usb_init_buffer(handle);
440
441 h->txbuf[0] = STLINK_DEBUG_COMMAND;
442 h->txbuf[1] = STLINK_DEBUG_STEPCORE;
443
444 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2);
445
446 if (res != ERROR_OK)
447 return res;
448
449 return ERROR_OK;
450 }
451
452 /** */
453 int stlink_usb_read_regs(void *handle)
454 {
455 int res;
456 struct stlink_usb_handle_s *h;
457
458 assert(handle != NULL);
459
460 h = (struct stlink_usb_handle_s *)handle;
461
462 stlink_usb_init_buffer(handle);
463
464 h->txbuf[0] = STLINK_DEBUG_COMMAND;
465 h->txbuf[1] = STLINK_DEBUG_READALLREGS;
466
467 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 84);
468
469 if (res != ERROR_OK)
470 return res;
471
472 return ERROR_OK;
473 }
474
475 /** */
476 int stlink_usb_read_reg(void *handle, int num, uint32_t *val)
477 {
478 int res;
479 struct stlink_usb_handle_s *h;
480
481 assert(handle != NULL);
482
483 h = (struct stlink_usb_handle_s *)handle;
484
485 stlink_usb_init_buffer(handle);
486
487 h->txbuf[0] = STLINK_DEBUG_COMMAND;
488 h->txbuf[1] = STLINK_DEBUG_READREG;
489 h->txbuf[2] = num;
490
491 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 4);
492
493 if (res != ERROR_OK)
494 return res;
495
496 *val = le_to_h_u32(h->rxbuf);
497
498 return ERROR_OK;
499 }
500
501 /** */
502 int stlink_usb_write_reg(void *handle, int num, uint32_t val)
503 {
504 int res;
505 struct stlink_usb_handle_s *h;
506
507 assert(handle != NULL);
508
509 h = (struct stlink_usb_handle_s *)handle;
510
511 stlink_usb_init_buffer(handle);
512
513 h->txbuf[0] = STLINK_DEBUG_COMMAND;
514 h->txbuf[1] = STLINK_DEBUG_WRITEREG;
515 h->txbuf[2] = num;
516 h_u32_to_le(h->txbuf + 3, val);
517
518 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, 2);
519
520 if (res != ERROR_OK)
521 return res;
522
523 return ERROR_OK;
524 }
525
526 /** */
527 int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
528 uint32_t *buffer)
529 {
530 int res;
531 struct stlink_usb_handle_s *h;
532
533 assert(handle != NULL);
534
535 h = (struct stlink_usb_handle_s *)handle;
536
537 stlink_usb_init_buffer(handle);
538
539 len *= 4;
540
541 h->txbuf[0] = STLINK_DEBUG_COMMAND;
542 h->txbuf[1] = STLINK_DEBUG_READMEM_32BIT;
543 h_u32_to_le(h->txbuf + 2, addr);
544 h_u16_to_le(h->txbuf + 2 + 4, len);
545
546 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, h->rxbuf, len);
547
548 if (res != ERROR_OK)
549 return res;
550
551 memcpy(buffer, h->rxbuf, len);
552
553 return ERROR_OK;
554 }
555
556 /** */
557 int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
558 uint32_t *buffer)
559 {
560 int res;
561 struct stlink_usb_handle_s *h;
562
563 assert(handle != NULL);
564
565 h = (struct stlink_usb_handle_s *)handle;
566
567 stlink_usb_init_buffer(handle);
568
569 len *= 4;
570
571 h->txbuf[0] = STLINK_DEBUG_COMMAND;
572 h->txbuf[1] = STLINK_DEBUG_WRITEMEM_32BIT;
573 h_u32_to_le(h->txbuf + 2, addr);
574 h_u16_to_le(h->txbuf + 2 + 4, len);
575
576 res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0);
577
578 if (res != ERROR_OK)
579 return res;
580
581 res = stlink_usb_recv(handle, (uint8_t *) buffer, len, 0, 0);
582
583 if (res != ERROR_OK)
584 return res;
585
586 memcpy(buffer, h->rxbuf, len);
587
588 return ERROR_OK;
589 }
590
591 /** */
592 int stlink_usb_open(struct stlink_interface_param_s *param, void **fd)
593 {
594 struct stlink_usb_handle_s *h;
595
596 LOG_DEBUG("stlink_usb_open");
597
598 h = malloc(sizeof(struct stlink_usb_handle_s));
599
600 if (h == 0) {
601 LOG_DEBUG("stlink_open_usb: malloc failed");
602 return ERROR_FAIL;
603 }
604
605 const uint16_t vids[] = { param->vid, 0 };
606 const uint16_t pids[] = { param->pid, 0 };
607
608 LOG_DEBUG("stlink_open_usb: vid: %04x pid: %04x", param->vid,
609 param->pid);
610
611 if (jtag_libusb_open(vids, pids, &h->fd) != ERROR_OK) {
612 LOG_DEBUG("stlink_open_usb: open failed");
613 return ERROR_FAIL;
614 }
615
616 jtag_libusb_set_configuration(h->fd, 0);
617
618 if (jtag_libusb_claim_interface(h->fd, 0) != ERROR_OK) {
619 LOG_DEBUG("stlink_open_usb: claim failed");
620 return ERROR_FAIL;
621 }
622
623 stlink_usb_init_mode(h);
624
625 stlink_usb_version(h);
626
627 *fd = h;
628
629 return ERROR_OK;
630 }
631
632 /** */
633 struct stlink_layout_api_s stlink_layout_api = {
634 /** */
635 .open = stlink_usb_open,
636 /** */
637 .idcode = stlink_usb_idcode,
638 /** */
639 .state = stlink_usb_state,
640 /** */
641 .reset = stlink_usb_reset,
642 /** */
643 .run = stlink_usb_run,
644 /** */
645 .halt = stlink_usb_halt,
646 /** */
647 .step = stlink_usb_step,
648 /** */
649 .read_regs = stlink_usb_read_regs,
650 /** */
651 .read_reg = stlink_usb_read_reg,
652 /** */
653 .write_reg = stlink_usb_write_reg,
654 /** */
655 .read_mem32 = stlink_usb_read_mem32,
656 /** */
657 .write_mem32 = stlink_usb_write_mem32,
658 };

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)