0bb5ec4443541ee65c80e5bc196ba3340a898778
[openocd.git] / src / jtag / drivers / nulink_usb.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4 * Copyright (C) 2016-2017 by Nuvoton *
5 * Zale Yu <cyyu@nuvoton.com> *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
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>
20
21 #include <target/cortex_m.h>
22
23 #include <hidapi.h>
24
25 #include "libusb_helper.h"
26
27 #define NULINK_READ_TIMEOUT LIBUSB_TIMEOUT_MS
28
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)
33
34 #define NULINK2_USB_PID1 (0x5200)
35 #define NULINK2_USB_PID2 (0x5201)
36
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 */
48
49 int (*xfer)(void *handle, uint8_t *buf, int size);
50 void (*init_buffer)(void *handle, uint32_t size);
51 };
52
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
65
66 #define ARM_SRAM_BASE 0x20000000UL
67
68 #define HARDWARE_CONFIG_NULINKPRO 1
69 #define HARDWARE_CONFIG_NULINK2 2
70
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 */
77 };
78
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*/
86 };
87
88 static int nulink_usb_xfer_rw(void *handle, uint8_t *buf)
89 {
90 struct nulink_usb_handle_s *h = handle;
91
92 assert(handle);
93
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;
98 }
99
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;
104 }
105 return ERROR_OK;
106 }
107
108 static int nulink1_usb_xfer(void *handle, uint8_t *buf, int size)
109 {
110 struct nulink_usb_handle_s *h = handle;
111
112 assert(handle);
113
114 int err = nulink_usb_xfer_rw(h, h->tempbuf);
115
116 memcpy(buf, h->tempbuf + 2, V6M_MAX_COMMAND_LENGTH);
117
118 return err;
119 }
120
121 static int nulink2_usb_xfer(void *handle, uint8_t *buf, int size)
122 {
123 struct nulink_usb_handle_s *h = handle;
124
125 assert(handle);
126
127 int err = nulink_usb_xfer_rw(h, h->tempbuf);
128
129 memcpy(buf, h->tempbuf + 3, V7M_MAX_COMMAND_LENGTH);
130
131 return err;
132 }
133
134 static void nulink1_usb_init_buffer(void *handle, uint32_t size)
135 {
136 struct nulink_usb_handle_s *h = handle;
137
138 h->cmdidx = 0;
139
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);
143
144 h->cmdbuf[0] = 0; /* report number */
145 h->cmdbuf[1] = ++h->usbcmdidx & 0x7F;
146 h->cmdbuf[2] = size;
147 h->cmdidx += 3;
148 }
149
150 static void nulink2_usb_init_buffer(void *handle, uint32_t size)
151 {
152 struct nulink_usb_handle_s *h = handle;
153
154 h->cmdidx = 0;
155
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);
159
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;
164 }
165
166 static inline int nulink_usb_xfer(void *handle, uint8_t *buf, int size)
167 {
168 struct nulink_usb_handle_s *h = handle;
169
170 assert(handle);
171
172 return h->xfer(handle, buf, size);
173 }
174
175 static inline void nulink_usb_init_buffer(void *handle, uint32_t size)
176 {
177 struct nulink_usb_handle_s *h = handle;
178
179 assert(handle);
180
181 h->init_buffer(handle, size);
182 }
183
184 static int nulink_usb_version(void *handle)
185 {
186 struct nulink_usb_handle_s *h = handle;
187
188 LOG_DEBUG("nulink_usb_version");
189
190 assert(handle);
191
192 nulink_usb_init_buffer(handle, V6M_MAX_COMMAND_LENGTH);
193
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;
197
198 int res = nulink_usb_xfer(handle, h->databuf, h->cmdsize);
199 if (res != ERROR_OK)
200 return res;
201
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));
205
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));
211
212 h->hardware_config |= HARDWARE_CONFIG_NULINKPRO;
213 } else {
214 LOG_INFO("Adapter is Nu-Link");
215 }
216
217 return ERROR_OK;
218 }
219
220 static int nulink_usb_idcode(void *handle, uint32_t *idcode)
221 {
222 struct nulink_usb_handle_s *h = handle;
223
224 LOG_DEBUG("nulink_usb_idcode");
225
226 assert(handle);
227
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;
232
233 int res = nulink_usb_xfer(handle, h->databuf, 4 * 2);
234 if (res != ERROR_OK)
235 return res;
236
237 *idcode = le_to_h_u32(h->databuf + 4 * 1);
238
239 LOG_INFO("IDCODE: 0x%08" PRIX32, *idcode);
240
241 return ERROR_OK;
242 }
243
244 static int nulink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
245 {
246 struct nulink_usb_handle_s *h = handle;
247
248 LOG_DEBUG("nulink_usb_write_debug_reg 0x%08" PRIX32 " 0x%08" PRIX32, addr, val);
249
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;
275
276 return nulink_usb_xfer(handle, h->databuf, 4 * 2);
277 }
278
279 static enum target_state nulink_usb_state(void *handle)
280 {
281 struct nulink_usb_handle_s *h = handle;
282
283 assert(handle);
284
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;
289
290 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
291 if (res != ERROR_OK)
292 return TARGET_UNKNOWN;
293
294 if (!le_to_h_u32(h->databuf + 4 * 2))
295 return TARGET_HALTED;
296 else
297 return TARGET_RUNNING;
298 }
299
300 static int nulink_usb_assert_srst(void *handle, int srst)
301 {
302 struct nulink_usb_handle_s *h = handle;
303
304 LOG_DEBUG("nulink_usb_assert_srst");
305
306 assert(handle);
307
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;
321
322 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
323 }
324
325 static int nulink_usb_reset(void *handle)
326 {
327 struct nulink_usb_handle_s *h = handle;
328
329 LOG_DEBUG("nulink_usb_reset");
330
331 assert(handle);
332
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;
346
347 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
348 }
349
350 static int nulink_usb_run(void *handle)
351 {
352 struct nulink_usb_handle_s *h = handle;
353
354 LOG_DEBUG("nulink_usb_run");
355
356 assert(handle);
357
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;
362
363 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
364 }
365
366 static int nulink_usb_halt(void *handle)
367 {
368 struct nulink_usb_handle_s *h = handle;
369
370 LOG_DEBUG("nulink_usb_halt");
371
372 assert(handle);
373
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;
378
379 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
380
381 LOG_DEBUG("Nu-Link stop_pc 0x%08" PRIx32, le_to_h_u32(h->databuf + 4));
382
383 return res;
384 }
385
386 static int nulink_usb_step(void *handle)
387 {
388 struct nulink_usb_handle_s *h = handle;
389
390 LOG_DEBUG("nulink_usb_step");
391
392 assert(handle);
393
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;
398
399 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
400
401 LOG_DEBUG("Nu-Link pc 0x%08" PRIx32, le_to_h_u32(h->databuf + 4));
402
403 return res;
404 }
405
406 static int nulink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val)
407 {
408 struct nulink_usb_handle_s *h = handle;
409
410 assert(handle);
411
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;
437
438 int res = nulink_usb_xfer(handle, h->databuf, 4 * 2);
439
440 *val = le_to_h_u32(h->databuf + 4 * 1);
441
442 return res;
443 }
444
445 static int nulink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val)
446 {
447 struct nulink_usb_handle_s *h = handle;
448
449 assert(handle);
450
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;
476
477 return nulink_usb_xfer(handle, h->databuf, 4 * 2);
478 }
479
480 static int nulink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len,
481 uint8_t *buffer)
482 {
483 int res = ERROR_OK;
484 uint32_t offset = 0;
485 uint32_t bytes_remaining = 12;
486 struct nulink_usb_handle_s *h = handle;
487
488 LOG_DEBUG("nulink_usb_read_mem8: addr 0x%08" PRIx32 ", len %" PRId16, addr, len);
489
490 assert(handle);
491
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);
500
501 addr = aligned_addr;
502 }
503
504 while (len) {
505 unsigned int count;
506
507 if (len < bytes_remaining)
508 bytes_remaining = len;
509
510 if (len < 4)
511 count = 1;
512 else
513 count = 2;
514
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;
531
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;
544 }
545
546 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
547 if (res != ERROR_OK)
548 break;
549
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);
556 }
557
558 if (len >= bytes_remaining)
559 len -= bytes_remaining;
560 }
561
562 return res;
563 }
564
565 static int nulink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len,
566 const uint8_t *buffer)
567 {
568 int res = ERROR_OK;
569 uint32_t offset = 0;
570 uint32_t bytes_remaining = 12;
571 struct nulink_usb_handle_s *h = handle;
572
573 LOG_DEBUG("nulink_usb_write_mem8: addr 0x%08" PRIx32 ", len %" PRIu16, addr, len);
574
575 assert(handle);
576
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);
585
586 addr = aligned_addr;
587 }
588
589 while (len) {
590 unsigned int count;
591
592 if (len < bytes_remaining)
593 bytes_remaining = len;
594
595 if (len < 4)
596 count = 1;
597 else
598 count = 2;
599
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;
616
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);
635 }
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);
640
641 } else {
642 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x0000FFFFUL);
643 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x0000FFFF", i);
644 }
645 }
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);
653 }
654 }
655 h->cmdidx += 4;
656
657 /* proceed to the next one */
658 addr += 4;
659 buffer += 4;
660 }
661
662 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
663 if (res != ERROR_OK)
664 break;
665
666 if (len >= bytes_remaining)
667 len -= bytes_remaining;
668 }
669
670 return res;
671 }
672
673 static int nulink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
674 uint8_t *buffer)
675 {
676 int res = ERROR_OK;
677 uint32_t bytes_remaining = 12;
678 struct nulink_usb_handle_s *h = handle;
679
680 assert(handle);
681
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;
686 }
687
688 while (len) {
689 if (len < bytes_remaining)
690 bytes_remaining = len;
691
692 unsigned int count = bytes_remaining / 4;
693
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;
710
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;
723 }
724
725 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
726
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;
731 }
732
733 if (len >= bytes_remaining)
734 len -= bytes_remaining;
735 else
736 len = 0;
737 }
738
739 return res;
740 }
741
742 static int nulink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
743 const uint8_t *buffer)
744 {
745 int res = ERROR_OK;
746 uint32_t bytes_remaining = 12;
747 struct nulink_usb_handle_s *h = handle;
748
749 assert(handle);
750
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;
755 }
756
757 while (len) {
758 if (len < bytes_remaining)
759 bytes_remaining = len;
760
761 unsigned int count = bytes_remaining / 4;
762
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;
779
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;
791
792 /* proceed to the next one */
793 addr += 4;
794 buffer += 4;
795 }
796
797 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
798
799 if (len >= bytes_remaining)
800 len -= bytes_remaining;
801 else
802 len = 0;
803 }
804
805 return res;
806 }
807
808 static uint32_t nulink_max_block_size(uint32_t tar_autoincr_block, uint32_t address)
809 {
810 uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address));
811
812 if (max_tar_block == 0)
813 max_tar_block = 4;
814
815 return max_tar_block;
816 }
817
818 static int nulink_usb_read_mem(void *handle, uint32_t addr, uint32_t size,
819 uint32_t count, uint8_t *buffer)
820 {
821 int retval = ERROR_OK;
822 struct nulink_usb_handle_s *h = handle;
823
824 /* calculate byte count */
825 count *= size;
826
827 while (count) {
828 uint32_t bytes_remaining = nulink_max_block_size(h->max_mem_packet, addr);
829
830 if (count < bytes_remaining)
831 bytes_remaining = count;
832
833 if (bytes_remaining >= 4)
834 size = 4;
835
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 */
846
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;
857 }
858
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);
865 }
866
867 if (retval != ERROR_OK)
868 return retval;
869
870 buffer += bytes_remaining;
871 addr += bytes_remaining;
872 count -= bytes_remaining;
873 }
874
875 return retval;
876 }
877
878 static int nulink_usb_write_mem(void *handle, uint32_t addr, uint32_t size,
879 uint32_t count, const uint8_t *buffer)
880 {
881 int retval = ERROR_OK;
882 struct nulink_usb_handle_s *h = handle;
883
884 if (addr < ARM_SRAM_BASE) {
885 LOG_DEBUG("nulink_usb_write_mem: address below ARM_SRAM_BASE, not supported.\n");
886 return retval;
887 }
888
889 /* calculate byte count */
890 count *= size;
891
892 while (count) {
893 uint32_t bytes_remaining = nulink_max_block_size(h->max_mem_packet, addr);
894
895 if (count < bytes_remaining)
896 bytes_remaining = count;
897
898 if (bytes_remaining >= 4)
899 size = 4;
900
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 */
911
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;
922 }
923
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);
928
929 } else {
930 retval = nulink_usb_write_mem8(handle, addr, bytes_remaining, buffer);
931 }
932
933 if (retval != ERROR_OK)
934 return retval;
935
936 buffer += bytes_remaining;
937 addr += bytes_remaining;
938 count -= bytes_remaining;
939 }
940
941 return retval;
942 }
943
944 static int nulink_usb_override_target(const char *targetname)
945 {
946 LOG_DEBUG("nulink_usb_override_target");
947
948 return !strcmp(targetname, "cortex_m");
949 }
950
951 static int nulink_speed(void *handle, int khz, bool query)
952 {
953 struct nulink_usb_handle_s *h = handle;
954 unsigned long max_ice_clock = khz;
955
956 LOG_DEBUG("nulink_speed: query %s", query ? "yes" : "no");
957
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;
966
967 LOG_DEBUG("Nu-Link nulink_speed: %lu", max_ice_clock);
968
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;
989
990 nulink_usb_xfer(handle, h->databuf, 4 * 3);
991
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);
1000 }
1001
1002 return max_ice_clock;
1003 }
1004
1005 static int nulink_usb_close(void *handle)
1006 {
1007 struct nulink_usb_handle_s *h = handle;
1008
1009 LOG_DEBUG("nulink_usb_close");
1010
1011 if (h && h->dev_handle)
1012 hid_close(h->dev_handle);
1013
1014 free(h);
1015
1016 hid_exit();
1017
1018 return ERROR_OK;
1019 }
1020
1021 static int nulink_usb_open(struct hl_interface_param_s *param, void **fd)
1022 {
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;
1027
1028 LOG_DEBUG("nulink_usb_open");
1029
1030 if (param->transport != HL_TRANSPORT_SWD)
1031 return TARGET_UNKNOWN;
1032
1033 if (!param->vid[0] && !param->pid[0]) {
1034 LOG_ERROR("Missing vid/pid");
1035 return ERROR_FAIL;
1036 }
1037
1038 if (hid_init() != 0) {
1039 LOG_ERROR("unable to open HIDAPI");
1040 return ERROR_FAIL;
1041 }
1042
1043 struct nulink_usb_handle_s *h = calloc(1, sizeof(*h));
1044 if (!h) {
1045 LOG_ERROR("Out of memory");
1046 goto error_open;
1047 }
1048
1049 const char *serial = adapter_get_required_serial();
1050 if (serial) {
1051 size_t len = mbstowcs(NULL, serial, 0);
1052
1053 target_serial = calloc(len + 1, sizeof(wchar_t));
1054 if (!target_serial) {
1055 LOG_ERROR("Out of memory");
1056 goto error_open;
1057 }
1058
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;
1063 }
1064 }
1065
1066 devs = hid_enumerate(0, 0);
1067 cur_dev = devs;
1068 while (cur_dev) {
1069 bool found = false;
1070
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;
1075 }
1076 }
1077
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;
1083 }
1084
1085 cur_dev = cur_dev->next;
1086 }
1087 if (cur_dev) {
1088 target_vid = cur_dev->vendor_id;
1089 target_pid = cur_dev->product_id;
1090 }
1091
1092 hid_free_enumeration(devs);
1093
1094 if (target_vid == 0 && target_pid == 0) {
1095 LOG_ERROR("unable to find Nu-Link");
1096 goto error_open;
1097 }
1098
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;
1103 }
1104
1105 h->dev_handle = dev;
1106 h->usbcmdidx = 0;
1107
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;
1122 }
1123
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)");
1133 }
1134
1135 /* SWD clock rate : 1MHz */
1136 nulink_speed(h, 1000, false);
1137
1138 /* get cpuid, so we can determine the max page size
1139 * start with a safe default */
1140 h->max_mem_packet = (1 << 10);
1141
1142 LOG_DEBUG("nulink_usb_open: we manually perform nulink_usb_reset");
1143 nulink_usb_reset(h);
1144
1145 *fd = h;
1146
1147 free(target_serial);
1148 return ERROR_OK;
1149
1150 error_open:
1151 nulink_usb_close(h);
1152 free(target_serial);
1153
1154 return ERROR_FAIL;
1155 }
1156
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,
1174 };

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)