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
;
125 int result
, retry
= 0;
128 assert(handle
!= NULL
);
129 h
= (struct icdi_usb_handle_s
*)handle
;
131 /* check we have a large enough buffer for checksum "#00" */
132 if (len
+ 3 > h
->max_packet
) {
133 LOG_ERROR("packet buffer too small");
137 /* calculate checksum - offset start of packet */
138 for (int i
= 1; i
< len
; i
++)
139 cksum
+= h
->write_buffer
[i
];
141 len
+= sprintf(&h
->write_buffer
[len
], PACKET_END
"%02x", cksum
);
143 #ifdef _DEBUG_USB_COMMS_
145 char ch
= h
->write_buffer
[1];
146 if (ch
== 'x' || ch
== 'X')
147 LOG_DEBUG("writing packet: <binary>");
149 memcpy(buffer
, h
->write_buffer
, len
>= 50 ? 50-1 : len
);
151 LOG_DEBUG("writing packet: %s", buffer
);
157 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_WRITE_ENDPOINT
, (unsigned char *)h
->write_buffer
, len
,
158 &transferred
, ICDI_WRITE_TIMEOUT
);
159 if (result
!= 0 || transferred
!= len
) {
160 LOG_DEBUG("Error TX Data %d", result
);
164 /* check that the client got the message ok, or shall we resend */
165 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_READ_ENDPOINT
, (unsigned char *)h
->read_buffer
, h
->max_packet
,
166 &transferred
, ICDI_READ_TIMEOUT
);
167 if (result
!= 0 || transferred
< 1) {
168 LOG_DEBUG("Error RX Data %d", result
);
172 #ifdef _DEBUG_USB_COMMS_
173 LOG_DEBUG("received reply: '%c' : count %d", h
->read_buffer
[0], transferred
);
176 if (h
->read_buffer
[0] == '-') {
177 LOG_DEBUG("Resending packet %d", ++retry
);
179 if (h
->read_buffer
[0] != '+')
180 LOG_DEBUG("Unexpected Reply from ICDI: %c", h
->read_buffer
[0]);
185 LOG_DEBUG("maximum nack retries attempted");
191 h
->read_count
= transferred
;
195 /* read reply from icdi */
196 result
= libusb_bulk_transfer(h
->usb_dev
, ICDI_READ_ENDPOINT
, (unsigned char *)h
->read_buffer
+ h
->read_count
,
197 h
->max_packet
- h
->read_count
, &transferred
, ICDI_READ_TIMEOUT
);
199 #ifdef _DEBUG_USB_COMMS_
200 LOG_DEBUG("received data: count %d", transferred
);
203 /* check for errors but retry for timeout */
206 if (result
== LIBUSB_ERROR_TIMEOUT
) {
207 LOG_DEBUG("Error RX timeout %d", result
);
209 LOG_DEBUG("Error RX Data %d", result
);
214 h
->read_count
+= transferred
;
216 /* we need to make sure we have a full packet, including checksum */
217 if (h
->read_count
> 5) {
219 /* check that we have received an packet delimiter
220 * we do not validate the checksum
221 * reply should contain $...#AA - so we check for # */
222 if (h
->read_buffer
[h
->read_count
- 3] == '#')
227 LOG_DEBUG("maximum data retries attempted");
235 static int icdi_send_cmd(void *handle
, const char *cmd
)
237 struct icdi_usb_handle_s
*h
;
238 h
= (struct icdi_usb_handle_s
*)handle
;
240 int cmd_len
= snprintf(h
->write_buffer
, h
->max_packet
, PACKET_START
"%s", cmd
);
241 return icdi_send_packet(handle
, cmd_len
);
244 static int icdi_send_remote_cmd(void *handle
, const char *data
)
246 struct icdi_usb_handle_s
*h
;
247 h
= (struct icdi_usb_handle_s
*)handle
;
249 size_t cmd_len
= sprintf(h
->write_buffer
, PACKET_START
"qRcmd,");
250 cmd_len
+= hexify(h
->write_buffer
+ cmd_len
, data
, 0, h
->max_packet
- cmd_len
);
252 return icdi_send_packet(handle
, cmd_len
);
255 static int icdi_get_cmd_result(void *handle
)
257 struct icdi_usb_handle_s
*h
;
261 assert(handle
!= NULL
);
262 h
= (struct icdi_usb_handle_s
*)handle
;
265 ch
= h
->read_buffer
[offset
++];
266 if (offset
> h
->read_count
)
270 if (memcmp("OK", h
->read_buffer
+ offset
, 2) == 0)
273 if (h
->read_buffer
[offset
] == 'E') {
276 if (unhexify(&result
, h
->read_buffer
+ offset
+ 1, 1) != 1)
281 /* for now we assume everything else is ok */
285 static int icdi_usb_idcode(void *handle
, uint32_t *idcode
)
290 static int icdi_usb_write_debug_reg(void *handle
, uint32_t addr
, uint32_t val
)
292 return icdi_usb_write_mem(handle
, addr
, 4, 1, (uint8_t *)&val
);
295 static enum target_state
icdi_usb_state(void *handle
)
298 struct icdi_usb_handle_s
*h
;
301 h
= (struct icdi_usb_handle_s
*)handle
;
303 result
= icdi_usb_read_mem(h
, DCB_DHCSR
, 4, 1, (uint8_t *)&dhcsr
);
304 if (result
!= ERROR_OK
)
305 return TARGET_UNKNOWN
;
308 return TARGET_HALTED
;
310 return TARGET_RUNNING
;
313 static int icdi_usb_version(void *handle
)
315 struct icdi_usb_handle_s
*h
;
316 h
= (struct icdi_usb_handle_s
*)handle
;
320 /* get info about icdi */
321 int result
= icdi_send_remote_cmd(handle
, "version");
322 if (result
!= ERROR_OK
)
325 if (h
->read_count
< 8) {
326 LOG_ERROR("Invalid Reply Received");
331 if (unhexify(version
, h
->read_buffer
+ 2, 4) != 4) {
332 LOG_WARNING("unable to get ICDI version");
336 /* null terminate and print info */
339 LOG_INFO("ICDI Firmware version: %s", version
);
344 static int icdi_usb_query(void *handle
)
348 struct icdi_usb_handle_s
*h
;
349 h
= (struct icdi_usb_handle_s
*)handle
;
351 result
= icdi_send_cmd(handle
, "qSupported");
352 if (result
!= ERROR_OK
)
356 result
= icdi_get_cmd_result(handle
);
357 if (result
!= ERROR_OK
) {
358 LOG_ERROR("query supported failed: 0x%x", result
);
362 /* from this we can get the max packet supported */
364 /* query packet buffer size */
365 char *offset
= strstr(h
->read_buffer
, "PacketSize");
370 max_packet
= strtoul(offset
+ 11, &separator
, 16);
372 LOG_ERROR("invalid max packet, using defaults");
374 h
->max_packet
= max_packet
;
375 LOG_DEBUG("max packet supported : %" PRIu32
" bytes", h
->max_packet
);
379 /* if required re allocate packet buffer */
380 if (h
->max_packet
!= ICDI_PACKET_SIZE
) {
381 h
->read_buffer
= realloc(h
->read_buffer
, h
->max_packet
);
382 h
->write_buffer
= realloc(h
->write_buffer
, h
->max_packet
);
383 if (h
->read_buffer
== 0 || h
->write_buffer
== 0) {
384 LOG_ERROR("unable to reallocate memory");
389 /* set extended mode */
390 result
= icdi_send_cmd(handle
, "!");
391 if (result
!= ERROR_OK
)
395 result
= icdi_get_cmd_result(handle
);
396 if (result
!= ERROR_OK
) {
397 LOG_ERROR("unable to enable extended mode: 0x%x", result
);
404 static int icdi_usb_reset(void *handle
)
406 /* we do this in hla_target.c */
410 static int icdi_usb_assert_srst(void *handle
, int srst
)
412 /* TODO not supported yet */
413 return ERROR_COMMAND_NOTFOUND
;
416 static int icdi_usb_run(void *handle
)
420 /* resume target at current address */
421 result
= icdi_send_cmd(handle
, "c");
422 if (result
!= ERROR_OK
)
426 result
= icdi_get_cmd_result(handle
);
427 if (result
!= ERROR_OK
) {
428 LOG_ERROR("continue failed: 0x%x", result
);
435 static int icdi_usb_halt(void *handle
)
439 /* this query halts the target ?? */
440 result
= icdi_send_cmd(handle
, "?");
441 if (result
!= ERROR_OK
)
445 result
= icdi_get_cmd_result(handle
);
446 if (result
!= ERROR_OK
) {
447 LOG_ERROR("halt failed: 0x%x", result
);
454 static int icdi_usb_step(void *handle
)
458 /* step target at current address */
459 result
= icdi_send_cmd(handle
, "s");
460 if (result
!= ERROR_OK
)
464 result
= icdi_get_cmd_result(handle
);
465 if (result
!= ERROR_OK
) {
466 LOG_ERROR("step failed: 0x%x", result
);
473 static int icdi_usb_read_regs(void *handle
)
475 /* currently unsupported */
479 static int icdi_usb_read_reg(void *handle
, int num
, uint32_t *val
)
482 struct icdi_usb_handle_s
*h
;
485 h
= (struct icdi_usb_handle_s
*)handle
;
487 snprintf(cmd
, sizeof(cmd
), "p%x", num
);
488 result
= icdi_send_cmd(handle
, cmd
);
489 if (result
!= ERROR_OK
)
493 result
= icdi_get_cmd_result(handle
);
494 if (result
!= ERROR_OK
) {
495 LOG_ERROR("register read failed: 0x%x", result
);
500 if (unhexify((char *)val
, h
->read_buffer
+ 2, 4) != 4) {
501 LOG_ERROR("failed to convert result");
508 static int icdi_usb_write_reg(void *handle
, int num
, uint32_t val
)
513 int cmd_len
= snprintf(cmd
, sizeof(cmd
), "P%x=", num
);
514 hexify(cmd
+ cmd_len
, (char *)&val
, 4, sizeof(cmd
));
516 result
= icdi_send_cmd(handle
, cmd
);
517 if (result
!= ERROR_OK
)
521 result
= icdi_get_cmd_result(handle
);
522 if (result
!= ERROR_OK
) {
523 LOG_ERROR("register write failed: 0x%x", result
);
530 static int icdi_usb_read_mem_int(void *handle
, uint32_t addr
, uint32_t len
, uint8_t *buffer
)
533 struct icdi_usb_handle_s
*h
;
536 h
= (struct icdi_usb_handle_s
*)handle
;
538 snprintf(cmd
, sizeof(cmd
), "x%x,%x", addr
, len
);
539 result
= icdi_send_cmd(handle
, cmd
);
540 if (result
!= ERROR_OK
)
544 result
= icdi_get_cmd_result(handle
);
545 if (result
!= ERROR_OK
) {
546 LOG_ERROR("memory read failed: 0x%x", result
);
551 int read_len
= remote_unescape_input(h
->read_buffer
+ 5, h
->read_count
- 8, (char *)buffer
, len
);
552 if (read_len
!= (int)len
) {
553 LOG_ERROR("read more bytes than expected: actual 0x%" PRIx32
" expected 0x%" PRIx32
, read_len
, len
);
560 static int icdi_usb_write_mem_int(void *handle
, uint32_t addr
, uint32_t len
, const uint8_t *buffer
)
563 struct icdi_usb_handle_s
*h
;
565 h
= (struct icdi_usb_handle_s
*)handle
;
567 size_t cmd_len
= snprintf(h
->write_buffer
, h
->max_packet
, PACKET_START
"X%x,%x:", addr
, len
);
570 cmd_len
+= remote_escape_output((char *)buffer
, len
, h
->write_buffer
+ cmd_len
,
571 &out_len
, h
->max_packet
- cmd_len
);
573 if (out_len
< (int)len
) {
574 /* for now issue a error as we have no way of allocating a larger buffer */
575 LOG_ERROR("memory buffer too small: requires 0x%" PRIx32
" actual 0x%" PRIx32
, out_len
, len
);
579 result
= icdi_send_packet(handle
, cmd_len
);
580 if (result
!= ERROR_OK
)
584 result
= icdi_get_cmd_result(handle
);
585 if (result
!= ERROR_OK
) {
586 LOG_ERROR("memory write failed: 0x%x", result
);
593 static int icdi_usb_read_mem(void *handle
, uint32_t addr
, uint32_t size
,
594 uint32_t count
, uint8_t *buffer
)
596 int retval
= ERROR_OK
;
597 struct icdi_usb_handle_s
*h
= (struct icdi_usb_handle_s
*)handle
;
598 uint32_t bytes_remaining
;
600 /* calculate byte count */
605 bytes_remaining
= h
->max_rw_packet
;
606 if (count
< bytes_remaining
)
607 bytes_remaining
= count
;
609 retval
= icdi_usb_read_mem_int(handle
, addr
, bytes_remaining
, buffer
);
610 if (retval
!= ERROR_OK
)
613 buffer
+= bytes_remaining
;
614 addr
+= bytes_remaining
;
615 count
-= bytes_remaining
;
621 static int icdi_usb_write_mem(void *handle
, uint32_t addr
, uint32_t size
,
622 uint32_t count
, const uint8_t *buffer
)
624 int retval
= ERROR_OK
;
625 struct icdi_usb_handle_s
*h
= (struct icdi_usb_handle_s
*)handle
;
626 uint32_t bytes_remaining
;
628 /* calculate byte count */
633 bytes_remaining
= h
->max_rw_packet
;
634 if (count
< bytes_remaining
)
635 bytes_remaining
= count
;
637 retval
= icdi_usb_write_mem_int(handle
, addr
, bytes_remaining
, buffer
);
638 if (retval
!= ERROR_OK
)
641 buffer
+= bytes_remaining
;
642 addr
+= bytes_remaining
;
643 count
-= bytes_remaining
;
649 static int icdi_usb_close(void *handle
)
651 struct icdi_usb_handle_s
*h
;
653 h
= (struct icdi_usb_handle_s
*)handle
;
656 libusb_close(h
->usb_dev
);
659 libusb_exit(h
->usb_ctx
);
662 free(h
->read_buffer
);
665 free(h
->write_buffer
);
672 static int icdi_usb_open(struct hl_interface_param_s
*param
, void **fd
)
675 struct icdi_usb_handle_s
*h
;
677 LOG_DEBUG("icdi_usb_open");
679 h
= calloc(1, sizeof(struct icdi_usb_handle_s
));
682 LOG_ERROR("unable to allocate memory");
686 LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param
->transport
,
687 param
->vid
, param
->pid
);
689 if (libusb_init(&h
->usb_ctx
) != 0) {
690 LOG_ERROR("libusb init failed");
694 h
->usb_dev
= libusb_open_device_with_vid_pid(h
->usb_ctx
, param
->vid
, param
->pid
);
696 LOG_ERROR("open failed");
700 if (libusb_claim_interface(h
->usb_dev
, 2)) {
701 LOG_DEBUG("claim interface failed");
705 /* check if mode is supported */
708 switch (param
->transport
) {
710 /* TODO place holder as swd is not currently supported */
711 case HL_TRANSPORT_SWD
:
713 case HL_TRANSPORT_JTAG
:
720 if (retval
!= ERROR_OK
) {
721 LOG_ERROR("mode (transport) not supported by device");
725 /* allocate buffer */
726 h
->read_buffer
= malloc(ICDI_PACKET_SIZE
);
727 h
->write_buffer
= malloc(ICDI_PACKET_SIZE
);
728 h
->max_packet
= ICDI_PACKET_SIZE
;
730 if (h
->read_buffer
== 0 || h
->write_buffer
== 0) {
731 LOG_DEBUG("malloc failed");
735 /* query icdi version etc */
736 retval
= icdi_usb_version(h
);
737 if (retval
!= ERROR_OK
)
740 /* query icdi support */
741 retval
= icdi_usb_query(h
);
742 if (retval
!= ERROR_OK
)
747 /* set the max target read/write buffer in bytes
748 * as we are using gdb binary packets to transfer memory we have to
749 * reserve half the buffer for any possible escape chars plus
750 * at least 64 bytes for the gdb packet header */
751 h
->max_rw_packet
= (((h
->max_packet
- 64) / 4) * 4) / 2;
761 struct hl_layout_api_s icdi_usb_layout_api
= {
762 .open
= icdi_usb_open
,
763 .close
= icdi_usb_close
,
764 .idcode
= icdi_usb_idcode
,
765 .state
= icdi_usb_state
,
766 .reset
= icdi_usb_reset
,
767 .assert_srst
= icdi_usb_assert_srst
,
769 .halt
= icdi_usb_halt
,
770 .step
= icdi_usb_step
,
771 .read_regs
= icdi_usb_read_regs
,
772 .read_reg
= icdi_usb_read_reg
,
773 .write_reg
= icdi_usb_write_reg
,
774 .read_mem
= icdi_usb_read_mem
,
775 .write_mem
= icdi_usb_write_mem
,
776 .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)