target: Do not use LOG_USER() for error messages
[openocd.git] / src / jtag / drivers / nulink_usb.c
blob4fdb85782787d3a9b80dd5d963bde94fdbafa9ad
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2016-2017 by Nuvoton *
5 * Zale Yu <cyyu@nuvoton.com> *
6 ***************************************************************************/
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
12 /* project specific includes */
13 #include <helper/binarybuffer.h>
14 #include <jtag/adapter.h>
15 #include <jtag/interface.h>
16 #include <jtag/hla/hla_layout.h>
17 #include <jtag/hla/hla_transport.h>
18 #include <jtag/hla/hla_interface.h>
19 #include <target/target.h>
21 #include <target/cortex_m.h>
23 #include <hidapi.h>
25 #include "libusb_helper.h"
27 #define NULINK_READ_TIMEOUT LIBUSB_TIMEOUT_MS
29 #define NULINK_HID_MAX_SIZE (64)
30 #define NULINK2_HID_MAX_SIZE (1024)
31 #define V6M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 2)
32 #define V7M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 3)
34 #define NULINK2_USB_PID1 (0x5200)
35 #define NULINK2_USB_PID2 (0x5201)
37 struct nulink_usb_handle_s {
38 hid_device *dev_handle;
39 uint16_t max_packet_size;
40 uint8_t usbcmdidx;
41 uint8_t cmdidx;
42 uint8_t cmdsize;
43 uint8_t cmdbuf[NULINK2_HID_MAX_SIZE + 1];
44 uint8_t tempbuf[NULINK2_HID_MAX_SIZE];
45 uint8_t databuf[NULINK2_HID_MAX_SIZE];
46 uint32_t max_mem_packet;
47 uint16_t hardware_config; /* bit 0: 1:Nu-Link-Pro, 0:Nu-Link */
49 int (*xfer)(void *handle, uint8_t *buf, int size);
50 void (*init_buffer)(void *handle, uint32_t size);
53 /* ICE Command */
54 #define CMD_READ_REG 0xB5UL
55 #define CMD_READ_RAM 0xB1UL
56 #define CMD_WRITE_REG 0xB8UL
57 #define CMD_WRITE_RAM 0xB9UL
58 #define CMD_CHECK_ID 0xA3UL
59 #define CMD_MCU_RESET 0xE2UL
60 #define CMD_CHECK_MCU_STOP 0xD8UL
61 #define CMD_MCU_STEP_RUN 0xD1UL
62 #define CMD_MCU_STOP_RUN 0xD2UL
63 #define CMD_MCU_FREE_RUN 0xD3UL
64 #define CMD_SET_CONFIG 0xA2UL
66 #define ARM_SRAM_BASE 0x20000000UL
68 #define HARDWARE_CONFIG_NULINKPRO 1
69 #define HARDWARE_CONFIG_NULINK2 2
71 enum nulink_reset {
72 RESET_AUTO = 0,
73 RESET_HW = 1,
74 RESET_SYSRESETREQ = 2,
75 RESET_VECTRESET = 3,
76 RESET_FAST_RESCUE = 4, /* Rescue and erase the chip, need very fast speed */
79 enum nulink_connect {
80 CONNECT_NORMAL = 0, /* Support all reset method */
81 CONNECT_PRE_RESET = 1, /* Support all reset method */
82 CONNECT_UNDER_RESET = 2, /* Support all reset method */
83 CONNECT_NONE = 3, /* Support RESET_HW, (RESET_AUTO = RESET_HW) */
84 CONNECT_DISCONNECT = 4, /* Support RESET_NONE, (RESET_AUTO = RESET_NONE) */
85 CONNECT_ICP_MODE = 5 /* Support NUC505 ICP mode*/
88 static int nulink_usb_xfer_rw(void *handle, uint8_t *buf)
90 struct nulink_usb_handle_s *h = handle;
92 assert(handle);
94 int ret = hid_write(h->dev_handle, h->cmdbuf, h->max_packet_size + 1);
95 if (ret < 0) {
96 LOG_ERROR("hid_write");
97 return ERROR_FAIL;
100 ret = hid_read_timeout(h->dev_handle, buf, h->max_packet_size, NULINK_READ_TIMEOUT);
101 if (ret < 0) {
102 LOG_ERROR("hid_read_timeout");
103 return ERROR_FAIL;
105 return ERROR_OK;
108 static int nulink1_usb_xfer(void *handle, uint8_t *buf, int size)
110 struct nulink_usb_handle_s *h = handle;
112 assert(handle);
114 int err = nulink_usb_xfer_rw(h, h->tempbuf);
116 memcpy(buf, h->tempbuf + 2, V6M_MAX_COMMAND_LENGTH);
118 return err;
121 static int nulink2_usb_xfer(void *handle, uint8_t *buf, int size)
123 struct nulink_usb_handle_s *h = handle;
125 assert(handle);
127 int err = nulink_usb_xfer_rw(h, h->tempbuf);
129 memcpy(buf, h->tempbuf + 3, V7M_MAX_COMMAND_LENGTH);
131 return err;
134 static void nulink1_usb_init_buffer(void *handle, uint32_t size)
136 struct nulink_usb_handle_s *h = handle;
138 h->cmdidx = 0;
140 memset(h->cmdbuf, 0, h->max_packet_size + 1);
141 memset(h->tempbuf, 0, h->max_packet_size);
142 memset(h->databuf, 0, h->max_packet_size);
144 h->cmdbuf[0] = 0; /* report number */
145 h->cmdbuf[1] = ++h->usbcmdidx & 0x7F;
146 h->cmdbuf[2] = size;
147 h->cmdidx += 3;
150 static void nulink2_usb_init_buffer(void *handle, uint32_t size)
152 struct nulink_usb_handle_s *h = handle;
154 h->cmdidx = 0;
156 memset(h->cmdbuf, 0, h->max_packet_size + 1);
157 memset(h->tempbuf, 0, h->max_packet_size);
158 memset(h->databuf, 0, h->max_packet_size);
160 h->cmdbuf[0] = 0; /* report number */
161 h->cmdbuf[1] = ++h->usbcmdidx & 0x7F;
162 h_u16_to_le(h->cmdbuf + 2, size);
163 h->cmdidx += 4;
166 static inline int nulink_usb_xfer(void *handle, uint8_t *buf, int size)
168 struct nulink_usb_handle_s *h = handle;
170 assert(handle);
172 return h->xfer(handle, buf, size);
175 static inline void nulink_usb_init_buffer(void *handle, uint32_t size)
177 struct nulink_usb_handle_s *h = handle;
179 assert(handle);
181 h->init_buffer(handle, size);
184 static int nulink_usb_version(void *handle)
186 struct nulink_usb_handle_s *h = handle;
188 LOG_DEBUG("nulink_usb_version");
190 assert(handle);
192 nulink_usb_init_buffer(handle, V6M_MAX_COMMAND_LENGTH);
194 memset(h->cmdbuf + h->cmdidx, 0xFF, V6M_MAX_COMMAND_LENGTH);
195 h->cmdbuf[h->cmdidx + 4] = 0xA1; /* host_rev_num: 6561 */;
196 h->cmdbuf[h->cmdidx + 5] = 0x19;
198 int res = nulink_usb_xfer(handle, h->databuf, h->cmdsize);
199 if (res != ERROR_OK)
200 return res;
202 LOG_INFO("Nu-Link firmware_version %" PRIu32 ", product_id (0x%08" PRIx32 ")",
203 le_to_h_u32(h->databuf),
204 le_to_h_u32(h->databuf + 4 * 1));
206 const bool is_nulinkpro = !!(le_to_h_u32(h->databuf + 4 * 2) & 1);
207 if (is_nulinkpro) {
208 LOG_INFO("Adapter is Nu-Link-Pro, target_voltage_mv(%" PRIu16 "), usb_voltage_mv(%" PRIu16 ")",
209 le_to_h_u16(h->databuf + 4 * 3 + 0),
210 le_to_h_u16(h->databuf + 4 * 3 + 2));
212 h->hardware_config |= HARDWARE_CONFIG_NULINKPRO;
213 } else {
214 LOG_INFO("Adapter is Nu-Link");
217 return ERROR_OK;
220 static int nulink_usb_idcode(void *handle, uint32_t *idcode)
222 struct nulink_usb_handle_s *h = handle;
224 LOG_DEBUG("nulink_usb_idcode");
226 assert(handle);
228 nulink_usb_init_buffer(handle, 4 * 1);
229 /* set command ID */
230 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_CHECK_ID);
231 h->cmdidx += 4;
233 int res = nulink_usb_xfer(handle, h->databuf, 4 * 2);
234 if (res != ERROR_OK)
235 return res;
237 *idcode = le_to_h_u32(h->databuf + 4 * 1);
239 LOG_INFO("IDCODE: 0x%08" PRIX32, *idcode);
241 return ERROR_OK;
244 static int nulink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
246 struct nulink_usb_handle_s *h = handle;
248 LOG_DEBUG("nulink_usb_write_debug_reg 0x%08" PRIX32 " 0x%08" PRIX32, addr, val);
250 nulink_usb_init_buffer(handle, 8 + 12 * 1);
251 /* set command ID */
252 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
253 h->cmdidx += 4;
254 /* Count of registers */
255 h->cmdbuf[h->cmdidx] = 1;
256 h->cmdidx += 1;
257 /* Array of bool value (u8ReadOld) */
258 h->cmdbuf[h->cmdidx] = 0x00;
259 h->cmdidx += 1;
260 /* Array of bool value (u8Verify) */
261 h->cmdbuf[h->cmdidx] = 0x00;
262 h->cmdidx += 1;
263 /* ignore */
264 h->cmdbuf[h->cmdidx] = 0;
265 h->cmdidx += 1;
266 /* u32Addr */
267 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
268 h->cmdidx += 4;
269 /* u32Data */
270 h_u32_to_le(h->cmdbuf + h->cmdidx, val);
271 h->cmdidx += 4;
272 /* u32Mask */
273 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
274 h->cmdidx += 4;
276 return nulink_usb_xfer(handle, h->databuf, 4 * 2);
279 static enum target_state nulink_usb_state(void *handle)
281 struct nulink_usb_handle_s *h = handle;
283 assert(handle);
285 nulink_usb_init_buffer(handle, 4 * 1);
286 /* set command ID */
287 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_CHECK_MCU_STOP);
288 h->cmdidx += 4;
290 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
291 if (res != ERROR_OK)
292 return TARGET_UNKNOWN;
294 if (!le_to_h_u32(h->databuf + 4 * 2))
295 return TARGET_HALTED;
296 else
297 return TARGET_RUNNING;
300 static int nulink_usb_assert_srst(void *handle, int srst)
302 struct nulink_usb_handle_s *h = handle;
304 LOG_DEBUG("nulink_usb_assert_srst");
306 assert(handle);
308 nulink_usb_init_buffer(handle, 4 * 4);
309 /* set command ID */
310 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_RESET);
311 h->cmdidx += 4;
312 /* set reset type */
313 h_u32_to_le(h->cmdbuf + h->cmdidx, RESET_SYSRESETREQ);
314 h->cmdidx += 4;
315 /* set connect type */
316 h_u32_to_le(h->cmdbuf + h->cmdidx, CONNECT_NORMAL);
317 h->cmdidx += 4;
318 /* set extMode */
319 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
320 h->cmdidx += 4;
322 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
325 static int nulink_usb_reset(void *handle)
327 struct nulink_usb_handle_s *h = handle;
329 LOG_DEBUG("nulink_usb_reset");
331 assert(handle);
333 nulink_usb_init_buffer(handle, 4 * 4);
334 /* set command ID */
335 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_RESET);
336 h->cmdidx += 4;
337 /* set reset type */
338 h_u32_to_le(h->cmdbuf + h->cmdidx, RESET_HW);
339 h->cmdidx += 4;
340 /* set connect type */
341 h_u32_to_le(h->cmdbuf + h->cmdidx, CONNECT_NORMAL);
342 h->cmdidx += 4;
343 /* set extMode */
344 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
345 h->cmdidx += 4;
347 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
350 static int nulink_usb_run(void *handle)
352 struct nulink_usb_handle_s *h = handle;
354 LOG_DEBUG("nulink_usb_run");
356 assert(handle);
358 nulink_usb_init_buffer(handle, 4 * 1);
359 /* set command ID */
360 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_FREE_RUN);
361 h->cmdidx += 4;
363 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
366 static int nulink_usb_halt(void *handle)
368 struct nulink_usb_handle_s *h = handle;
370 LOG_DEBUG("nulink_usb_halt");
372 assert(handle);
374 nulink_usb_init_buffer(handle, 4 * 1);
375 /* set command ID */
376 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_STOP_RUN);
377 h->cmdidx += 4;
379 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
381 LOG_DEBUG("Nu-Link stop_pc 0x%08" PRIx32, le_to_h_u32(h->databuf + 4));
383 return res;
386 static int nulink_usb_step(void *handle)
388 struct nulink_usb_handle_s *h = handle;
390 LOG_DEBUG("nulink_usb_step");
392 assert(handle);
394 nulink_usb_init_buffer(handle, 4 * 1);
395 /* set command ID */
396 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_STEP_RUN);
397 h->cmdidx += 4;
399 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
401 LOG_DEBUG("Nu-Link pc 0x%08" PRIx32, le_to_h_u32(h->databuf + 4));
403 return res;
406 static int nulink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val)
408 struct nulink_usb_handle_s *h = handle;
410 assert(handle);
412 nulink_usb_init_buffer(handle, 8 + 12 * 1);
413 /* set command ID */
414 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_REG);
415 h->cmdidx += 4;
416 /* Count of registers */
417 h->cmdbuf[h->cmdidx] = 1;
418 h->cmdidx += 1;
419 /* Array of bool value (u8ReadOld) */
420 h->cmdbuf[h->cmdidx] = 0xFF;
421 h->cmdidx += 1;
422 /* Array of bool value (u8Verify) */
423 h->cmdbuf[h->cmdidx] = 0x00;
424 h->cmdidx += 1;
425 /* ignore */
426 h->cmdbuf[h->cmdidx] = 0;
427 h->cmdidx += 1;
428 /* u32Addr */
429 h_u32_to_le(h->cmdbuf + h->cmdidx, regsel);
430 h->cmdidx += 4;
431 /* u32Data */
432 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
433 h->cmdidx += 4;
434 /* u32Mask */
435 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
436 h->cmdidx += 4;
438 int res = nulink_usb_xfer(handle, h->databuf, 4 * 2);
440 *val = le_to_h_u32(h->databuf + 4 * 1);
442 return res;
445 static int nulink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val)
447 struct nulink_usb_handle_s *h = handle;
449 assert(handle);
451 nulink_usb_init_buffer(handle, 8 + 12 * 1);
452 /* set command ID */
453 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_REG);
454 h->cmdidx += 4;
455 /* Count of registers */
456 h->cmdbuf[h->cmdidx] = 1;
457 h->cmdidx += 1;
458 /* Array of bool value (u8ReadOld) */
459 h->cmdbuf[h->cmdidx] = 0x00;
460 h->cmdidx += 1;
461 /* Array of bool value (u8Verify) */
462 h->cmdbuf[h->cmdidx] = 0x00;
463 h->cmdidx += 1;
464 /* ignore */
465 h->cmdbuf[h->cmdidx] = 0;
466 h->cmdidx += 1;
467 /* u32Addr */
468 h_u32_to_le(h->cmdbuf + h->cmdidx, regsel);
469 h->cmdidx += 4;
470 /* u32Data */
471 h_u32_to_le(h->cmdbuf + h->cmdidx, val);
472 h->cmdidx += 4;
473 /* u32Mask */
474 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
475 h->cmdidx += 4;
477 return nulink_usb_xfer(handle, h->databuf, 4 * 2);
480 static int nulink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len,
481 uint8_t *buffer)
483 int res = ERROR_OK;
484 uint32_t offset = 0;
485 uint32_t bytes_remaining = 12;
486 struct nulink_usb_handle_s *h = handle;
488 LOG_DEBUG("nulink_usb_read_mem8: addr 0x%08" PRIx32 ", len %" PRId16, addr, len);
490 assert(handle);
492 /* check whether data is word aligned */
493 if (addr % 4) {
494 uint32_t aligned_addr = addr / 4;
495 aligned_addr = aligned_addr * 4;
496 offset = addr - aligned_addr;
497 LOG_DEBUG("nulink_usb_read_mem8: unaligned address addr 0x%08" PRIx32
498 "/aligned addr 0x%08" PRIx32 " offset %" PRIu32,
499 addr, aligned_addr, offset);
501 addr = aligned_addr;
504 while (len) {
505 unsigned int count;
507 if (len < bytes_remaining)
508 bytes_remaining = len;
510 if (len < 4)
511 count = 1;
512 else
513 count = 2;
515 nulink_usb_init_buffer(handle, 8 + 12 * count);
516 /* set command ID */
517 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
518 h->cmdidx += 4;
519 /* Count of registers */
520 h->cmdbuf[h->cmdidx] = count;
521 h->cmdidx += 1;
522 /* Array of bool value (u8ReadOld) */
523 h->cmdbuf[h->cmdidx] = 0xFF;
524 h->cmdidx += 1;
525 /* Array of bool value (u8Verify) */
526 h->cmdbuf[h->cmdidx] = 0x00;
527 h->cmdidx += 1;
528 /* ignore */
529 h->cmdbuf[h->cmdidx] = 0;
530 h->cmdidx += 1;
532 for (unsigned int i = 0; i < count; i++) {
533 /* u32Addr */
534 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
535 h->cmdidx += 4;
536 /* u32Data */
537 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
538 h->cmdidx += 4;
539 /* u32Mask */
540 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
541 h->cmdidx += 4;
542 /* proceed to the next one */
543 addr += 4;
546 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
547 if (res != ERROR_OK)
548 break;
550 /* fill in the output buffer */
551 for (unsigned int i = 0; i < count; i++) {
552 if (i == 0)
553 memcpy(buffer, h->databuf + 4 + offset, len);
554 else
555 memcpy(buffer + 2 * i, h->databuf + 4 * (2 * i + 1), len - 2);
558 if (len >= bytes_remaining)
559 len -= bytes_remaining;
562 return res;
565 static int nulink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len,
566 const uint8_t *buffer)
568 int res = ERROR_OK;
569 uint32_t offset = 0;
570 uint32_t bytes_remaining = 12;
571 struct nulink_usb_handle_s *h = handle;
573 LOG_DEBUG("nulink_usb_write_mem8: addr 0x%08" PRIx32 ", len %" PRIu16, addr, len);
575 assert(handle);
577 /* check whether data is word aligned */
578 if (addr % 4) {
579 uint32_t aligned_addr = addr / 4;
580 aligned_addr = aligned_addr * 4;
581 offset = addr - aligned_addr;
582 LOG_DEBUG("nulink_usb_write_mem8: address not aligned. addr(0x%08" PRIx32
583 ")/aligned_addr(0x%08" PRIx32 ")/offset(%" PRIu32 ")",
584 addr, aligned_addr, offset);
586 addr = aligned_addr;
589 while (len) {
590 unsigned int count;
592 if (len < bytes_remaining)
593 bytes_remaining = len;
595 if (len < 4)
596 count = 1;
597 else
598 count = 2;
600 nulink_usb_init_buffer(handle, 8 + 12 * count);
601 /* set command ID */
602 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
603 h->cmdidx += 4;
604 /* Count of registers */
605 h->cmdbuf[h->cmdidx] = count;
606 h->cmdidx += 1;
607 /* Array of bool value (u8ReadOld) */
608 h->cmdbuf[h->cmdidx] = 0x00;
609 h->cmdidx += 1;
610 /* Array of bool value (u8Verify) */
611 h->cmdbuf[h->cmdidx] = 0x00;
612 h->cmdidx += 1;
613 /* ignore */
614 h->cmdbuf[h->cmdidx] = 0;
615 h->cmdidx += 1;
617 for (unsigned int i = 0; i < count; i++) {
618 /* u32Addr */
619 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
620 h->cmdidx += 4;
621 /* u32Data */
622 uint32_t u32buffer = buf_get_u32(buffer, 0, len * 8);
623 u32buffer = (u32buffer << offset * 8);
624 h_u32_to_le(h->cmdbuf + h->cmdidx, u32buffer);
625 h->cmdidx += 4;
626 /* u32Mask */
627 if (i == 0) {
628 if (offset == 0) {
629 if (len == 1) {
630 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFF00UL);
631 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFFFF00", i);
632 } else {
633 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFF0000UL);
634 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFF0000", i);
636 } else {
637 if (len == 1) {
638 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFF00FFFFUL);
639 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFF00FFFF", i);
641 } else {
642 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x0000FFFFUL);
643 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x0000FFFF", i);
646 } else {
647 if (len == 4) {
648 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFF0000UL);
649 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFF0000", i);
650 } else {
651 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
652 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x00000000", i);
655 h->cmdidx += 4;
657 /* proceed to the next one */
658 addr += 4;
659 buffer += 4;
662 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
663 if (res != ERROR_OK)
664 break;
666 if (len >= bytes_remaining)
667 len -= bytes_remaining;
670 return res;
673 static int nulink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
674 uint8_t *buffer)
676 int res = ERROR_OK;
677 uint32_t bytes_remaining = 12;
678 struct nulink_usb_handle_s *h = handle;
680 assert(handle);
682 /* data must be a multiple of 4 and word aligned */
683 if (len % 4 || addr % 4) {
684 LOG_ERROR("Invalid data alignment");
685 return ERROR_TARGET_UNALIGNED_ACCESS;
688 while (len) {
689 if (len < bytes_remaining)
690 bytes_remaining = len;
692 unsigned int count = bytes_remaining / 4;
694 nulink_usb_init_buffer(handle, 8 + 12 * count);
695 /* set command ID */
696 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
697 h->cmdidx += 4;
698 /* Count of registers */
699 h->cmdbuf[h->cmdidx] = count;
700 h->cmdidx += 1;
701 /* Array of bool value (u8ReadOld) */
702 h->cmdbuf[h->cmdidx] = 0xFF;
703 h->cmdidx += 1;
704 /* Array of bool value (u8Verify) */
705 h->cmdbuf[h->cmdidx] = 0x00;
706 h->cmdidx += 1;
707 /* ignore */
708 h->cmdbuf[h->cmdidx] = 0;
709 h->cmdidx += 1;
711 for (unsigned int i = 0; i < count; i++) {
712 /* u32Addr */
713 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
714 h->cmdidx += 4;
715 /* u32Data */
716 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
717 h->cmdidx += 4;
718 /* u32Mask */
719 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
720 h->cmdidx += 4;
721 /* proceed to the next one */
722 addr += 4;
725 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
727 /* fill in the output buffer */
728 for (unsigned int i = 0; i < count; i++) {
729 memcpy(buffer, h->databuf + 4 * (2 * i + 1), 4);
730 buffer += 4;
733 if (len >= bytes_remaining)
734 len -= bytes_remaining;
735 else
736 len = 0;
739 return res;
742 static int nulink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
743 const uint8_t *buffer)
745 int res = ERROR_OK;
746 uint32_t bytes_remaining = 12;
747 struct nulink_usb_handle_s *h = handle;
749 assert(handle);
751 /* data must be a multiple of 4 and word aligned */
752 if (len % 4 || addr % 4) {
753 LOG_ERROR("Invalid data alignment");
754 return ERROR_TARGET_UNALIGNED_ACCESS;
757 while (len) {
758 if (len < bytes_remaining)
759 bytes_remaining = len;
761 unsigned int count = bytes_remaining / 4;
763 nulink_usb_init_buffer(handle, 8 + 12 * count);
764 /* set command ID */
765 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
766 h->cmdidx += 4;
767 /* Count of registers */
768 h->cmdbuf[h->cmdidx] = count;
769 h->cmdidx += 1;
770 /* Array of bool value (u8ReadOld) */
771 h->cmdbuf[h->cmdidx] = 0x00;
772 h->cmdidx += 1;
773 /* Array of bool value (u8Verify) */
774 h->cmdbuf[h->cmdidx] = 0x00;
775 h->cmdidx += 1;
776 /* ignore */
777 h->cmdbuf[h->cmdidx] = 0;
778 h->cmdidx += 1;
780 for (unsigned int i = 0; i < count; i++) {
781 /* u32Addr */
782 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
783 h->cmdidx += 4;
784 /* u32Data */
785 uint32_t u32buffer = buf_get_u32(buffer, 0, 32);
786 h_u32_to_le(h->cmdbuf + h->cmdidx, u32buffer);
787 h->cmdidx += 4;
788 /* u32Mask */
789 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000);
790 h->cmdidx += 4;
792 /* proceed to the next one */
793 addr += 4;
794 buffer += 4;
797 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
799 if (len >= bytes_remaining)
800 len -= bytes_remaining;
801 else
802 len = 0;
805 return res;
808 static uint32_t nulink_max_block_size(uint32_t tar_autoincr_block, uint32_t address)
810 uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address));
812 if (max_tar_block == 0)
813 max_tar_block = 4;
815 return max_tar_block;
818 static int nulink_usb_read_mem(void *handle, uint32_t addr, uint32_t size,
819 uint32_t count, uint8_t *buffer)
821 int retval = ERROR_OK;
822 struct nulink_usb_handle_s *h = handle;
824 /* calculate byte count */
825 count *= size;
827 while (count) {
828 uint32_t bytes_remaining = nulink_max_block_size(h->max_mem_packet, addr);
830 if (count < bytes_remaining)
831 bytes_remaining = count;
833 if (bytes_remaining >= 4)
834 size = 4;
836 /* the nulink only supports 8/32bit memory read/writes
837 * honour 32bit, all others will be handled as 8bit access */
838 if (size == 4) {
839 /* When in jtag mode the nulink uses the auto-increment functionality.
840 * However it expects us to pass the data correctly, this includes
841 * alignment and any page boundaries. We already do this as part of the
842 * adi_v5 implementation, but the nulink is a hla adapter and so this
843 * needs implementing manually.
844 * currently this only affects jtag mode, they do single
845 * access in SWD mode - but this may change and so we do it for both modes */
847 /* we first need to check for any unaligned bytes */
848 if (addr % 4) {
849 uint32_t head_bytes = 4 - (addr % 4);
850 retval = nulink_usb_read_mem8(handle, addr, head_bytes, buffer);
851 if (retval != ERROR_OK)
852 return retval;
853 buffer += head_bytes;
854 addr += head_bytes;
855 count -= head_bytes;
856 bytes_remaining -= head_bytes;
859 if (bytes_remaining % 4)
860 retval = nulink_usb_read_mem(handle, addr, 1, bytes_remaining, buffer);
861 else
862 retval = nulink_usb_read_mem32(handle, addr, bytes_remaining, buffer);
863 } else {
864 retval = nulink_usb_read_mem8(handle, addr, bytes_remaining, buffer);
867 if (retval != ERROR_OK)
868 return retval;
870 buffer += bytes_remaining;
871 addr += bytes_remaining;
872 count -= bytes_remaining;
875 return retval;
878 static int nulink_usb_write_mem(void *handle, uint32_t addr, uint32_t size,
879 uint32_t count, const uint8_t *buffer)
881 int retval = ERROR_OK;
882 struct nulink_usb_handle_s *h = handle;
884 if (addr < ARM_SRAM_BASE) {
885 LOG_DEBUG("nulink_usb_write_mem: address below ARM_SRAM_BASE, not supported.\n");
886 return retval;
889 /* calculate byte count */
890 count *= size;
892 while (count) {
893 uint32_t bytes_remaining = nulink_max_block_size(h->max_mem_packet, addr);
895 if (count < bytes_remaining)
896 bytes_remaining = count;
898 if (bytes_remaining >= 4)
899 size = 4;
901 /* the nulink only supports 8/32bit memory read/writes
902 * honour 32bit, all others will be handled as 8bit access */
903 if (size == 4) {
904 /* When in jtag mode the nulink uses the auto-increment functionality.
905 * However it expects us to pass the data correctly, this includes
906 * alignment and any page boundaries. We already do this as part of the
907 * adi_v5 implementation, but the nulink is a hla adapter and so this
908 * needs implementing manually.
909 * currently this only affects jtag mode, do single
910 * access in SWD mode - but this may change and so we do it for both modes */
912 /* we first need to check for any unaligned bytes */
913 if (addr % 4) {
914 uint32_t head_bytes = 4 - (addr % 4);
915 retval = nulink_usb_write_mem8(handle, addr, head_bytes, buffer);
916 if (retval != ERROR_OK)
917 return retval;
918 buffer += head_bytes;
919 addr += head_bytes;
920 count -= head_bytes;
921 bytes_remaining -= head_bytes;
924 if (bytes_remaining % 4)
925 retval = nulink_usb_write_mem(handle, addr, 1, bytes_remaining, buffer);
926 else
927 retval = nulink_usb_write_mem32(handle, addr, bytes_remaining, buffer);
929 } else {
930 retval = nulink_usb_write_mem8(handle, addr, bytes_remaining, buffer);
933 if (retval != ERROR_OK)
934 return retval;
936 buffer += bytes_remaining;
937 addr += bytes_remaining;
938 count -= bytes_remaining;
941 return retval;
944 static int nulink_usb_override_target(const char *targetname)
946 LOG_DEBUG("nulink_usb_override_target");
948 return !strcmp(targetname, "cortex_m");
951 static int nulink_speed(void *handle, int khz, bool query)
953 struct nulink_usb_handle_s *h = handle;
954 unsigned long max_ice_clock = khz;
956 LOG_DEBUG("nulink_speed: query %s", query ? "yes" : "no");
958 if (max_ice_clock > 12000)
959 max_ice_clock = 12000;
960 else if ((max_ice_clock == 3 * 512) || (max_ice_clock == 1500))
961 max_ice_clock = 1500;
962 else if (max_ice_clock >= 1000)
963 max_ice_clock = max_ice_clock / 1000 * 1000;
964 else
965 max_ice_clock = max_ice_clock / 100 * 100;
967 LOG_DEBUG("Nu-Link nulink_speed: %lu", max_ice_clock);
969 if (!query) {
970 nulink_usb_init_buffer(handle, 4 * 6);
971 /* set command ID */
972 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_SET_CONFIG);
973 h->cmdidx += 4;
974 /* set max SWD clock */
975 h_u32_to_le(h->cmdbuf + h->cmdidx, max_ice_clock);
976 h->cmdidx += 4;
977 /* chip type: NUC_CHIP_TYPE_GENERAL_V6M */
978 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
979 h->cmdidx += 4;
980 /* IO voltage */
981 h_u32_to_le(h->cmdbuf + h->cmdidx, 5000);
982 h->cmdidx += 4;
983 /* If supply voltage to target or not */
984 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
985 h->cmdidx += 4;
986 /* USB_FUNC_E: USB_FUNC_HID_BULK */
987 h_u32_to_le(h->cmdbuf + h->cmdidx, 2);
988 h->cmdidx += 4;
990 nulink_usb_xfer(handle, h->databuf, 4 * 3);
992 LOG_DEBUG("nulink_speed: h->hardware_config(%" PRId16 ")", h->hardware_config);
993 if (h->hardware_config & HARDWARE_CONFIG_NULINKPRO)
994 LOG_INFO("Nu-Link target_voltage_mv[0](%04" PRIx16 "), target_voltage_mv[1](%04" PRIx16
995 "), target_voltage_mv[2](%04" PRIx16 "), if_target_power_supplied(%d)",
996 le_to_h_u16(h->databuf + 4 * 1 + 0),
997 le_to_h_u16(h->databuf + 4 * 1 + 2),
998 le_to_h_u16(h->databuf + 4 * 2 + 0),
999 le_to_h_u16(h->databuf + 4 * 2 + 2) & 1);
1002 return max_ice_clock;
1005 static int nulink_usb_close(void *handle)
1007 struct nulink_usb_handle_s *h = handle;
1009 LOG_DEBUG("nulink_usb_close");
1011 if (h && h->dev_handle)
1012 hid_close(h->dev_handle);
1014 free(h);
1016 hid_exit();
1018 return ERROR_OK;
1021 static int nulink_usb_open(struct hl_interface_param_s *param, void **fd)
1023 struct hid_device_info *devs, *cur_dev;
1024 uint16_t target_vid = 0;
1025 uint16_t target_pid = 0;
1026 wchar_t *target_serial = NULL;
1028 LOG_DEBUG("nulink_usb_open");
1030 if (param->transport != HL_TRANSPORT_SWD)
1031 return TARGET_UNKNOWN;
1033 if (!param->vid[0] && !param->pid[0]) {
1034 LOG_ERROR("Missing vid/pid");
1035 return ERROR_FAIL;
1038 if (hid_init() != 0) {
1039 LOG_ERROR("unable to open HIDAPI");
1040 return ERROR_FAIL;
1043 struct nulink_usb_handle_s *h = calloc(1, sizeof(*h));
1044 if (!h) {
1045 LOG_ERROR("Out of memory");
1046 goto error_open;
1049 const char *serial = adapter_get_required_serial();
1050 if (serial) {
1051 size_t len = mbstowcs(NULL, serial, 0);
1053 target_serial = calloc(len + 1, sizeof(wchar_t));
1054 if (!target_serial) {
1055 LOG_ERROR("Out of memory");
1056 goto error_open;
1059 if (mbstowcs(target_serial, serial, len + 1) == (size_t)(-1)) {
1060 LOG_WARNING("unable to convert serial");
1061 free(target_serial);
1062 target_serial = NULL;
1066 devs = hid_enumerate(0, 0);
1067 cur_dev = devs;
1068 while (cur_dev) {
1069 bool found = false;
1071 for (unsigned int i = 0; param->vid[i] || param->pid[i]; i++) {
1072 if (param->vid[i] == cur_dev->vendor_id && param->pid[i] == cur_dev->product_id) {
1073 found = true;
1074 break;
1078 if (found) {
1079 if (!target_serial)
1080 break;
1081 if (cur_dev->serial_number && wcscmp(target_serial, cur_dev->serial_number) == 0)
1082 break;
1085 cur_dev = cur_dev->next;
1087 if (cur_dev) {
1088 target_vid = cur_dev->vendor_id;
1089 target_pid = cur_dev->product_id;
1092 hid_free_enumeration(devs);
1094 if (target_vid == 0 && target_pid == 0) {
1095 LOG_ERROR("unable to find Nu-Link");
1096 goto error_open;
1099 hid_device *dev = hid_open(target_vid, target_pid, target_serial);
1100 if (!dev) {
1101 LOG_ERROR("unable to open Nu-Link device 0x%" PRIx16 ":0x%" PRIx16, target_vid, target_pid);
1102 goto error_open;
1105 h->dev_handle = dev;
1106 h->usbcmdidx = 0;
1108 switch (target_pid) {
1109 case NULINK2_USB_PID1:
1110 case NULINK2_USB_PID2:
1111 h->hardware_config = HARDWARE_CONFIG_NULINK2;
1112 h->max_packet_size = NULINK2_HID_MAX_SIZE;
1113 h->init_buffer = nulink2_usb_init_buffer;
1114 h->xfer = nulink2_usb_xfer;
1115 break;
1116 default:
1117 h->hardware_config = 0;
1118 h->max_packet_size = NULINK_HID_MAX_SIZE;
1119 h->init_buffer = nulink1_usb_init_buffer;
1120 h->xfer = nulink1_usb_xfer;
1121 break;
1124 /* get the device version */
1125 h->cmdsize = 4 * 5;
1126 int err = nulink_usb_version(h);
1127 if (err != ERROR_OK) {
1128 LOG_DEBUG("nulink_usb_version failed with cmdSize(4 * 5)");
1129 h->cmdsize = 4 * 6;
1130 err = nulink_usb_version(h);
1131 if (err != ERROR_OK)
1132 LOG_DEBUG("nulink_usb_version failed with cmdSize(4 * 6)");
1135 /* SWD clock rate : 1MHz */
1136 nulink_speed(h, 1000, false);
1138 /* get cpuid, so we can determine the max page size
1139 * start with a safe default */
1140 h->max_mem_packet = (1 << 10);
1142 LOG_DEBUG("nulink_usb_open: we manually perform nulink_usb_reset");
1143 nulink_usb_reset(h);
1145 *fd = h;
1147 free(target_serial);
1148 return ERROR_OK;
1150 error_open:
1151 nulink_usb_close(h);
1152 free(target_serial);
1154 return ERROR_FAIL;
1157 struct hl_layout_api_s nulink_usb_layout_api = {
1158 .open = nulink_usb_open,
1159 .close = nulink_usb_close,
1160 .idcode = nulink_usb_idcode,
1161 .state = nulink_usb_state,
1162 .reset = nulink_usb_reset,
1163 .assert_srst = nulink_usb_assert_srst,
1164 .run = nulink_usb_run,
1165 .halt = nulink_usb_halt,
1166 .step = nulink_usb_step,
1167 .read_reg = nulink_usb_read_reg,
1168 .write_reg = nulink_usb_write_reg,
1169 .read_mem = nulink_usb_read_mem,
1170 .write_mem = nulink_usb_write_mem,
1171 .write_debug_reg = nulink_usb_write_debug_reg,
1172 .override_target = nulink_usb_override_target,
1173 .speed = nulink_speed,