1 /***************************************************************************
2 * Copyright (C) 2016-2017 by Nuvoton *
3 * Zale Yu <cyyu@nuvoton.com> *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
23 /* project specific includes */
24 #include <helper/binarybuffer.h>
25 #include <jtag/interface.h>
26 #include <jtag/hla/hla_layout.h>
27 #include <jtag/hla/hla_transport.h>
28 #include <jtag/hla/hla_interface.h>
29 #include <target/target.h>
31 #include <target/cortex_m.h>
35 #define NULINK_READ_TIMEOUT 1000
37 #define NULINK_HID_MAX_SIZE (64)
38 #define V6M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 2)
40 struct nulink_usb_handle_s
{
41 hid_device
*dev_handle
;
42 uint16_t max_packet_size
;
45 uint8_t cmdbuf
[NULINK_HID_MAX_SIZE
+ 1];
46 uint8_t tempbuf
[NULINK_HID_MAX_SIZE
];
47 uint8_t databuf
[NULINK_HID_MAX_SIZE
];
48 uint32_t max_mem_packet
;
49 uint16_t hardware_config
; /* bit 0: 1:Nu-Link-Pro, 0:Nu-Link */
53 #define CMD_READ_REG 0xB5UL
54 #define CMD_READ_RAM 0xB1UL
55 #define CMD_WRITE_REG 0xB8UL
56 #define CMD_WRITE_RAM 0xB9UL
57 #define CMD_CHECK_ID 0xA3UL
58 #define CMD_MCU_RESET 0xE2UL
59 #define CMD_CHECK_MCU_STOP 0xD8UL
60 #define CMD_MCU_STEP_RUN 0xD1UL
61 #define CMD_MCU_STOP_RUN 0xD2UL
62 #define CMD_MCU_FREE_RUN 0xD3UL
63 #define CMD_SET_CONFIG 0xA2UL
65 #define ARM_SRAM_BASE 0x20000000UL
67 #define HARDWARE_CONFIG_NULINKPRO 1
72 RESET_SYSRESETREQ
= 2,
74 RESET_FAST_RESCUE
= 4, /* Rescue and erase the chip, need very fast speed */
78 CONNECT_NORMAL
= 0, /* Support all reset method */
79 CONNECT_PRE_RESET
= 1, /* Support all reset method */
80 CONNECT_UNDER_RESET
= 2, /* Support all reset method */
81 CONNECT_NONE
= 3, /* Support RESET_HW, (RESET_AUTO = RESET_HW) */
82 CONNECT_DISCONNECT
= 4, /* Support RESET_NONE, (RESET_AUTO = RESET_NONE) */
83 CONNECT_ICP_MODE
= 5 /* Support NUC505 ICP mode*/
86 static int nulink_usb_xfer_rw(void *handle
, uint8_t *buf
)
88 struct nulink_usb_handle_s
*h
= handle
;
92 int ret
= hid_write(h
->dev_handle
, h
->cmdbuf
, h
->max_packet_size
+ 1);
94 LOG_ERROR("hid_write");
98 ret
= hid_read_timeout(h
->dev_handle
, buf
, h
->max_packet_size
, NULINK_READ_TIMEOUT
);
100 LOG_ERROR("hid_read_timeout");
106 static int nulink_usb_xfer(void *handle
, uint8_t *buf
, int size
)
108 struct nulink_usb_handle_s
*h
= handle
;
112 int err
= nulink_usb_xfer_rw(h
, h
->tempbuf
);
114 memcpy(buf
, h
->tempbuf
+ 2, V6M_MAX_COMMAND_LENGTH
);
119 static void nulink_usb_init_buffer(void *handle
, uint32_t size
)
121 struct nulink_usb_handle_s
*h
= handle
;
125 memset(h
->cmdbuf
, 0, h
->max_packet_size
+ 1);
126 memset(h
->tempbuf
, 0, h
->max_packet_size
);
127 memset(h
->databuf
, 0, h
->max_packet_size
);
129 h
->cmdbuf
[0] = 0; /* report number */
130 h
->cmdbuf
[1] = ++h
->usbcmdidx
& 0x7F;
135 static int nulink_usb_version(void *handle
)
137 struct nulink_usb_handle_s
*h
= handle
;
139 LOG_DEBUG("nulink_usb_version");
143 nulink_usb_init_buffer(handle
, V6M_MAX_COMMAND_LENGTH
);
145 memset(h
->cmdbuf
+ h
->cmdidx
, 0xFF, V6M_MAX_COMMAND_LENGTH
);
146 h
->cmdbuf
[h
->cmdidx
+ 4] = 0xA1; /* host_rev_num: 6561 */;
147 h
->cmdbuf
[h
->cmdidx
+ 5] = 0x19;
149 int res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * 5);
153 LOG_INFO("Nu-Link firmware_version %" PRIu32
", product_id (0x%08" PRIx32
")",
154 le_to_h_u32(h
->databuf
),
155 le_to_h_u32(h
->databuf
+ 4 * 1));
157 const bool is_nulinkpro
= !!(le_to_h_u32(h
->databuf
+ 4 * 2) & 1);
159 LOG_INFO("Adapter is Nu-Link-Pro, target_voltage_mv(%" PRIu16
"), usb_voltage_mv(%" PRIu16
")",
160 le_to_h_u16(h
->databuf
+ 4 * 3 + 0),
161 le_to_h_u16(h
->databuf
+ 4 * 3 + 2));
163 h
->hardware_config
|= HARDWARE_CONFIG_NULINKPRO
;
165 LOG_INFO("Adapter is Nu-Link");
171 static int nulink_usb_idcode(void *handle
, uint32_t *idcode
)
173 struct nulink_usb_handle_s
*h
= handle
;
175 LOG_DEBUG("nulink_usb_idcode");
179 nulink_usb_init_buffer(handle
, 4 * 1);
181 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_CHECK_ID
);
184 int res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * 2);
188 *idcode
= le_to_h_u32(h
->databuf
+ 4 * 1);
190 LOG_INFO("IDCODE: 0x%08" PRIX32
, *idcode
);
195 static int nulink_usb_write_debug_reg(void *handle
, uint32_t addr
, uint32_t val
)
197 struct nulink_usb_handle_s
*h
= handle
;
199 LOG_DEBUG("nulink_usb_write_debug_reg 0x%08" PRIX32
"0x%08" PRIX32
, addr
, val
);
201 nulink_usb_init_buffer(handle
, 8 + 12 * 1);
203 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_WRITE_RAM
);
205 /* Count of registers */
206 h
->cmdbuf
[h
->cmdidx
] = 1;
208 /* Array of bool value (u8ReadOld) */
209 h
->cmdbuf
[h
->cmdidx
] = 0x00;
211 /* Array of bool value (u8Verify) */
212 h
->cmdbuf
[h
->cmdidx
] = 0x00;
215 h
->cmdbuf
[h
->cmdidx
] = 0;
218 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, addr
);
221 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, val
);
224 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0x00000000UL
);
227 return nulink_usb_xfer(handle
, h
->databuf
, 4 * 2);
230 static enum target_state
nulink_usb_state(void *handle
)
232 struct nulink_usb_handle_s
*h
= handle
;
236 nulink_usb_init_buffer(handle
, 4 * 1);
238 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_CHECK_MCU_STOP
);
241 int res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * 4);
243 return TARGET_UNKNOWN
;
245 if (!le_to_h_u32(h
->databuf
+ 4 * 2))
246 return TARGET_HALTED
;
248 return TARGET_RUNNING
;
251 static int nulink_usb_assert_srst(void *handle
, int srst
)
253 struct nulink_usb_handle_s
*h
= handle
;
255 LOG_DEBUG("nulink_usb_assert_srst");
259 nulink_usb_init_buffer(handle
, 4 * 4);
261 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_MCU_RESET
);
264 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, RESET_SYSRESETREQ
);
266 /* set connect type */
267 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CONNECT_NORMAL
);
270 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0);
273 return nulink_usb_xfer(handle
, h
->databuf
, 4 * 4);
276 static int nulink_usb_reset(void *handle
)
278 struct nulink_usb_handle_s
*h
= handle
;
280 LOG_DEBUG("nulink_usb_reset");
284 nulink_usb_init_buffer(handle
, 4 * 4);
286 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_MCU_RESET
);
289 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, RESET_HW
);
291 /* set connect type */
292 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CONNECT_NORMAL
);
295 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0);
298 return nulink_usb_xfer(handle
, h
->databuf
, 4 * 4);
301 static int nulink_usb_run(void *handle
)
303 struct nulink_usb_handle_s
*h
= handle
;
305 LOG_DEBUG("nulink_usb_run");
309 nulink_usb_init_buffer(handle
, 4 * 1);
311 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_MCU_FREE_RUN
);
314 return nulink_usb_xfer(handle
, h
->databuf
, 4 * 4);
317 static int nulink_usb_halt(void *handle
)
319 struct nulink_usb_handle_s
*h
= handle
;
321 LOG_DEBUG("nulink_usb_halt");
325 nulink_usb_init_buffer(handle
, 4 * 1);
327 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_MCU_STOP_RUN
);
330 int res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * 4);
332 LOG_DEBUG("Nu-Link stop_pc 0x%08" PRIx32
, le_to_h_u32(h
->databuf
+ 4));
337 static int nulink_usb_step(void *handle
)
339 struct nulink_usb_handle_s
*h
= handle
;
341 LOG_DEBUG("nulink_usb_step");
345 nulink_usb_init_buffer(handle
, 4 * 1);
347 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_MCU_STEP_RUN
);
350 int res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * 4);
352 LOG_DEBUG("Nu-Link pc 0x%08" PRIx32
, le_to_h_u32(h
->databuf
+ 4));
357 static int nulink_usb_read_reg(void *handle
, int num
, uint32_t *val
)
359 struct nulink_usb_handle_s
*h
= handle
;
363 nulink_usb_init_buffer(handle
, 8 + 12 * 1);
365 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_WRITE_REG
);
367 /* Count of registers */
368 h
->cmdbuf
[h
->cmdidx
] = 1;
370 /* Array of bool value (u8ReadOld) */
371 h
->cmdbuf
[h
->cmdidx
] = 0xFF;
373 /* Array of bool value (u8Verify) */
374 h
->cmdbuf
[h
->cmdidx
] = 0x00;
377 h
->cmdbuf
[h
->cmdidx
] = 0;
380 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, num
);
383 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0);
386 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0xFFFFFFFFUL
);
389 int res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * 2);
391 *val
= le_to_h_u32(h
->databuf
+ 4 * 1);
396 static int nulink_usb_write_reg(void *handle
, int num
, uint32_t val
)
398 struct nulink_usb_handle_s
*h
= handle
;
402 nulink_usb_init_buffer(handle
, 8 + 12 * 1);
404 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_WRITE_REG
);
406 /* Count of registers */
407 h
->cmdbuf
[h
->cmdidx
] = 1;
409 /* Array of bool value (u8ReadOld) */
410 h
->cmdbuf
[h
->cmdidx
] = 0x00;
412 /* Array of bool value (u8Verify) */
413 h
->cmdbuf
[h
->cmdidx
] = 0x00;
416 h
->cmdbuf
[h
->cmdidx
] = 0;
419 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, num
);
422 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, val
);
425 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0x00000000UL
);
428 return nulink_usb_xfer(handle
, h
->databuf
, 4 * 2);
431 static int nulink_usb_read_mem8(void *handle
, uint32_t addr
, uint16_t len
,
436 uint32_t bytes_remaining
= 12;
437 struct nulink_usb_handle_s
*h
= handle
;
439 LOG_DEBUG("nulink_usb_read_mem8: addr 0x%08" PRIx32
", len %" PRId16
, addr
, len
);
443 /* check whether data is word aligned */
445 uint32_t aligned_addr
= addr
/ 4;
446 aligned_addr
= aligned_addr
* 4;
447 offset
= addr
- aligned_addr
;
448 LOG_DEBUG("nulink_usb_read_mem8: unaligned address addr 0x%08" PRIx32
449 "/aligned addr 0x%08" PRIx32
"offset %" PRIu32
,
450 addr
, aligned_addr
, offset
);
458 if (len
< bytes_remaining
)
459 bytes_remaining
= len
;
466 nulink_usb_init_buffer(handle
, 8 + 12 * count
);
468 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_WRITE_RAM
);
470 /* Count of registers */
471 h
->cmdbuf
[h
->cmdidx
] = count
;
473 /* Array of bool value (u8ReadOld) */
474 h
->cmdbuf
[h
->cmdidx
] = 0xFF;
476 /* Array of bool value (u8Verify) */
477 h
->cmdbuf
[h
->cmdidx
] = 0x00;
480 h
->cmdbuf
[h
->cmdidx
] = 0;
483 for (unsigned int i
= 0; i
< count
; i
++) {
485 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, addr
);
488 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0);
491 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0xFFFFFFFFUL
);
493 /* proceed to the next one */
497 res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * count
* 2);
501 /* fill in the output buffer */
502 for (unsigned int i
= 0; i
< count
; i
++) {
504 memcpy(buffer
, h
->databuf
+ 4 + offset
, len
);
506 memcpy(buffer
+ 2 * i
, h
->databuf
+ 4 * (2 * i
+ 1), len
- 2);
509 if (len
>= bytes_remaining
)
510 len
-= bytes_remaining
;
516 static int nulink_usb_write_mem8(void *handle
, uint32_t addr
, uint16_t len
,
517 const uint8_t *buffer
)
521 uint32_t bytes_remaining
= 12;
522 struct nulink_usb_handle_s
*h
= handle
;
524 LOG_DEBUG("nulink_usb_write_mem8: addr 0x%08" PRIx32
", len %" PRIu16
, addr
, len
);
528 /* check whether data is word aligned */
530 uint32_t aligned_addr
= addr
/ 4;
531 aligned_addr
= aligned_addr
* 4;
532 offset
= addr
- aligned_addr
;
533 LOG_DEBUG("nulink_usb_write_mem8: address not aligned. addr(0x%08" PRIx32
534 ")/aligned_addr(0x%08" PRIx32
")/offset(%" PRIu32
")",
535 addr
, aligned_addr
, offset
);
543 if (len
< bytes_remaining
)
544 bytes_remaining
= len
;
551 nulink_usb_init_buffer(handle
, 8 + 12 * count
);
553 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_WRITE_RAM
);
555 /* Count of registers */
556 h
->cmdbuf
[h
->cmdidx
] = count
;
558 /* Array of bool value (u8ReadOld) */
559 h
->cmdbuf
[h
->cmdidx
] = 0x00;
561 /* Array of bool value (u8Verify) */
562 h
->cmdbuf
[h
->cmdidx
] = 0x00;
565 h
->cmdbuf
[h
->cmdidx
] = 0;
568 for (unsigned int i
= 0; i
< count
; i
++) {
570 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, addr
);
573 uint32_t u32buffer
= buf_get_u32(buffer
, 0, len
* 8);
574 u32buffer
= (u32buffer
<< offset
* 8);
575 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, u32buffer
);
581 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0xFFFFFF00UL
);
582 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFFFF00", i
);
584 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0xFFFF0000UL
);
585 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFF0000", i
);
589 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0xFF00FFFFUL
);
590 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFF00FFFF", i
);
593 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0x0000FFFFUL
);
594 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x0000FFFF", i
);
599 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0xFFFF0000UL
);
600 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFF0000", i
);
602 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0x00000000UL
);
603 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x00000000", i
);
608 /* proceed to the next one */
613 res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * count
* 2);
617 if (len
>= bytes_remaining
)
618 len
-= bytes_remaining
;
624 static int nulink_usb_read_mem32(void *handle
, uint32_t addr
, uint16_t len
,
628 uint32_t bytes_remaining
= 12;
629 struct nulink_usb_handle_s
*h
= handle
;
633 /* data must be a multiple of 4 and word aligned */
634 if (len
% 4 || addr
% 4) {
635 LOG_ERROR("Invalid data alignment");
636 return ERROR_TARGET_UNALIGNED_ACCESS
;
640 if (len
< bytes_remaining
)
641 bytes_remaining
= len
;
643 unsigned int count
= bytes_remaining
/ 4;
645 nulink_usb_init_buffer(handle
, 8 + 12 * count
);
647 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_WRITE_RAM
);
649 /* Count of registers */
650 h
->cmdbuf
[h
->cmdidx
] = count
;
652 /* Array of bool value (u8ReadOld) */
653 h
->cmdbuf
[h
->cmdidx
] = 0xFF;
655 /* Array of bool value (u8Verify) */
656 h
->cmdbuf
[h
->cmdidx
] = 0x00;
659 h
->cmdbuf
[h
->cmdidx
] = 0;
662 for (unsigned int i
= 0; i
< count
; i
++) {
664 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, addr
);
667 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0);
670 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0xFFFFFFFFUL
);
672 /* proceed to the next one */
676 res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * count
* 2);
678 /* fill in the output buffer */
679 for (unsigned int i
= 0; i
< count
; i
++) {
680 memcpy(buffer
, h
->databuf
+ 4 * (2 * i
+ 1), 4);
684 if (len
>= bytes_remaining
)
685 len
-= bytes_remaining
;
693 static int nulink_usb_write_mem32(void *handle
, uint32_t addr
, uint16_t len
,
694 const uint8_t *buffer
)
697 uint32_t bytes_remaining
= 12;
698 struct nulink_usb_handle_s
*h
= handle
;
702 /* data must be a multiple of 4 and word aligned */
703 if (len
% 4 || addr
% 4) {
704 LOG_ERROR("Invalid data alignment");
705 return ERROR_TARGET_UNALIGNED_ACCESS
;
709 if (len
< bytes_remaining
)
710 bytes_remaining
= len
;
712 unsigned int count
= bytes_remaining
/ 4;
714 nulink_usb_init_buffer(handle
, 8 + 12 * count
);
716 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_WRITE_RAM
);
718 /* Count of registers */
719 h
->cmdbuf
[h
->cmdidx
] = count
;
721 /* Array of bool value (u8ReadOld) */
722 h
->cmdbuf
[h
->cmdidx
] = 0x00;
724 /* Array of bool value (u8Verify) */
725 h
->cmdbuf
[h
->cmdidx
] = 0x00;
728 h
->cmdbuf
[h
->cmdidx
] = 0;
731 for (unsigned int i
= 0; i
< count
; i
++) {
733 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, addr
);
736 uint32_t u32buffer
= buf_get_u32(buffer
, 0, 32);
737 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, u32buffer
);
740 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0x00000000);
743 /* proceed to the next one */
748 res
= nulink_usb_xfer(handle
, h
->databuf
, 4 * count
* 2);
750 if (len
>= bytes_remaining
)
751 len
-= bytes_remaining
;
759 static uint32_t nulink_max_block_size(uint32_t tar_autoincr_block
, uint32_t address
)
761 uint32_t max_tar_block
= (tar_autoincr_block
- ((tar_autoincr_block
- 1) & address
));
763 if (max_tar_block
== 0)
766 return max_tar_block
;
769 static int nulink_usb_read_mem(void *handle
, uint32_t addr
, uint32_t size
,
770 uint32_t count
, uint8_t *buffer
)
772 int retval
= ERROR_OK
;
773 struct nulink_usb_handle_s
*h
= handle
;
775 /* calculate byte count */
779 uint32_t bytes_remaining
= nulink_max_block_size(h
->max_mem_packet
, addr
);
781 if (count
< bytes_remaining
)
782 bytes_remaining
= count
;
784 if (bytes_remaining
>= 4)
787 /* the nulink only supports 8/32bit memory read/writes
788 * honour 32bit, all others will be handled as 8bit access */
790 /* When in jtag mode the nulink uses the auto-increment functinality.
791 * However it expects us to pass the data correctly, this includes
792 * alignment and any page boundaries. We already do this as part of the
793 * adi_v5 implementation, but the nulink is a hla adapter and so this
794 * needs implementiong manually.
795 * currently this only affects jtag mode, they do single
796 * access in SWD mode - but this may change and so we do it for both modes */
798 /* we first need to check for any unaligned bytes */
800 uint32_t head_bytes
= 4 - (addr
% 4);
801 retval
= nulink_usb_read_mem8(handle
, addr
, head_bytes
, buffer
);
802 if (retval
!= ERROR_OK
)
804 buffer
+= head_bytes
;
807 bytes_remaining
-= head_bytes
;
810 if (bytes_remaining
% 4)
811 retval
= nulink_usb_read_mem(handle
, addr
, 1, bytes_remaining
, buffer
);
813 retval
= nulink_usb_read_mem32(handle
, addr
, bytes_remaining
, buffer
);
815 retval
= nulink_usb_read_mem8(handle
, addr
, bytes_remaining
, buffer
);
818 if (retval
!= ERROR_OK
)
821 buffer
+= bytes_remaining
;
822 addr
+= bytes_remaining
;
823 count
-= bytes_remaining
;
829 static int nulink_usb_write_mem(void *handle
, uint32_t addr
, uint32_t size
,
830 uint32_t count
, const uint8_t *buffer
)
832 int retval
= ERROR_OK
;
833 struct nulink_usb_handle_s
*h
= handle
;
835 if (addr
< ARM_SRAM_BASE
) {
836 LOG_DEBUG("nulink_usb_write_mem: address below ARM_SRAM_BASE, not supported.\n");
840 /* calculate byte count */
844 uint32_t bytes_remaining
= nulink_max_block_size(h
->max_mem_packet
, addr
);
846 if (count
< bytes_remaining
)
847 bytes_remaining
= count
;
849 if (bytes_remaining
>= 4)
852 /* the nulink only supports 8/32bit memory read/writes
853 * honour 32bit, all others will be handled as 8bit access */
855 /* When in jtag mode the nulink uses the auto-increment functinality.
856 * However it expects us to pass the data correctly, this includes
857 * alignment and any page boundaries. We already do this as part of the
858 * adi_v5 implementation, but the nulink is a hla adapter and so this
859 * needs implementiong manually.
860 * currently this only affects jtag mode, do single
861 * access in SWD mode - but this may change and so we do it for both modes */
863 /* we first need to check for any unaligned bytes */
865 uint32_t head_bytes
= 4 - (addr
% 4);
866 retval
= nulink_usb_write_mem8(handle
, addr
, head_bytes
, buffer
);
867 if (retval
!= ERROR_OK
)
869 buffer
+= head_bytes
;
872 bytes_remaining
-= head_bytes
;
875 if (bytes_remaining
% 4)
876 retval
= nulink_usb_write_mem(handle
, addr
, 1, bytes_remaining
, buffer
);
878 retval
= nulink_usb_write_mem32(handle
, addr
, bytes_remaining
, buffer
);
881 retval
= nulink_usb_write_mem8(handle
, addr
, bytes_remaining
, buffer
);
884 if (retval
!= ERROR_OK
)
887 buffer
+= bytes_remaining
;
888 addr
+= bytes_remaining
;
889 count
-= bytes_remaining
;
895 static int nulink_usb_override_target(const char *targetname
)
897 LOG_DEBUG("nulink_usb_override_target");
899 return !strcmp(targetname
, "cortex_m");
902 static int nulink_speed(void *handle
, int khz
, bool query
)
904 struct nulink_usb_handle_s
*h
= handle
;
905 unsigned long max_ice_clock
= khz
;
907 LOG_DEBUG("nulink_speed: query %s", query
? "yes" : "no");
909 if (max_ice_clock
> 12000)
910 max_ice_clock
= 12000;
911 else if ((max_ice_clock
== 3 * 512) || (max_ice_clock
== 1500))
912 max_ice_clock
= 1500;
913 else if (max_ice_clock
>= 1000)
914 max_ice_clock
= max_ice_clock
/ 1000 * 1000;
916 max_ice_clock
= max_ice_clock
/ 100 * 100;
918 LOG_DEBUG("Nu-Link nulink_speed: %lu", max_ice_clock
);
921 nulink_usb_init_buffer(handle
, 4 * 6);
923 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, CMD_SET_CONFIG
);
925 /* set max SWD clock */
926 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, max_ice_clock
);
928 /* chip type: NUC_CHIP_TYPE_GENERAL_V6M */
929 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0);
932 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 5000);
934 /* If supply voltage to target or not */
935 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 0);
937 /* USB_FUNC_E: USB_FUNC_HID_BULK */
938 h_u32_to_le(h
->cmdbuf
+ h
->cmdidx
, 2);
941 nulink_usb_xfer(handle
, h
->databuf
, 4 * 3);
943 LOG_DEBUG("nulink_speed: h->hardware_config(%" PRId16
")", h
->hardware_config
);
944 if (h
->hardware_config
& HARDWARE_CONFIG_NULINKPRO
)
945 LOG_INFO("Nu-Link target_voltage_mv[0](%04" PRIx16
"), target_voltage_mv[1](%04" PRIx16
946 "), target_voltage_mv[2](%04" PRIx16
"), if_target_power_supplied(%d)",
947 le_to_h_u16(h
->databuf
+ 4 * 1 + 0),
948 le_to_h_u16(h
->databuf
+ 4 * 1 + 2),
949 le_to_h_u16(h
->databuf
+ 4 * 2 + 0),
950 le_to_h_u16(h
->databuf
+ 4 * 2 + 2) & 1);
953 return max_ice_clock
;
956 static int nulink_usb_close(void *handle
)
958 struct nulink_usb_handle_s
*h
= handle
;
960 LOG_DEBUG("nulink_usb_close");
962 if (h
&& h
->dev_handle
)
963 hid_close(h
->dev_handle
);
972 static int nulink_usb_open(struct hl_interface_param_s
*param
, void **fd
)
974 struct hid_device_info
*devs
, *cur_dev
;
975 uint16_t target_vid
= 0;
976 uint16_t target_pid
= 0;
977 wchar_t *target_serial
= NULL
;
979 LOG_DEBUG("nulink_usb_open");
981 if (param
->transport
!= HL_TRANSPORT_SWD
)
982 return TARGET_UNKNOWN
;
984 if (!param
->vid
[0] && !param
->pid
[0]) {
985 LOG_ERROR("Missing vid/pid");
989 if (hid_init() != 0) {
990 LOG_ERROR("unable to open HIDAPI");
994 struct nulink_usb_handle_s
*h
= calloc(1, sizeof(*h
));
996 LOG_ERROR("Out of memory");
1000 if (param
->serial
) {
1001 size_t len
= mbstowcs(NULL
, param
->serial
, 0);
1003 target_serial
= calloc(len
+ 1, sizeof(wchar_t));
1004 if (!target_serial
) {
1005 LOG_ERROR("Out of memory");
1009 if (mbstowcs(target_serial
, param
->serial
, len
+ 1) == (size_t)(-1)) {
1010 LOG_WARNING("unable to convert serial");
1011 free(target_serial
);
1012 target_serial
= NULL
;
1016 devs
= hid_enumerate(0, 0);
1021 for (unsigned int i
= 0; param
->vid
[i
] || param
->pid
[i
]; i
++) {
1022 if (param
->vid
[i
] == cur_dev
->vendor_id
&& param
->pid
[i
] == cur_dev
->product_id
) {
1031 if (cur_dev
->serial_number
&& wcscmp(target_serial
, cur_dev
->serial_number
) == 0)
1035 cur_dev
= cur_dev
->next
;
1038 target_vid
= cur_dev
->vendor_id
;
1039 target_pid
= cur_dev
->product_id
;
1042 hid_free_enumeration(devs
);
1044 if (target_vid
== 0 && target_pid
== 0) {
1045 LOG_ERROR("unable to find Nu-Link");
1049 hid_device
*dev
= hid_open(target_vid
, target_pid
, target_serial
);
1051 LOG_ERROR("unable to open Nu-Link device 0x%" PRIx16
":0x%" PRIx16
, target_vid
, target_pid
);
1055 h
->dev_handle
= dev
;
1057 h
->hardware_config
= 0;
1058 h
->max_packet_size
= NULINK_HID_MAX_SIZE
;
1060 /* get the device version */
1061 int err
= nulink_usb_version(h
);
1062 if (err
!= ERROR_OK
)
1065 /* SWD clock rate : 1MHz */
1066 nulink_speed(h
, 1000, false);
1068 /* get cpuid, so we can determine the max page size
1069 * start with a safe default */
1070 h
->max_mem_packet
= (1 << 10);
1072 LOG_DEBUG("nulink_usb_open: we manually perform nulink_usb_reset");
1073 nulink_usb_reset(h
);
1077 free(target_serial
);
1081 nulink_usb_close(h
);
1082 free(target_serial
);
1087 struct hl_layout_api_s nulink_usb_layout_api
= {
1088 .open
= nulink_usb_open
,
1089 .close
= nulink_usb_close
,
1090 .idcode
= nulink_usb_idcode
,
1091 .state
= nulink_usb_state
,
1092 .reset
= nulink_usb_reset
,
1093 .assert_srst
= nulink_usb_assert_srst
,
1094 .run
= nulink_usb_run
,
1095 .halt
= nulink_usb_halt
,
1096 .step
= nulink_usb_step
,
1097 .read_reg
= nulink_usb_read_reg
,
1098 .write_reg
= nulink_usb_write_reg
,
1099 .read_mem
= nulink_usb_read_mem
,
1100 .write_mem
= nulink_usb_write_mem
,
1101 .write_debug_reg
= nulink_usb_write_debug_reg
,
1102 .override_target
= nulink_usb_override_target
,
1103 .speed
= nulink_speed
,
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)