1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
5 * Copyright (C) 2012 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 ***************************************************************************/
13 /* project specific includes */
14 #include <helper/binarybuffer.h>
15 #include <jtag/adapter.h>
16 #include <jtag/interface.h>
17 #include <jtag/hla/hla_layout.h>
18 #include <jtag/hla/hla_transport.h>
19 #include <jtag/hla/hla_interface.h>
20 #include <target/target.h>
22 #include <target/cortex_m.h>
24 #include "libusb_helper.h"
26 #define ICDI_WRITE_ENDPOINT 0x02
27 #define ICDI_READ_ENDPOINT 0x83
29 #define ICDI_WRITE_TIMEOUT (LIBUSB_TIMEOUT_MS)
30 #define ICDI_READ_TIMEOUT (LIBUSB_TIMEOUT_MS)
31 #define ICDI_PACKET_SIZE 2048
33 #define PACKET_START "$"
34 #define PACKET_END "#"
36 struct icdi_usb_handle_s
{
37 struct libusb_device_handle
*usb_dev
;
43 uint32_t max_rw_packet
; /* max X packet (read/write memory) transfers */
46 static int icdi_usb_read_mem(void *handle
, uint32_t addr
, uint32_t size
,
47 uint32_t count
, uint8_t *buffer
);
48 static int icdi_usb_write_mem(void *handle
, uint32_t addr
, uint32_t size
,
49 uint32_t count
, const uint8_t *buffer
);
51 static int remote_escape_output(const char *buffer
, int len
, char *out_buf
, int *out_len
, int out_maxlen
)
53 int input_index
, output_index
;
57 for (input_index
= 0; input_index
< len
; input_index
++) {
59 char b
= buffer
[input_index
];
61 if (b
== '$' || b
== '#' || b
== '}' || b
== '*') {
62 /* These must be escaped. */
63 if (output_index
+ 2 > out_maxlen
)
65 out_buf
[output_index
++] = '}';
66 out_buf
[output_index
++] = b
^ 0x20;
68 if (output_index
+ 1 > out_maxlen
)
70 out_buf
[output_index
++] = b
;
74 *out_len
= input_index
;
78 static int remote_unescape_input(const char *buffer
, int len
, char *out_buf
, int out_maxlen
)
80 int input_index
, output_index
;
86 for (input_index
= 0; input_index
< len
; input_index
++) {
88 char b
= buffer
[input_index
];
90 if (output_index
+ 1 > out_maxlen
)
91 LOG_ERROR("Received too much data from the target.");
94 out_buf
[output_index
++] = b
^ 0x20;
99 out_buf
[output_index
++] = b
;
103 LOG_ERROR("Unmatched escape character in target response.");
108 static int icdi_send_packet(void *handle
, int len
)
110 unsigned char cksum
= 0;
111 struct icdi_usb_handle_s
*h
= handle
;
112 int result
, retry
= 0;
117 /* check we have a large enough buffer for checksum "#00" */
118 if (len
+ 3 > h
->max_packet
) {
119 LOG_ERROR("packet buffer too small");
123 /* calculate checksum - offset start of packet */
124 for (int i
= 1; i
< len
; i
++)
125 cksum
+= h
->write_buffer
[i
];
127 len
+= sprintf(&h
->write_buffer
[len
], PACKET_END
"%02x", cksum
);
129 #ifdef _DEBUG_USB_COMMS_
131 char ch
= h
->write_buffer
[1];
132 if (ch
== 'x' || ch
== 'X')
133 LOG_DEBUG("writing packet: <binary>");
135 memcpy(buffer
, h
->write_buffer
, len
>= 50 ? 50-1 : len
);
137 LOG_DEBUG("writing packet: %s", buffer
);
143 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_WRITE_ENDPOINT
, (unsigned char *)h
->write_buffer
, len
,
144 &transferred
, ICDI_WRITE_TIMEOUT
);
145 if (result
!= 0 || transferred
!= len
) {
146 LOG_DEBUG("Error TX Data %d", result
);
150 /* check that the client got the message ok, or shall we resend */
151 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_READ_ENDPOINT
, (unsigned char *)h
->read_buffer
, h
->max_packet
,
152 &transferred
, ICDI_READ_TIMEOUT
);
153 if (result
!= 0 || transferred
< 1) {
154 LOG_DEBUG("Error RX Data %d", result
);
158 #ifdef _DEBUG_USB_COMMS_
159 LOG_DEBUG("received reply: '%c' : count %d", h
->read_buffer
[0], transferred
);
162 if (h
->read_buffer
[0] == '-') {
163 LOG_DEBUG("Resending packet %d", ++retry
);
165 if (h
->read_buffer
[0] != '+')
166 LOG_DEBUG("Unexpected Reply from ICDI: %c", h
->read_buffer
[0]);
171 LOG_DEBUG("maximum nack retries attempted");
177 h
->read_count
= transferred
;
181 /* read reply from icdi */
182 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_READ_ENDPOINT
, (unsigned char *)h
->read_buffer
+ h
->read_count
,
183 h
->max_packet
- h
->read_count
, &transferred
, ICDI_READ_TIMEOUT
);
185 #ifdef _DEBUG_USB_COMMS_
186 LOG_DEBUG("received data: count %d", transferred
);
189 /* check for errors but retry for timeout */
192 if (result
== LIBUSB_ERROR_TIMEOUT
) {
193 LOG_DEBUG("Error RX timeout %d", result
);
195 LOG_DEBUG("Error RX Data %d", result
);
200 h
->read_count
+= transferred
;
202 /* we need to make sure we have a full packet, including checksum */
203 if (h
->read_count
> 5) {
205 /* check that we have received an packet delimiter
206 * we do not validate the checksum
207 * reply should contain $...#AA - so we check for # */
208 if (h
->read_buffer
[h
->read_count
- 3] == '#')
213 LOG_DEBUG("maximum data retries attempted");
221 static int icdi_send_cmd(void *handle
, const char *cmd
)
223 struct icdi_usb_handle_s
*h
= handle
;
225 int cmd_len
= snprintf(h
->write_buffer
, h
->max_packet
, PACKET_START
"%s", cmd
);
226 return icdi_send_packet(handle
, cmd_len
);
229 static int icdi_send_remote_cmd(void *handle
, const char *data
)
231 struct icdi_usb_handle_s
*h
= handle
;
233 size_t cmd_len
= sprintf(h
->write_buffer
, PACKET_START
"qRcmd,");
234 cmd_len
+= hexify(h
->write_buffer
+ cmd_len
, (const uint8_t *)data
,
235 strlen(data
), h
->max_packet
- cmd_len
);
237 return icdi_send_packet(handle
, cmd_len
);
240 static int icdi_get_cmd_result(void *handle
)
242 struct icdi_usb_handle_s
*h
= handle
;
249 ch
= h
->read_buffer
[offset
++];
250 if (offset
> h
->read_count
)
254 if (memcmp("OK", h
->read_buffer
+ offset
, 2) == 0)
257 if (h
->read_buffer
[offset
] == 'E') {
260 if (unhexify(&result
, h
->read_buffer
+ offset
+ 1, 1) != 1)
265 /* for now we assume everything else is ok */
269 static int icdi_usb_idcode(void *handle
, uint32_t *idcode
)
275 static int icdi_usb_write_debug_reg(void *handle
, uint32_t addr
, uint32_t val
)
278 /* REVISIT: There's no target pointer here so there's no way to use target_buffer_set_u32().
279 * I guess all supported chips are little-endian anyway. */
280 h_u32_to_le(buf
, val
);
281 return icdi_usb_write_mem(handle
, addr
, 4, 1, buf
);
284 static enum target_state
icdi_usb_state(void *handle
)
287 struct icdi_usb_handle_s
*h
= handle
;
291 result
= icdi_usb_read_mem(h
, DCB_DHCSR
, 4, 1, buf
);
292 if (result
!= ERROR_OK
)
293 return TARGET_UNKNOWN
;
295 /* REVISIT: There's no target pointer here so there's no way to use target_buffer_get_u32().
296 * I guess all supported chips are little-endian anyway. */
297 dhcsr
= le_to_h_u32(buf
);
299 return TARGET_HALTED
;
301 return TARGET_RUNNING
;
304 static int icdi_usb_version(void *handle
)
306 struct icdi_usb_handle_s
*h
= handle
;
310 /* get info about icdi */
311 int result
= icdi_send_remote_cmd(handle
, "version");
312 if (result
!= ERROR_OK
)
315 if (h
->read_count
< 8) {
316 LOG_ERROR("Invalid Reply Received");
321 if (unhexify((uint8_t *)version
, h
->read_buffer
+ 2, 4) != 4) {
322 LOG_WARNING("unable to get ICDI version");
326 /* null terminate and print info */
329 LOG_INFO("ICDI Firmware version: %s", version
);
334 static int icdi_usb_query(void *handle
)
338 struct icdi_usb_handle_s
*h
= handle
;
340 result
= icdi_send_cmd(handle
, "qSupported");
341 if (result
!= ERROR_OK
)
345 result
= icdi_get_cmd_result(handle
);
346 if (result
!= ERROR_OK
) {
347 LOG_ERROR("query supported failed: 0x%x", result
);
351 /* from this we can get the max packet supported */
353 /* query packet buffer size */
354 char *offset
= strstr(h
->read_buffer
, "PacketSize");
359 max_packet
= strtol(offset
+ 11, &separator
, 16);
361 LOG_ERROR("invalid max packet, using defaults");
363 h
->max_packet
= max_packet
;
364 LOG_DEBUG("max packet supported : %i bytes", h
->max_packet
);
368 /* if required re allocate packet buffer */
369 if (h
->max_packet
!= ICDI_PACKET_SIZE
) {
370 h
->read_buffer
= realloc(h
->read_buffer
, h
->max_packet
);
371 h
->write_buffer
= realloc(h
->write_buffer
, h
->max_packet
);
372 if (h
->read_buffer
== 0 || h
->write_buffer
== 0) {
373 LOG_ERROR("unable to reallocate memory");
378 /* set extended mode */
379 result
= icdi_send_cmd(handle
, "!");
380 if (result
!= ERROR_OK
)
384 result
= icdi_get_cmd_result(handle
);
385 if (result
!= ERROR_OK
) {
386 LOG_ERROR("unable to enable extended mode: 0x%x", result
);
393 static int icdi_usb_reset(void *handle
)
395 /* we do this in hla_target.c */
399 static int icdi_usb_assert_srst(void *handle
, int srst
)
401 /* TODO not supported yet */
402 return ERROR_COMMAND_NOTFOUND
;
405 static int icdi_usb_run(void *handle
)
409 /* resume target at current address */
410 result
= icdi_send_cmd(handle
, "c");
411 if (result
!= ERROR_OK
)
415 result
= icdi_get_cmd_result(handle
);
416 if (result
!= ERROR_OK
) {
417 LOG_ERROR("continue failed: 0x%x", result
);
424 static int icdi_usb_halt(void *handle
)
428 /* this query halts the target ?? */
429 result
= icdi_send_cmd(handle
, "?");
430 if (result
!= ERROR_OK
)
434 result
= icdi_get_cmd_result(handle
);
435 if (result
!= ERROR_OK
) {
436 LOG_ERROR("halt failed: 0x%x", result
);
443 static int icdi_usb_step(void *handle
)
447 /* step target at current address */
448 result
= icdi_send_cmd(handle
, "s");
449 if (result
!= ERROR_OK
)
453 result
= icdi_get_cmd_result(handle
);
454 if (result
!= ERROR_OK
) {
455 LOG_ERROR("step failed: 0x%x", result
);
462 static int icdi_usb_read_regs(void *handle
)
464 /* currently unsupported */
468 static int icdi_usb_read_reg(void *handle
, unsigned int regsel
, uint32_t *val
)
471 struct icdi_usb_handle_s
*h
= handle
;
474 snprintf(cmd
, sizeof(cmd
), "p%x", regsel
);
475 result
= icdi_send_cmd(handle
, cmd
);
476 if (result
!= ERROR_OK
)
480 result
= icdi_get_cmd_result(handle
);
481 if (result
!= ERROR_OK
) {
482 LOG_ERROR("register read failed: 0x%x", result
);
488 if (unhexify(buf
, h
->read_buffer
+ 2, 4) != 4) {
489 LOG_ERROR("failed to convert result");
492 *val
= le_to_h_u32(buf
);
497 static int icdi_usb_write_reg(void *handle
, unsigned int regsel
, uint32_t val
)
502 h_u32_to_le(buf
, val
);
504 int cmd_len
= snprintf(cmd
, sizeof(cmd
), "P%x=", regsel
);
505 hexify(cmd
+ cmd_len
, buf
, 4, sizeof(cmd
));
507 result
= icdi_send_cmd(handle
, cmd
);
508 if (result
!= ERROR_OK
)
512 result
= icdi_get_cmd_result(handle
);
513 if (result
!= ERROR_OK
) {
514 LOG_ERROR("register write failed: 0x%x", result
);
521 static int icdi_usb_read_mem_int(void *handle
, uint32_t addr
, uint32_t len
, uint8_t *buffer
)
524 struct icdi_usb_handle_s
*h
= handle
;
527 snprintf(cmd
, sizeof(cmd
), "x%" PRIx32
",%" PRIx32
, addr
, len
);
528 result
= icdi_send_cmd(handle
, cmd
);
529 if (result
!= ERROR_OK
)
533 result
= icdi_get_cmd_result(handle
);
534 if (result
!= ERROR_OK
) {
535 LOG_ERROR("memory read failed: 0x%x", result
);
540 int read_len
= remote_unescape_input(h
->read_buffer
+ 5, h
->read_count
- 8, (char *)buffer
, len
);
541 if (read_len
!= (int)len
) {
542 LOG_ERROR("read more bytes than expected: actual 0x%x expected 0x%" PRIx32
, read_len
, len
);
549 static int icdi_usb_write_mem_int(void *handle
, uint32_t addr
, uint32_t len
, const uint8_t *buffer
)
552 struct icdi_usb_handle_s
*h
= handle
;
554 size_t cmd_len
= snprintf(h
->write_buffer
, h
->max_packet
, PACKET_START
"X%" PRIx32
",%" PRIx32
":", addr
, len
);
557 cmd_len
+= remote_escape_output((const char *)buffer
, len
, h
->write_buffer
+ cmd_len
,
558 &out_len
, h
->max_packet
- cmd_len
);
560 if (out_len
< (int)len
) {
561 /* for now issue a error as we have no way of allocating a larger buffer */
562 LOG_ERROR("memory buffer too small: requires 0x%x actual 0x%" PRIx32
, out_len
, len
);
566 result
= icdi_send_packet(handle
, cmd_len
);
567 if (result
!= ERROR_OK
)
571 result
= icdi_get_cmd_result(handle
);
572 if (result
!= ERROR_OK
) {
573 LOG_ERROR("memory write failed: 0x%x", result
);
580 static int icdi_usb_read_mem(void *handle
, uint32_t addr
, uint32_t size
,
581 uint32_t count
, uint8_t *buffer
)
583 int retval
= ERROR_OK
;
584 struct icdi_usb_handle_s
*h
= handle
;
585 uint32_t bytes_remaining
;
587 /* calculate byte count */
592 bytes_remaining
= h
->max_rw_packet
;
593 if (count
< bytes_remaining
)
594 bytes_remaining
= count
;
596 retval
= icdi_usb_read_mem_int(handle
, addr
, bytes_remaining
, buffer
);
597 if (retval
!= ERROR_OK
)
600 buffer
+= bytes_remaining
;
601 addr
+= bytes_remaining
;
602 count
-= bytes_remaining
;
608 static int icdi_usb_write_mem(void *handle
, uint32_t addr
, uint32_t size
,
609 uint32_t count
, const uint8_t *buffer
)
611 int retval
= ERROR_OK
;
612 struct icdi_usb_handle_s
*h
= handle
;
613 uint32_t bytes_remaining
;
615 /* calculate byte count */
620 bytes_remaining
= h
->max_rw_packet
;
621 if (count
< bytes_remaining
)
622 bytes_remaining
= count
;
624 retval
= icdi_usb_write_mem_int(handle
, addr
, bytes_remaining
, buffer
);
625 if (retval
!= ERROR_OK
)
628 buffer
+= bytes_remaining
;
629 addr
+= bytes_remaining
;
630 count
-= bytes_remaining
;
636 static int icdi_usb_override_target(const char *targetname
)
638 return !strcmp(targetname
, "cortex_m");
641 static int icdi_usb_close(void *handle
)
643 struct icdi_usb_handle_s
*h
= handle
;
649 jtag_libusb_close(h
->usb_dev
);
651 free(h
->read_buffer
);
652 free(h
->write_buffer
);
657 static int icdi_usb_open(struct hl_interface_param_s
*param
, void **fd
)
659 /* TODO: Convert remaining libusb_ calls to jtag_libusb_ */
661 struct icdi_usb_handle_s
*h
;
663 LOG_DEBUG("icdi_usb_open");
665 h
= calloc(1, sizeof(struct icdi_usb_handle_s
));
668 LOG_ERROR("unable to allocate memory");
672 for (uint8_t i
= 0; param
->vid
[i
] && param
->pid
[i
]; ++i
)
673 LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", param
->transport
,
674 param
->vid
[i
], param
->pid
[i
], adapter_get_required_serial() ? adapter_get_required_serial() : "");
676 /* TI (Stellaris) ICDI provides its serial number in the USB descriptor;
677 no need to provide a callback here. */
678 jtag_libusb_open(param
->vid
, param
->pid
, &h
->usb_dev
, NULL
);
681 LOG_ERROR("open failed");
685 if (libusb_claim_interface(h
->usb_dev
, 2)) {
686 LOG_DEBUG("claim interface failed");
690 /* check if mode is supported */
693 switch (param
->transport
) {
695 /* TODO place holder as swd is not currently supported */
696 case HL_TRANSPORT_SWD
:
698 case HL_TRANSPORT_JTAG
:
705 if (retval
!= ERROR_OK
) {
706 LOG_ERROR("mode (transport) not supported by device");
710 /* allocate buffer */
711 h
->read_buffer
= malloc(ICDI_PACKET_SIZE
);
712 h
->write_buffer
= malloc(ICDI_PACKET_SIZE
);
713 h
->max_packet
= ICDI_PACKET_SIZE
;
715 if (h
->read_buffer
== 0 || h
->write_buffer
== 0) {
716 LOG_DEBUG("malloc failed");
720 /* query icdi version etc */
721 retval
= icdi_usb_version(h
);
722 if (retval
!= ERROR_OK
)
725 /* query icdi support */
726 retval
= icdi_usb_query(h
);
727 if (retval
!= ERROR_OK
)
732 /* set the max target read/write buffer in bytes
733 * as we are using gdb binary packets to transfer memory we have to
734 * reserve half the buffer for any possible escape chars plus
735 * at least 64 bytes for the gdb packet header */
736 h
->max_rw_packet
= (((h
->max_packet
- 64) / 4) * 4) / 2;
746 struct hl_layout_api_s icdi_usb_layout_api
= {
747 .open
= icdi_usb_open
,
748 .close
= icdi_usb_close
,
749 .idcode
= icdi_usb_idcode
,
750 .state
= icdi_usb_state
,
751 .reset
= icdi_usb_reset
,
752 .assert_srst
= icdi_usb_assert_srst
,
754 .halt
= icdi_usb_halt
,
755 .step
= icdi_usb_step
,
756 .read_regs
= icdi_usb_read_regs
,
757 .read_reg
= icdi_usb_read_reg
,
758 .write_reg
= icdi_usb_write_reg
,
759 .read_mem
= icdi_usb_read_mem
,
760 .write_mem
= icdi_usb_write_mem
,
761 .write_debug_reg
= icdi_usb_write_debug_reg
,
762 .override_target
= icdi_usb_override_target
,
763 .custom_command
= icdi_send_remote_cmd
,
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)