1 /***************************************************************************
3 * Copyright (C) 2012 by Spencer Oliver *
4 * spen@spen-soft.co.uk *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
20 ***************************************************************************/
26 /* project specific includes */
27 #include <helper/binarybuffer.h>
28 #include <jtag/interface.h>
29 #include <jtag/hla/hla_layout.h>
30 #include <jtag/hla/hla_transport.h>
31 #include <jtag/hla/hla_interface.h>
32 #include <target/target.h>
34 #include <target/cortex_m.h>
36 #include <libusb-1.0/libusb.h>
38 #define ICDI_WRITE_ENDPOINT 0x02
39 #define ICDI_READ_ENDPOINT 0x83
41 #define ICDI_WRITE_TIMEOUT 1000
42 #define ICDI_READ_TIMEOUT 1000
43 #define ICDI_PACKET_SIZE 2048
45 #define PACKET_START "$"
46 #define PACKET_END "#"
48 struct icdi_usb_handle_s
{
49 libusb_context
*usb_ctx
;
50 libusb_device_handle
*usb_dev
;
58 static int icdi_usb_read_mem32(void *handle
, uint32_t addr
, uint16_t len
, uint8_t *buffer
);
59 static int icdi_usb_write_mem32(void *handle
, uint32_t addr
, uint16_t len
, const uint8_t *buffer
);
61 static int remote_escape_output(const char *buffer
, int len
, char *out_buf
, int *out_len
, int out_maxlen
)
63 int input_index
, output_index
;
67 for (input_index
= 0; input_index
< len
; input_index
++) {
69 char b
= buffer
[input_index
];
71 if (b
== '$' || b
== '#' || b
== '}' || b
== '*') {
72 /* These must be escaped. */
73 if (output_index
+ 2 > out_maxlen
)
75 out_buf
[output_index
++] = '}';
76 out_buf
[output_index
++] = b
^ 0x20;
78 if (output_index
+ 1 > out_maxlen
)
80 out_buf
[output_index
++] = b
;
84 *out_len
= input_index
;
88 static int remote_unescape_input(const char *buffer
, int len
, char *out_buf
, int out_maxlen
)
90 int input_index
, output_index
;
96 for (input_index
= 0; input_index
< len
; input_index
++) {
98 char b
= buffer
[input_index
];
100 if (output_index
+ 1 > out_maxlen
)
101 LOG_ERROR("Received too much data from the target.");
104 out_buf
[output_index
++] = b
^ 0x20;
109 out_buf
[output_index
++] = b
;
113 LOG_ERROR("Unmatched escape character in target response.");
118 static int icdi_send_packet(void *handle
, int len
)
120 unsigned char cksum
= 0;
121 struct icdi_usb_handle_s
*h
;
122 int result
, retry
= 0;
125 assert(handle
!= NULL
);
126 h
= (struct icdi_usb_handle_s
*)handle
;
128 /* check we have a large enough buffer for checksum "#00" */
129 if (len
+ 3 > h
->max_packet
) {
130 LOG_ERROR("packet buffer too small");
134 /* calculate checksum - offset start of packet */
135 for (int i
= 1; i
< len
; i
++)
136 cksum
+= h
->write_buffer
[i
];
138 len
+= sprintf(&h
->write_buffer
[len
], PACKET_END
"%02x", cksum
);
140 #ifdef _DEBUG_USB_COMMS_
142 char ch
= h
->write_buffer
[1];
143 if (ch
== 'x' || ch
== 'X')
144 LOG_DEBUG("writing packet: <binary>");
146 memcpy(buffer
, h
->write_buffer
, len
>= 50 ? 50-1 : len
);
148 LOG_DEBUG("writing packet: %s", buffer
);
154 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_WRITE_ENDPOINT
, (unsigned char *)h
->write_buffer
, len
,
155 &transferred
, ICDI_WRITE_TIMEOUT
);
156 if (result
!= 0 || transferred
!= len
) {
157 LOG_DEBUG("Error TX Data %d", result
);
161 /* check that the client got the message ok, or shall we resend */
162 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_READ_ENDPOINT
, (unsigned char *)h
->read_buffer
, h
->max_packet
,
163 &transferred
, ICDI_READ_TIMEOUT
);
164 if (result
!= 0 || transferred
< 1) {
165 LOG_DEBUG("Error RX Data %d", result
);
169 #ifdef _DEBUG_USB_COMMS_
170 LOG_DEBUG("received reply: '%c' : count %d", h
->read_buffer
[0], transferred
);
173 if (h
->read_buffer
[0] == '-') {
174 LOG_DEBUG("Resending packet %d", ++retry
);
176 if (h
->read_buffer
[0] != '+')
177 LOG_DEBUG("Unexpected Reply from ICDI: %c", h
->read_buffer
[0]);
182 LOG_DEBUG("maximum nack retries attempted");
188 h
->read_count
= transferred
;
192 /* read reply from icdi */
193 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_READ_ENDPOINT
, (unsigned char *)h
->read_buffer
+ h
->read_count
,
194 h
->max_packet
- h
->read_count
, &transferred
, ICDI_READ_TIMEOUT
);
196 #ifdef _DEBUG_USB_COMMS_
197 LOG_DEBUG("received data: count %d", transferred
);
200 /* check for errors but retry for timeout */
203 if (result
== LIBUSB_ERROR_TIMEOUT
) {
204 LOG_DEBUG("Error RX timeout %d", result
);
206 LOG_DEBUG("Error RX Data %d", result
);
211 h
->read_count
+= transferred
;
213 /* we need to make sure we have a full packet, including checksum */
214 if (h
->read_count
> 5) {
216 /* check that we have received an packet delimiter
217 * we do not validate the checksum
218 * reply should contain $...#AA - so we check for # */
219 if (h
->read_buffer
[h
->read_count
- 3] == '#')
224 LOG_DEBUG("maximum data retries attempted");
232 static int icdi_send_cmd(void *handle
, const char *cmd
)
234 struct icdi_usb_handle_s
*h
;
235 h
= (struct icdi_usb_handle_s
*)handle
;
237 int cmd_len
= snprintf(h
->write_buffer
, h
->max_packet
, PACKET_START
"%s", cmd
);
238 return icdi_send_packet(handle
, cmd_len
);
241 static int icdi_send_remote_cmd(void *handle
, const char *data
)
243 struct icdi_usb_handle_s
*h
;
244 h
= (struct icdi_usb_handle_s
*)handle
;
246 size_t cmd_len
= sprintf(h
->write_buffer
, PACKET_START
"qRcmd,");
247 cmd_len
+= hexify(h
->write_buffer
+ cmd_len
, data
, 0, h
->max_packet
- cmd_len
);
249 return icdi_send_packet(handle
, cmd_len
);
252 static int icdi_get_cmd_result(void *handle
)
254 struct icdi_usb_handle_s
*h
;
258 assert(handle
!= NULL
);
259 h
= (struct icdi_usb_handle_s
*)handle
;
262 ch
= h
->read_buffer
[offset
++];
263 if (offset
> h
->read_count
)
267 if (memcmp("OK", h
->read_buffer
+ offset
, 2) == 0)
270 if (h
->read_buffer
[offset
] == 'E') {
273 if (unhexify(&result
, h
->read_buffer
+ offset
+ 1, 1) != 1)
278 /* for now we assume everything else is ok */
282 static int icdi_usb_idcode(void *handle
, uint32_t *idcode
)
287 static int icdi_usb_write_debug_reg(void *handle
, uint32_t addr
, uint32_t val
)
289 return icdi_usb_write_mem32(handle
, addr
, 1, (uint8_t *)&val
);
292 static enum target_state
icdi_usb_state(void *handle
)
295 struct icdi_usb_handle_s
*h
;
298 h
= (struct icdi_usb_handle_s
*)handle
;
300 result
= icdi_usb_read_mem32(h
, DCB_DHCSR
, 1, (uint8_t *)&dhcsr
);
301 if (result
!= ERROR_OK
)
302 return TARGET_UNKNOWN
;
305 return TARGET_HALTED
;
307 return TARGET_RUNNING
;
310 static int icdi_usb_version(void *handle
)
312 struct icdi_usb_handle_s
*h
;
313 h
= (struct icdi_usb_handle_s
*)handle
;
317 /* get info about icdi */
318 int result
= icdi_send_remote_cmd(handle
, "version");
319 if (result
!= ERROR_OK
)
322 if (h
->read_count
< 8) {
323 LOG_ERROR("Invalid Reply Received");
328 if (unhexify(version
, h
->read_buffer
+ 2, 4) != 4) {
329 LOG_WARNING("unable to get ICDI version");
333 /* null terminate and print info */
336 LOG_INFO("ICDI Firmware version: %s", version
);
341 static int icdi_usb_query(void *handle
)
345 struct icdi_usb_handle_s
*h
;
346 h
= (struct icdi_usb_handle_s
*)handle
;
348 result
= icdi_send_cmd(handle
, "qSupported");
349 if (result
!= ERROR_OK
)
353 result
= icdi_get_cmd_result(handle
);
354 if (result
!= ERROR_OK
) {
355 LOG_ERROR("query supported failed: 0x%x", result
);
359 /* from this we can get the max packet supported */
361 /* query packet buffer size */
362 char *offset
= strstr(h
->read_buffer
, "PacketSize");
367 max_packet
= strtoul(offset
+ 11, &separator
, 16);
369 LOG_ERROR("invalid max packet, using defaults");
371 h
->max_packet
= max_packet
;
372 LOG_DEBUG("max packet supported : %" PRIu32
" bytes", h
->max_packet
);
376 /* if required re allocate packet buffer */
377 if (h
->max_packet
!= ICDI_PACKET_SIZE
) {
378 h
->read_buffer
= realloc(h
->read_buffer
, h
->max_packet
);
379 h
->write_buffer
= realloc(h
->write_buffer
, h
->max_packet
);
380 if (h
->read_buffer
== 0 || h
->write_buffer
== 0) {
381 LOG_ERROR("unable to reallocate memory");
386 /* set extended mode */
387 result
= icdi_send_cmd(handle
, "!");
388 if (result
!= ERROR_OK
)
392 result
= icdi_get_cmd_result(handle
);
393 if (result
!= ERROR_OK
) {
394 LOG_ERROR("unable to enable extended mode: 0x%x", result
);
401 static int icdi_usb_reset(void *handle
)
403 /* we do this in hla_target.c */
407 static int icdi_usb_assert_srst(void *handle
, int srst
)
409 /* TODO not supported yet */
410 return ERROR_COMMAND_NOTFOUND
;
413 static int icdi_usb_run(void *handle
)
417 /* resume target at current address */
418 result
= icdi_send_cmd(handle
, "c");
419 if (result
!= ERROR_OK
)
423 result
= icdi_get_cmd_result(handle
);
424 if (result
!= ERROR_OK
) {
425 LOG_ERROR("continue failed: 0x%x", result
);
432 static int icdi_usb_halt(void *handle
)
436 /* this query halts the target ?? */
437 result
= icdi_send_cmd(handle
, "?");
438 if (result
!= ERROR_OK
)
442 result
= icdi_get_cmd_result(handle
);
443 if (result
!= ERROR_OK
) {
444 LOG_ERROR("halt failed: 0x%x", result
);
451 static int icdi_usb_step(void *handle
)
455 /* step target at current address */
456 result
= icdi_send_cmd(handle
, "s");
457 if (result
!= ERROR_OK
)
461 result
= icdi_get_cmd_result(handle
);
462 if (result
!= ERROR_OK
) {
463 LOG_ERROR("step failed: 0x%x", result
);
470 static int icdi_usb_read_regs(void *handle
)
472 /* currently unsupported */
476 static int icdi_usb_read_reg(void *handle
, int num
, uint32_t *val
)
479 struct icdi_usb_handle_s
*h
;
482 h
= (struct icdi_usb_handle_s
*)handle
;
484 snprintf(cmd
, sizeof(cmd
), "p%x", num
);
485 result
= icdi_send_cmd(handle
, cmd
);
486 if (result
!= ERROR_OK
)
490 result
= icdi_get_cmd_result(handle
);
491 if (result
!= ERROR_OK
) {
492 LOG_ERROR("register read failed: 0x%x", result
);
497 if (unhexify((char *)val
, h
->read_buffer
+ 2, 4) != 4) {
498 LOG_ERROR("failed to convert result");
505 static int icdi_usb_write_reg(void *handle
, int num
, uint32_t val
)
510 int cmd_len
= snprintf(cmd
, sizeof(cmd
), "P%x=", num
);
511 hexify(cmd
+ cmd_len
, (char *)&val
, 4, sizeof(cmd
));
513 result
= icdi_send_cmd(handle
, cmd
);
514 if (result
!= ERROR_OK
)
518 result
= icdi_get_cmd_result(handle
);
519 if (result
!= ERROR_OK
) {
520 LOG_ERROR("register write failed: 0x%x", result
);
527 static int icdi_usb_read_mem(void *handle
, uint32_t addr
, uint32_t len
, uint8_t *buffer
)
530 struct icdi_usb_handle_s
*h
;
533 h
= (struct icdi_usb_handle_s
*)handle
;
535 snprintf(cmd
, sizeof(cmd
), "x%x,%x", addr
, len
);
536 result
= icdi_send_cmd(handle
, cmd
);
537 if (result
!= ERROR_OK
)
541 result
= icdi_get_cmd_result(handle
);
542 if (result
!= ERROR_OK
) {
543 LOG_ERROR("memory read failed: 0x%x", result
);
548 int read_len
= remote_unescape_input(h
->read_buffer
+ 5, h
->read_count
- 8, (char *)buffer
, len
);
549 if (read_len
!= (int)len
) {
550 LOG_ERROR("read more bytes than expected: actual 0x%" PRIx32
" expected 0x%" PRIx32
, read_len
, len
);
557 static int icdi_usb_write_mem(void *handle
, uint32_t addr
, uint32_t len
, const uint8_t *buffer
)
560 struct icdi_usb_handle_s
*h
;
562 h
= (struct icdi_usb_handle_s
*)handle
;
564 size_t cmd_len
= snprintf(h
->write_buffer
, h
->max_packet
, PACKET_START
"X%x,%x:", addr
, len
);
567 cmd_len
+= remote_escape_output((char *)buffer
, len
, h
->write_buffer
+ cmd_len
,
568 &out_len
, h
->max_packet
- cmd_len
);
570 if (out_len
< (int)len
) {
571 /* for now issue a error as we have no way of allocating a larger buffer */
572 LOG_ERROR("memory buffer too small: requires 0x%" PRIx32
" actual 0x%" PRIx32
, out_len
, len
);
576 result
= icdi_send_packet(handle
, cmd_len
);
577 if (result
!= ERROR_OK
)
581 result
= icdi_get_cmd_result(handle
);
582 if (result
!= ERROR_OK
) {
583 LOG_ERROR("memory write failed: 0x%x", result
);
590 static int icdi_usb_read_mem8(void *handle
, uint32_t addr
, uint16_t len
, uint8_t *buffer
)
592 return icdi_usb_read_mem(handle
, addr
, len
, buffer
);
595 static int icdi_usb_write_mem8(void *handle
, uint32_t addr
, uint16_t len
, const uint8_t *buffer
)
597 return icdi_usb_write_mem(handle
, addr
, len
, buffer
);
600 static int icdi_usb_read_mem32(void *handle
, uint32_t addr
, uint16_t len
, uint8_t *buffer
)
602 return icdi_usb_read_mem(handle
, addr
, len
* 4, buffer
);
605 static int icdi_usb_write_mem32(void *handle
, uint32_t addr
, uint16_t len
, const uint8_t *buffer
)
607 return icdi_usb_write_mem(handle
, addr
, len
* 4, buffer
);
610 static int icdi_usb_close(void *handle
)
612 struct icdi_usb_handle_s
*h
;
614 h
= (struct icdi_usb_handle_s
*)handle
;
617 libusb_close(h
->usb_dev
);
620 libusb_exit(h
->usb_ctx
);
623 free(h
->read_buffer
);
626 free(h
->write_buffer
);
633 static int icdi_usb_open(struct hl_interface_param_s
*param
, void **fd
)
636 struct icdi_usb_handle_s
*h
;
638 LOG_DEBUG("icdi_usb_open");
640 h
= calloc(1, sizeof(struct icdi_usb_handle_s
));
643 LOG_ERROR("unable to allocate memory");
647 LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param
->transport
,
648 param
->vid
, param
->pid
);
650 if (libusb_init(&h
->usb_ctx
) != 0) {
651 LOG_ERROR("libusb init failed");
655 h
->usb_dev
= libusb_open_device_with_vid_pid(h
->usb_ctx
, param
->vid
, param
->pid
);
657 LOG_ERROR("open failed");
661 if (libusb_claim_interface(h
->usb_dev
, 2)) {
662 LOG_DEBUG("claim interface failed");
666 /* check if mode is supported */
669 switch (param
->transport
) {
671 /* TODO place holder as swd is not currently supported */
672 case HL_TRANSPORT_SWD
:
674 case HL_TRANSPORT_JTAG
:
681 if (retval
!= ERROR_OK
) {
682 LOG_ERROR("mode (transport) not supported by device");
686 /* allocate buffer */
687 h
->read_buffer
= malloc(ICDI_PACKET_SIZE
);
688 h
->write_buffer
= malloc(ICDI_PACKET_SIZE
);
689 h
->max_packet
= ICDI_PACKET_SIZE
;
691 if (h
->read_buffer
== 0 || h
->write_buffer
== 0) {
692 LOG_DEBUG("malloc failed");
696 /* query icdi version etc */
697 retval
= icdi_usb_version(h
);
698 if (retval
!= ERROR_OK
)
701 /* query icdi support */
702 retval
= icdi_usb_query(h
);
703 if (retval
!= ERROR_OK
)
708 /* set the max target read/write buffer in bytes
709 * as we are using gdb binary packets to transfer memory we have to
710 * reserve half the buffer for any possible escape chars plus
711 * at least 64 bytes for the gdb packet header */
712 param
->max_buffer
= (((h
->max_packet
- 64) / 4) * 4) / 2;
722 struct hl_layout_api_s icdi_usb_layout_api
= {
723 .open
= icdi_usb_open
,
724 .close
= icdi_usb_close
,
725 .idcode
= icdi_usb_idcode
,
726 .state
= icdi_usb_state
,
727 .reset
= icdi_usb_reset
,
728 .assert_srst
= icdi_usb_assert_srst
,
730 .halt
= icdi_usb_halt
,
731 .step
= icdi_usb_step
,
732 .read_regs
= icdi_usb_read_regs
,
733 .read_reg
= icdi_usb_read_reg
,
734 .write_reg
= icdi_usb_write_reg
,
735 .read_mem8
= icdi_usb_read_mem8
,
736 .write_mem8
= icdi_usb_write_mem8
,
737 .read_mem32
= icdi_usb_read_mem32
,
738 .write_mem32
= icdi_usb_write_mem32
,
739 .write_debug_reg
= icdi_usb_write_debug_reg
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)