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>
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
;
56 uint32_t max_rw_packet
; /* max X packet (read/write memory) transfers */
59 static int icdi_usb_read_mem(void *handle
, uint32_t addr
, uint32_t size
,
60 uint32_t count
, uint8_t *buffer
);
61 static int icdi_usb_write_mem(void *handle
, uint32_t addr
, uint32_t size
,
62 uint32_t count
, const uint8_t *buffer
);
64 static int remote_escape_output(const char *buffer
, int len
, char *out_buf
, int *out_len
, int out_maxlen
)
66 int input_index
, output_index
;
70 for (input_index
= 0; input_index
< len
; input_index
++) {
72 char b
= buffer
[input_index
];
74 if (b
== '$' || b
== '#' || b
== '}' || b
== '*') {
75 /* These must be escaped. */
76 if (output_index
+ 2 > out_maxlen
)
78 out_buf
[output_index
++] = '}';
79 out_buf
[output_index
++] = b
^ 0x20;
81 if (output_index
+ 1 > out_maxlen
)
83 out_buf
[output_index
++] = b
;
87 *out_len
= input_index
;
91 static int remote_unescape_input(const char *buffer
, int len
, char *out_buf
, int out_maxlen
)
93 int input_index
, output_index
;
99 for (input_index
= 0; input_index
< len
; input_index
++) {
101 char b
= buffer
[input_index
];
103 if (output_index
+ 1 > out_maxlen
)
104 LOG_ERROR("Received too much data from the target.");
107 out_buf
[output_index
++] = b
^ 0x20;
112 out_buf
[output_index
++] = b
;
116 LOG_ERROR("Unmatched escape character in target response.");
121 static int icdi_send_packet(void *handle
, int len
)
123 unsigned char cksum
= 0;
124 struct icdi_usb_handle_s
*h
= handle
;
125 int result
, retry
= 0;
128 assert(handle
!= NULL
);
130 /* check we have a large enough buffer for checksum "#00" */
131 if (len
+ 3 > h
->max_packet
) {
132 LOG_ERROR("packet buffer too small");
136 /* calculate checksum - offset start of packet */
137 for (int i
= 1; i
< len
; i
++)
138 cksum
+= h
->write_buffer
[i
];
140 len
+= sprintf(&h
->write_buffer
[len
], PACKET_END
"%02x", cksum
);
142 #ifdef _DEBUG_USB_COMMS_
144 char ch
= h
->write_buffer
[1];
145 if (ch
== 'x' || ch
== 'X')
146 LOG_DEBUG("writing packet: <binary>");
148 memcpy(buffer
, h
->write_buffer
, len
>= 50 ? 50-1 : len
);
150 LOG_DEBUG("writing packet: %s", buffer
);
156 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_WRITE_ENDPOINT
, (unsigned char *)h
->write_buffer
, len
,
157 &transferred
, ICDI_WRITE_TIMEOUT
);
158 if (result
!= 0 || transferred
!= len
) {
159 LOG_DEBUG("Error TX Data %d", result
);
163 /* check that the client got the message ok, or shall we resend */
164 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_READ_ENDPOINT
, (unsigned char *)h
->read_buffer
, h
->max_packet
,
165 &transferred
, ICDI_READ_TIMEOUT
);
166 if (result
!= 0 || transferred
< 1) {
167 LOG_DEBUG("Error RX Data %d", result
);
171 #ifdef _DEBUG_USB_COMMS_
172 LOG_DEBUG("received reply: '%c' : count %d", h
->read_buffer
[0], transferred
);
175 if (h
->read_buffer
[0] == '-') {
176 LOG_DEBUG("Resending packet %d", ++retry
);
178 if (h
->read_buffer
[0] != '+')
179 LOG_DEBUG("Unexpected Reply from ICDI: %c", h
->read_buffer
[0]);
184 LOG_DEBUG("maximum nack retries attempted");
190 h
->read_count
= transferred
;
194 /* read reply from icdi */
195 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_READ_ENDPOINT
, (unsigned char *)h
->read_buffer
+ h
->read_count
,
196 h
->max_packet
- h
->read_count
, &transferred
, ICDI_READ_TIMEOUT
);
198 #ifdef _DEBUG_USB_COMMS_
199 LOG_DEBUG("received data: count %d", transferred
);
202 /* check for errors but retry for timeout */
205 if (result
== LIBUSB_ERROR_TIMEOUT
) {
206 LOG_DEBUG("Error RX timeout %d", result
);
208 LOG_DEBUG("Error RX Data %d", result
);
213 h
->read_count
+= transferred
;
215 /* we need to make sure we have a full packet, including checksum */
216 if (h
->read_count
> 5) {
218 /* check that we have received an packet delimiter
219 * we do not validate the checksum
220 * reply should contain $...#AA - so we check for # */
221 if (h
->read_buffer
[h
->read_count
- 3] == '#')
226 LOG_DEBUG("maximum data retries attempted");
234 static int icdi_send_cmd(void *handle
, const char *cmd
)
236 struct icdi_usb_handle_s
*h
= handle
;
238 int cmd_len
= snprintf(h
->write_buffer
, h
->max_packet
, PACKET_START
"%s", cmd
);
239 return icdi_send_packet(handle
, cmd_len
);
242 static int icdi_send_remote_cmd(void *handle
, const char *data
)
244 struct icdi_usb_handle_s
*h
= 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
= handle
;
258 assert(handle
!= NULL
);
261 ch
= h
->read_buffer
[offset
++];
262 if (offset
> h
->read_count
)
266 if (memcmp("OK", h
->read_buffer
+ offset
, 2) == 0)
269 if (h
->read_buffer
[offset
] == 'E') {
272 if (unhexify(&result
, h
->read_buffer
+ offset
+ 1, 1) != 1)
277 /* for now we assume everything else is ok */
281 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
)
290 /* REVISIT: There's no target pointer here so there's no way to use target_buffer_set_u32().
291 * I guess all supported chips are little-endian anyway. */
292 h_u32_to_le(buf
, val
);
293 return icdi_usb_write_mem(handle
, addr
, 4, 1, buf
);
296 static enum target_state
icdi_usb_state(void *handle
)
299 struct icdi_usb_handle_s
*h
= handle
;
303 result
= icdi_usb_read_mem(h
, DCB_DHCSR
, 4, 1, buf
);
304 if (result
!= ERROR_OK
)
305 return TARGET_UNKNOWN
;
307 /* REVISIT: There's no target pointer here so there's no way to use target_buffer_get_u32().
308 * I guess all supported chips are little-endian anyway. */
309 dhcsr
= le_to_h_u32(buf
);
311 return TARGET_HALTED
;
313 return TARGET_RUNNING
;
316 static int icdi_usb_version(void *handle
)
318 struct icdi_usb_handle_s
*h
= handle
;
322 /* get info about icdi */
323 int result
= icdi_send_remote_cmd(handle
, "version");
324 if (result
!= ERROR_OK
)
327 if (h
->read_count
< 8) {
328 LOG_ERROR("Invalid Reply Received");
333 if (unhexify(version
, h
->read_buffer
+ 2, 4) != 4) {
334 LOG_WARNING("unable to get ICDI version");
338 /* null terminate and print info */
341 LOG_INFO("ICDI Firmware version: %s", version
);
346 static int icdi_usb_query(void *handle
)
350 struct icdi_usb_handle_s
*h
= handle
;
352 result
= icdi_send_cmd(handle
, "qSupported");
353 if (result
!= ERROR_OK
)
357 result
= icdi_get_cmd_result(handle
);
358 if (result
!= ERROR_OK
) {
359 LOG_ERROR("query supported failed: 0x%x", result
);
363 /* from this we can get the max packet supported */
365 /* query packet buffer size */
366 char *offset
= strstr(h
->read_buffer
, "PacketSize");
371 max_packet
= strtol(offset
+ 11, &separator
, 16);
373 LOG_ERROR("invalid max packet, using defaults");
375 h
->max_packet
= max_packet
;
376 LOG_DEBUG("max packet supported : %i bytes", h
->max_packet
);
380 /* if required re allocate packet buffer */
381 if (h
->max_packet
!= ICDI_PACKET_SIZE
) {
382 h
->read_buffer
= realloc(h
->read_buffer
, h
->max_packet
);
383 h
->write_buffer
= realloc(h
->write_buffer
, h
->max_packet
);
384 if (h
->read_buffer
== 0 || h
->write_buffer
== 0) {
385 LOG_ERROR("unable to reallocate memory");
390 /* set extended mode */
391 result
= icdi_send_cmd(handle
, "!");
392 if (result
!= ERROR_OK
)
396 result
= icdi_get_cmd_result(handle
);
397 if (result
!= ERROR_OK
) {
398 LOG_ERROR("unable to enable extended mode: 0x%x", result
);
405 static int icdi_usb_reset(void *handle
)
407 /* we do this in hla_target.c */
411 static int icdi_usb_assert_srst(void *handle
, int srst
)
413 /* TODO not supported yet */
414 return ERROR_COMMAND_NOTFOUND
;
417 static int icdi_usb_run(void *handle
)
421 /* resume target at current address */
422 result
= icdi_send_cmd(handle
, "c");
423 if (result
!= ERROR_OK
)
427 result
= icdi_get_cmd_result(handle
);
428 if (result
!= ERROR_OK
) {
429 LOG_ERROR("continue failed: 0x%x", result
);
436 static int icdi_usb_halt(void *handle
)
440 /* this query halts the target ?? */
441 result
= icdi_send_cmd(handle
, "?");
442 if (result
!= ERROR_OK
)
446 result
= icdi_get_cmd_result(handle
);
447 if (result
!= ERROR_OK
) {
448 LOG_ERROR("halt failed: 0x%x", result
);
455 static int icdi_usb_step(void *handle
)
459 /* step target at current address */
460 result
= icdi_send_cmd(handle
, "s");
461 if (result
!= ERROR_OK
)
465 result
= icdi_get_cmd_result(handle
);
466 if (result
!= ERROR_OK
) {
467 LOG_ERROR("step failed: 0x%x", result
);
474 static int icdi_usb_read_regs(void *handle
)
476 /* currently unsupported */
480 static int icdi_usb_read_reg(void *handle
, int num
, uint32_t *val
)
483 struct icdi_usb_handle_s
*h
= handle
;
486 snprintf(cmd
, sizeof(cmd
), "p%x", num
);
487 result
= icdi_send_cmd(handle
, cmd
);
488 if (result
!= ERROR_OK
)
492 result
= icdi_get_cmd_result(handle
);
493 if (result
!= ERROR_OK
) {
494 LOG_ERROR("register read failed: 0x%x", result
);
500 if (unhexify((char *)buf
, h
->read_buffer
+ 2, 4) != 4) {
501 LOG_ERROR("failed to convert result");
504 *val
= le_to_h_u32(buf
);
509 static int icdi_usb_write_reg(void *handle
, int num
, uint32_t val
)
514 h_u32_to_le(buf
, val
);
516 int cmd_len
= snprintf(cmd
, sizeof(cmd
), "P%x=", num
);
517 hexify(cmd
+ cmd_len
, (const char *)buf
, 4, sizeof(cmd
));
519 result
= icdi_send_cmd(handle
, cmd
);
520 if (result
!= ERROR_OK
)
524 result
= icdi_get_cmd_result(handle
);
525 if (result
!= ERROR_OK
) {
526 LOG_ERROR("register write failed: 0x%x", result
);
533 static int icdi_usb_read_mem_int(void *handle
, uint32_t addr
, uint32_t len
, uint8_t *buffer
)
536 struct icdi_usb_handle_s
*h
= handle
;
539 snprintf(cmd
, sizeof(cmd
), "x%" PRIx32
",%" PRIx32
, addr
, len
);
540 result
= icdi_send_cmd(handle
, cmd
);
541 if (result
!= ERROR_OK
)
545 result
= icdi_get_cmd_result(handle
);
546 if (result
!= ERROR_OK
) {
547 LOG_ERROR("memory read failed: 0x%x", result
);
552 int read_len
= remote_unescape_input(h
->read_buffer
+ 5, h
->read_count
- 8, (char *)buffer
, len
);
553 if (read_len
!= (int)len
) {
554 LOG_ERROR("read more bytes than expected: actual 0x%x expected 0x%" PRIx32
, read_len
, len
);
561 static int icdi_usb_write_mem_int(void *handle
, uint32_t addr
, uint32_t len
, const uint8_t *buffer
)
564 struct icdi_usb_handle_s
*h
= handle
;
566 size_t cmd_len
= snprintf(h
->write_buffer
, h
->max_packet
, PACKET_START
"X%" PRIx32
",%" PRIx32
":", addr
, len
);
569 cmd_len
+= remote_escape_output((const char *)buffer
, len
, h
->write_buffer
+ cmd_len
,
570 &out_len
, h
->max_packet
- cmd_len
);
572 if (out_len
< (int)len
) {
573 /* for now issue a error as we have no way of allocating a larger buffer */
574 LOG_ERROR("memory buffer too small: requires 0x%x actual 0x%" PRIx32
, out_len
, len
);
578 result
= icdi_send_packet(handle
, cmd_len
);
579 if (result
!= ERROR_OK
)
583 result
= icdi_get_cmd_result(handle
);
584 if (result
!= ERROR_OK
) {
585 LOG_ERROR("memory write failed: 0x%x", result
);
592 static int icdi_usb_read_mem(void *handle
, uint32_t addr
, uint32_t size
,
593 uint32_t count
, uint8_t *buffer
)
595 int retval
= ERROR_OK
;
596 struct icdi_usb_handle_s
*h
= handle
;
597 uint32_t bytes_remaining
;
599 /* calculate byte count */
604 bytes_remaining
= h
->max_rw_packet
;
605 if (count
< bytes_remaining
)
606 bytes_remaining
= count
;
608 retval
= icdi_usb_read_mem_int(handle
, addr
, bytes_remaining
, buffer
);
609 if (retval
!= ERROR_OK
)
612 buffer
+= bytes_remaining
;
613 addr
+= bytes_remaining
;
614 count
-= bytes_remaining
;
620 static int icdi_usb_write_mem(void *handle
, uint32_t addr
, uint32_t size
,
621 uint32_t count
, const uint8_t *buffer
)
623 int retval
= ERROR_OK
;
624 struct icdi_usb_handle_s
*h
= handle
;
625 uint32_t bytes_remaining
;
627 /* calculate byte count */
632 bytes_remaining
= h
->max_rw_packet
;
633 if (count
< bytes_remaining
)
634 bytes_remaining
= count
;
636 retval
= icdi_usb_write_mem_int(handle
, addr
, bytes_remaining
, buffer
);
637 if (retval
!= ERROR_OK
)
640 buffer
+= bytes_remaining
;
641 addr
+= bytes_remaining
;
642 count
-= bytes_remaining
;
648 static int icdi_usb_override_target(const char *targetname
)
650 return !strcmp(targetname
, "cortex_m");
653 static int icdi_usb_close(void *handle
)
655 struct icdi_usb_handle_s
*h
= handle
;
661 libusb_close(h
->usb_dev
);
664 libusb_exit(h
->usb_ctx
);
667 free(h
->read_buffer
);
670 free(h
->write_buffer
);
677 static int icdi_usb_open(struct hl_interface_param_s
*param
, void **fd
)
680 struct icdi_usb_handle_s
*h
;
682 LOG_DEBUG("icdi_usb_open");
684 h
= calloc(1, sizeof(struct icdi_usb_handle_s
));
687 LOG_ERROR("unable to allocate memory");
691 LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param
->transport
,
692 param
->vid
, param
->pid
);
694 if (libusb_init(&h
->usb_ctx
) != 0) {
695 LOG_ERROR("libusb init failed");
699 h
->usb_dev
= libusb_open_device_with_vid_pid(h
->usb_ctx
, param
->vid
, param
->pid
);
701 LOG_ERROR("open failed");
705 if (libusb_claim_interface(h
->usb_dev
, 2)) {
706 LOG_DEBUG("claim interface failed");
710 /* check if mode is supported */
713 switch (param
->transport
) {
715 /* TODO place holder as swd is not currently supported */
716 case HL_TRANSPORT_SWD
:
718 case HL_TRANSPORT_JTAG
:
725 if (retval
!= ERROR_OK
) {
726 LOG_ERROR("mode (transport) not supported by device");
730 /* allocate buffer */
731 h
->read_buffer
= malloc(ICDI_PACKET_SIZE
);
732 h
->write_buffer
= malloc(ICDI_PACKET_SIZE
);
733 h
->max_packet
= ICDI_PACKET_SIZE
;
735 if (h
->read_buffer
== 0 || h
->write_buffer
== 0) {
736 LOG_DEBUG("malloc failed");
740 /* query icdi version etc */
741 retval
= icdi_usb_version(h
);
742 if (retval
!= ERROR_OK
)
745 /* query icdi support */
746 retval
= icdi_usb_query(h
);
747 if (retval
!= ERROR_OK
)
752 /* set the max target read/write buffer in bytes
753 * as we are using gdb binary packets to transfer memory we have to
754 * reserve half the buffer for any possible escape chars plus
755 * at least 64 bytes for the gdb packet header */
756 h
->max_rw_packet
= (((h
->max_packet
- 64) / 4) * 4) / 2;
766 struct hl_layout_api_s icdi_usb_layout_api
= {
767 .open
= icdi_usb_open
,
768 .close
= icdi_usb_close
,
769 .idcode
= icdi_usb_idcode
,
770 .state
= icdi_usb_state
,
771 .reset
= icdi_usb_reset
,
772 .assert_srst
= icdi_usb_assert_srst
,
774 .halt
= icdi_usb_halt
,
775 .step
= icdi_usb_step
,
776 .read_regs
= icdi_usb_read_regs
,
777 .read_reg
= icdi_usb_read_reg
,
778 .write_reg
= icdi_usb_write_reg
,
779 .read_mem
= icdi_usb_read_mem
,
780 .write_mem
= icdi_usb_write_mem
,
781 .write_debug_reg
= icdi_usb_write_debug_reg
,
782 .override_target
= icdi_usb_override_target
,
783 .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)