jtag/hla, jtag/stlink: switch to command 'adapter serial'
[openocd.git] / src / jtag / drivers / nulink_usb.c
1 /***************************************************************************
2 * Copyright (C) 2016-2017 by Nuvoton *
3 * Zale Yu <cyyu@nuvoton.com> *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 /* project specific includes */
24 #include <helper/binarybuffer.h>
25 #include <jtag/adapter.h>
26 #include <jtag/interface.h>
27 #include <jtag/hla/hla_layout.h>
28 #include <jtag/hla/hla_transport.h>
29 #include <jtag/hla/hla_interface.h>
30 #include <target/target.h>
31
32 #include <target/cortex_m.h>
33
34 #include <hidapi.h>
35
36 #define NULINK_READ_TIMEOUT 1000
37
38 #define NULINK_HID_MAX_SIZE (64)
39 #define NULINK2_HID_MAX_SIZE (1024)
40 #define V6M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 2)
41 #define V7M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 3)
42
43 #define NULINK2_USB_PID1 (0x5200)
44 #define NULINK2_USB_PID2 (0x5201)
45
46 struct nulink_usb_handle_s {
47 hid_device *dev_handle;
48 uint16_t max_packet_size;
49 uint8_t usbcmdidx;
50 uint8_t cmdidx;
51 uint8_t cmdsize;
52 uint8_t cmdbuf[NULINK2_HID_MAX_SIZE + 1];
53 uint8_t tempbuf[NULINK2_HID_MAX_SIZE];
54 uint8_t databuf[NULINK2_HID_MAX_SIZE];
55 uint32_t max_mem_packet;
56 uint16_t hardware_config; /* bit 0: 1:Nu-Link-Pro, 0:Nu-Link */
57
58 int (*xfer)(void *handle, uint8_t *buf, int size);
59 void (*init_buffer)(void *handle, uint32_t size);
60 };
61
62 /* ICE Command */
63 #define CMD_READ_REG 0xB5UL
64 #define CMD_READ_RAM 0xB1UL
65 #define CMD_WRITE_REG 0xB8UL
66 #define CMD_WRITE_RAM 0xB9UL
67 #define CMD_CHECK_ID 0xA3UL
68 #define CMD_MCU_RESET 0xE2UL
69 #define CMD_CHECK_MCU_STOP 0xD8UL
70 #define CMD_MCU_STEP_RUN 0xD1UL
71 #define CMD_MCU_STOP_RUN 0xD2UL
72 #define CMD_MCU_FREE_RUN 0xD3UL
73 #define CMD_SET_CONFIG 0xA2UL
74
75 #define ARM_SRAM_BASE 0x20000000UL
76
77 #define HARDWARE_CONFIG_NULINKPRO 1
78 #define HARDWARE_CONFIG_NULINK2 2
79
80 enum nulink_reset {
81 RESET_AUTO = 0,
82 RESET_HW = 1,
83 RESET_SYSRESETREQ = 2,
84 RESET_VECTRESET = 3,
85 RESET_FAST_RESCUE = 4, /* Rescue and erase the chip, need very fast speed */
86 };
87
88 enum nulink_connect {
89 CONNECT_NORMAL = 0, /* Support all reset method */
90 CONNECT_PRE_RESET = 1, /* Support all reset method */
91 CONNECT_UNDER_RESET = 2, /* Support all reset method */
92 CONNECT_NONE = 3, /* Support RESET_HW, (RESET_AUTO = RESET_HW) */
93 CONNECT_DISCONNECT = 4, /* Support RESET_NONE, (RESET_AUTO = RESET_NONE) */
94 CONNECT_ICP_MODE = 5 /* Support NUC505 ICP mode*/
95 };
96
97 static int nulink_usb_xfer_rw(void *handle, uint8_t *buf)
98 {
99 struct nulink_usb_handle_s *h = handle;
100
101 assert(handle);
102
103 int ret = hid_write(h->dev_handle, h->cmdbuf, h->max_packet_size + 1);
104 if (ret < 0) {
105 LOG_ERROR("hid_write");
106 return ERROR_FAIL;
107 }
108
109 ret = hid_read_timeout(h->dev_handle, buf, h->max_packet_size, NULINK_READ_TIMEOUT);
110 if (ret < 0) {
111 LOG_ERROR("hid_read_timeout");
112 return ERROR_FAIL;
113 }
114 return ERROR_OK;
115 }
116
117 static int nulink1_usb_xfer(void *handle, uint8_t *buf, int size)
118 {
119 struct nulink_usb_handle_s *h = handle;
120
121 assert(handle);
122
123 int err = nulink_usb_xfer_rw(h, h->tempbuf);
124
125 memcpy(buf, h->tempbuf + 2, V6M_MAX_COMMAND_LENGTH);
126
127 return err;
128 }
129
130 static int nulink2_usb_xfer(void *handle, uint8_t *buf, int size)
131 {
132 struct nulink_usb_handle_s *h = handle;
133
134 assert(handle);
135
136 int err = nulink_usb_xfer_rw(h, h->tempbuf);
137
138 memcpy(buf, h->tempbuf + 3, V7M_MAX_COMMAND_LENGTH);
139
140 return err;
141 }
142
143 static void nulink1_usb_init_buffer(void *handle, uint32_t size)
144 {
145 struct nulink_usb_handle_s *h = handle;
146
147 h->cmdidx = 0;
148
149 memset(h->cmdbuf, 0, h->max_packet_size + 1);
150 memset(h->tempbuf, 0, h->max_packet_size);
151 memset(h->databuf, 0, h->max_packet_size);
152
153 h->cmdbuf[0] = 0; /* report number */
154 h->cmdbuf[1] = ++h->usbcmdidx & 0x7F;
155 h->cmdbuf[2] = size;
156 h->cmdidx += 3;
157 }
158
159 static void nulink2_usb_init_buffer(void *handle, uint32_t size)
160 {
161 struct nulink_usb_handle_s *h = handle;
162
163 h->cmdidx = 0;
164
165 memset(h->cmdbuf, 0, h->max_packet_size + 1);
166 memset(h->tempbuf, 0, h->max_packet_size);
167 memset(h->databuf, 0, h->max_packet_size);
168
169 h->cmdbuf[0] = 0; /* report number */
170 h->cmdbuf[1] = ++h->usbcmdidx & 0x7F;
171 h_u16_to_le(h->cmdbuf + 2, size);
172 h->cmdidx += 4;
173 }
174
175 static inline int nulink_usb_xfer(void *handle, uint8_t *buf, int size)
176 {
177 struct nulink_usb_handle_s *h = handle;
178
179 assert(handle);
180
181 return h->xfer(handle, buf, size);
182 }
183
184 static inline void nulink_usb_init_buffer(void *handle, uint32_t size)
185 {
186 struct nulink_usb_handle_s *h = handle;
187
188 assert(handle);
189
190 h->init_buffer(handle, size);
191 }
192
193 static int nulink_usb_version(void *handle)
194 {
195 struct nulink_usb_handle_s *h = handle;
196
197 LOG_DEBUG("nulink_usb_version");
198
199 assert(handle);
200
201 nulink_usb_init_buffer(handle, V6M_MAX_COMMAND_LENGTH);
202
203 memset(h->cmdbuf + h->cmdidx, 0xFF, V6M_MAX_COMMAND_LENGTH);
204 h->cmdbuf[h->cmdidx + 4] = 0xA1; /* host_rev_num: 6561 */;
205 h->cmdbuf[h->cmdidx + 5] = 0x19;
206
207 int res = nulink_usb_xfer(handle, h->databuf, h->cmdsize);
208 if (res != ERROR_OK)
209 return res;
210
211 LOG_INFO("Nu-Link firmware_version %" PRIu32 ", product_id (0x%08" PRIx32 ")",
212 le_to_h_u32(h->databuf),
213 le_to_h_u32(h->databuf + 4 * 1));
214
215 const bool is_nulinkpro = !!(le_to_h_u32(h->databuf + 4 * 2) & 1);
216 if (is_nulinkpro) {
217 LOG_INFO("Adapter is Nu-Link-Pro, target_voltage_mv(%" PRIu16 "), usb_voltage_mv(%" PRIu16 ")",
218 le_to_h_u16(h->databuf + 4 * 3 + 0),
219 le_to_h_u16(h->databuf + 4 * 3 + 2));
220
221 h->hardware_config |= HARDWARE_CONFIG_NULINKPRO;
222 } else {
223 LOG_INFO("Adapter is Nu-Link");
224 }
225
226 return ERROR_OK;
227 }
228
229 static int nulink_usb_idcode(void *handle, uint32_t *idcode)
230 {
231 struct nulink_usb_handle_s *h = handle;
232
233 LOG_DEBUG("nulink_usb_idcode");
234
235 assert(handle);
236
237 nulink_usb_init_buffer(handle, 4 * 1);
238 /* set command ID */
239 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_CHECK_ID);
240 h->cmdidx += 4;
241
242 int res = nulink_usb_xfer(handle, h->databuf, 4 * 2);
243 if (res != ERROR_OK)
244 return res;
245
246 *idcode = le_to_h_u32(h->databuf + 4 * 1);
247
248 LOG_INFO("IDCODE: 0x%08" PRIX32, *idcode);
249
250 return ERROR_OK;
251 }
252
253 static int nulink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
254 {
255 struct nulink_usb_handle_s *h = handle;
256
257 LOG_DEBUG("nulink_usb_write_debug_reg 0x%08" PRIX32 " 0x%08" PRIX32, addr, val);
258
259 nulink_usb_init_buffer(handle, 8 + 12 * 1);
260 /* set command ID */
261 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
262 h->cmdidx += 4;
263 /* Count of registers */
264 h->cmdbuf[h->cmdidx] = 1;
265 h->cmdidx += 1;
266 /* Array of bool value (u8ReadOld) */
267 h->cmdbuf[h->cmdidx] = 0x00;
268 h->cmdidx += 1;
269 /* Array of bool value (u8Verify) */
270 h->cmdbuf[h->cmdidx] = 0x00;
271 h->cmdidx += 1;
272 /* ignore */
273 h->cmdbuf[h->cmdidx] = 0;
274 h->cmdidx += 1;
275 /* u32Addr */
276 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
277 h->cmdidx += 4;
278 /* u32Data */
279 h_u32_to_le(h->cmdbuf + h->cmdidx, val);
280 h->cmdidx += 4;
281 /* u32Mask */
282 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
283 h->cmdidx += 4;
284
285 return nulink_usb_xfer(handle, h->databuf, 4 * 2);
286 }
287
288 static enum target_state nulink_usb_state(void *handle)
289 {
290 struct nulink_usb_handle_s *h = handle;
291
292 assert(handle);
293
294 nulink_usb_init_buffer(handle, 4 * 1);
295 /* set command ID */
296 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_CHECK_MCU_STOP);
297 h->cmdidx += 4;
298
299 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
300 if (res != ERROR_OK)
301 return TARGET_UNKNOWN;
302
303 if (!le_to_h_u32(h->databuf + 4 * 2))
304 return TARGET_HALTED;
305 else
306 return TARGET_RUNNING;
307 }
308
309 static int nulink_usb_assert_srst(void *handle, int srst)
310 {
311 struct nulink_usb_handle_s *h = handle;
312
313 LOG_DEBUG("nulink_usb_assert_srst");
314
315 assert(handle);
316
317 nulink_usb_init_buffer(handle, 4 * 4);
318 /* set command ID */
319 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_RESET);
320 h->cmdidx += 4;
321 /* set reset type */
322 h_u32_to_le(h->cmdbuf + h->cmdidx, RESET_SYSRESETREQ);
323 h->cmdidx += 4;
324 /* set connect type */
325 h_u32_to_le(h->cmdbuf + h->cmdidx, CONNECT_NORMAL);
326 h->cmdidx += 4;
327 /* set extMode */
328 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
329 h->cmdidx += 4;
330
331 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
332 }
333
334 static int nulink_usb_reset(void *handle)
335 {
336 struct nulink_usb_handle_s *h = handle;
337
338 LOG_DEBUG("nulink_usb_reset");
339
340 assert(handle);
341
342 nulink_usb_init_buffer(handle, 4 * 4);
343 /* set command ID */
344 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_RESET);
345 h->cmdidx += 4;
346 /* set reset type */
347 h_u32_to_le(h->cmdbuf + h->cmdidx, RESET_HW);
348 h->cmdidx += 4;
349 /* set connect type */
350 h_u32_to_le(h->cmdbuf + h->cmdidx, CONNECT_NORMAL);
351 h->cmdidx += 4;
352 /* set extMode */
353 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
354 h->cmdidx += 4;
355
356 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
357 }
358
359 static int nulink_usb_run(void *handle)
360 {
361 struct nulink_usb_handle_s *h = handle;
362
363 LOG_DEBUG("nulink_usb_run");
364
365 assert(handle);
366
367 nulink_usb_init_buffer(handle, 4 * 1);
368 /* set command ID */
369 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_FREE_RUN);
370 h->cmdidx += 4;
371
372 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
373 }
374
375 static int nulink_usb_halt(void *handle)
376 {
377 struct nulink_usb_handle_s *h = handle;
378
379 LOG_DEBUG("nulink_usb_halt");
380
381 assert(handle);
382
383 nulink_usb_init_buffer(handle, 4 * 1);
384 /* set command ID */
385 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_STOP_RUN);
386 h->cmdidx += 4;
387
388 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
389
390 LOG_DEBUG("Nu-Link stop_pc 0x%08" PRIx32, le_to_h_u32(h->databuf + 4));
391
392 return res;
393 }
394
395 static int nulink_usb_step(void *handle)
396 {
397 struct nulink_usb_handle_s *h = handle;
398
399 LOG_DEBUG("nulink_usb_step");
400
401 assert(handle);
402
403 nulink_usb_init_buffer(handle, 4 * 1);
404 /* set command ID */
405 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_STEP_RUN);
406 h->cmdidx += 4;
407
408 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
409
410 LOG_DEBUG("Nu-Link pc 0x%08" PRIx32, le_to_h_u32(h->databuf + 4));
411
412 return res;
413 }
414
415 static int nulink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val)
416 {
417 struct nulink_usb_handle_s *h = handle;
418
419 assert(handle);
420
421 nulink_usb_init_buffer(handle, 8 + 12 * 1);
422 /* set command ID */
423 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_REG);
424 h->cmdidx += 4;
425 /* Count of registers */
426 h->cmdbuf[h->cmdidx] = 1;
427 h->cmdidx += 1;
428 /* Array of bool value (u8ReadOld) */
429 h->cmdbuf[h->cmdidx] = 0xFF;
430 h->cmdidx += 1;
431 /* Array of bool value (u8Verify) */
432 h->cmdbuf[h->cmdidx] = 0x00;
433 h->cmdidx += 1;
434 /* ignore */
435 h->cmdbuf[h->cmdidx] = 0;
436 h->cmdidx += 1;
437 /* u32Addr */
438 h_u32_to_le(h->cmdbuf + h->cmdidx, regsel);
439 h->cmdidx += 4;
440 /* u32Data */
441 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
442 h->cmdidx += 4;
443 /* u32Mask */
444 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
445 h->cmdidx += 4;
446
447 int res = nulink_usb_xfer(handle, h->databuf, 4 * 2);
448
449 *val = le_to_h_u32(h->databuf + 4 * 1);
450
451 return res;
452 }
453
454 static int nulink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val)
455 {
456 struct nulink_usb_handle_s *h = handle;
457
458 assert(handle);
459
460 nulink_usb_init_buffer(handle, 8 + 12 * 1);
461 /* set command ID */
462 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_REG);
463 h->cmdidx += 4;
464 /* Count of registers */
465 h->cmdbuf[h->cmdidx] = 1;
466 h->cmdidx += 1;
467 /* Array of bool value (u8ReadOld) */
468 h->cmdbuf[h->cmdidx] = 0x00;
469 h->cmdidx += 1;
470 /* Array of bool value (u8Verify) */
471 h->cmdbuf[h->cmdidx] = 0x00;
472 h->cmdidx += 1;
473 /* ignore */
474 h->cmdbuf[h->cmdidx] = 0;
475 h->cmdidx += 1;
476 /* u32Addr */
477 h_u32_to_le(h->cmdbuf + h->cmdidx, regsel);
478 h->cmdidx += 4;
479 /* u32Data */
480 h_u32_to_le(h->cmdbuf + h->cmdidx, val);
481 h->cmdidx += 4;
482 /* u32Mask */
483 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
484 h->cmdidx += 4;
485
486 return nulink_usb_xfer(handle, h->databuf, 4 * 2);
487 }
488
489 static int nulink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len,
490 uint8_t *buffer)
491 {
492 int res = ERROR_OK;
493 uint32_t offset = 0;
494 uint32_t bytes_remaining = 12;
495 struct nulink_usb_handle_s *h = handle;
496
497 LOG_DEBUG("nulink_usb_read_mem8: addr 0x%08" PRIx32 ", len %" PRId16, addr, len);
498
499 assert(handle);
500
501 /* check whether data is word aligned */
502 if (addr % 4) {
503 uint32_t aligned_addr = addr / 4;
504 aligned_addr = aligned_addr * 4;
505 offset = addr - aligned_addr;
506 LOG_DEBUG("nulink_usb_read_mem8: unaligned address addr 0x%08" PRIx32
507 "/aligned addr 0x%08" PRIx32 " offset %" PRIu32,
508 addr, aligned_addr, offset);
509
510 addr = aligned_addr;
511 }
512
513 while (len) {
514 unsigned int count;
515
516 if (len < bytes_remaining)
517 bytes_remaining = len;
518
519 if (len < 4)
520 count = 1;
521 else
522 count = 2;
523
524 nulink_usb_init_buffer(handle, 8 + 12 * count);
525 /* set command ID */
526 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
527 h->cmdidx += 4;
528 /* Count of registers */
529 h->cmdbuf[h->cmdidx] = count;
530 h->cmdidx += 1;
531 /* Array of bool value (u8ReadOld) */
532 h->cmdbuf[h->cmdidx] = 0xFF;
533 h->cmdidx += 1;
534 /* Array of bool value (u8Verify) */
535 h->cmdbuf[h->cmdidx] = 0x00;
536 h->cmdidx += 1;
537 /* ignore */
538 h->cmdbuf[h->cmdidx] = 0;
539 h->cmdidx += 1;
540
541 for (unsigned int i = 0; i < count; i++) {
542 /* u32Addr */
543 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
544 h->cmdidx += 4;
545 /* u32Data */
546 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
547 h->cmdidx += 4;
548 /* u32Mask */
549 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
550 h->cmdidx += 4;
551 /* proceed to the next one */
552 addr += 4;
553 }
554
555 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
556 if (res != ERROR_OK)
557 break;
558
559 /* fill in the output buffer */
560 for (unsigned int i = 0; i < count; i++) {
561 if (i == 0)
562 memcpy(buffer, h->databuf + 4 + offset, len);
563 else
564 memcpy(buffer + 2 * i, h->databuf + 4 * (2 * i + 1), len - 2);
565 }
566
567 if (len >= bytes_remaining)
568 len -= bytes_remaining;
569 }
570
571 return res;
572 }
573
574 static int nulink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len,
575 const uint8_t *buffer)
576 {
577 int res = ERROR_OK;
578 uint32_t offset = 0;
579 uint32_t bytes_remaining = 12;
580 struct nulink_usb_handle_s *h = handle;
581
582 LOG_DEBUG("nulink_usb_write_mem8: addr 0x%08" PRIx32 ", len %" PRIu16, addr, len);
583
584 assert(handle);
585
586 /* check whether data is word aligned */
587 if (addr % 4) {
588 uint32_t aligned_addr = addr / 4;
589 aligned_addr = aligned_addr * 4;
590 offset = addr - aligned_addr;
591 LOG_DEBUG("nulink_usb_write_mem8: address not aligned. addr(0x%08" PRIx32
592 ")/aligned_addr(0x%08" PRIx32 ")/offset(%" PRIu32 ")",
593 addr, aligned_addr, offset);
594
595 addr = aligned_addr;
596 }
597
598 while (len) {
599 unsigned int count;
600
601 if (len < bytes_remaining)
602 bytes_remaining = len;
603
604 if (len < 4)
605 count = 1;
606 else
607 count = 2;
608
609 nulink_usb_init_buffer(handle, 8 + 12 * count);
610 /* set command ID */
611 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
612 h->cmdidx += 4;
613 /* Count of registers */
614 h->cmdbuf[h->cmdidx] = count;
615 h->cmdidx += 1;
616 /* Array of bool value (u8ReadOld) */
617 h->cmdbuf[h->cmdidx] = 0x00;
618 h->cmdidx += 1;
619 /* Array of bool value (u8Verify) */
620 h->cmdbuf[h->cmdidx] = 0x00;
621 h->cmdidx += 1;
622 /* ignore */
623 h->cmdbuf[h->cmdidx] = 0;
624 h->cmdidx += 1;
625
626 for (unsigned int i = 0; i < count; i++) {
627 /* u32Addr */
628 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
629 h->cmdidx += 4;
630 /* u32Data */
631 uint32_t u32buffer = buf_get_u32(buffer, 0, len * 8);
632 u32buffer = (u32buffer << offset * 8);
633 h_u32_to_le(h->cmdbuf + h->cmdidx, u32buffer);
634 h->cmdidx += 4;
635 /* u32Mask */
636 if (i == 0) {
637 if (offset == 0) {
638 if (len == 1) {
639 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFF00UL);
640 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFFFF00", i);
641 } else {
642 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFF0000UL);
643 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFF0000", i);
644 }
645 } else {
646 if (len == 1) {
647 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFF00FFFFUL);
648 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFF00FFFF", i);
649
650 } else {
651 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x0000FFFFUL);
652 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x0000FFFF", i);
653 }
654 }
655 } else {
656 if (len == 4) {
657 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFF0000UL);
658 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFF0000", i);
659 } else {
660 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
661 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x00000000", i);
662 }
663 }
664 h->cmdidx += 4;
665
666 /* proceed to the next one */
667 addr += 4;
668 buffer += 4;
669 }
670
671 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
672 if (res != ERROR_OK)
673 break;
674
675 if (len >= bytes_remaining)
676 len -= bytes_remaining;
677 }
678
679 return res;
680 }
681
682 static int nulink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
683 uint8_t *buffer)
684 {
685 int res = ERROR_OK;
686 uint32_t bytes_remaining = 12;
687 struct nulink_usb_handle_s *h = handle;
688
689 assert(handle);
690
691 /* data must be a multiple of 4 and word aligned */
692 if (len % 4 || addr % 4) {
693 LOG_ERROR("Invalid data alignment");
694 return ERROR_TARGET_UNALIGNED_ACCESS;
695 }
696
697 while (len) {
698 if (len < bytes_remaining)
699 bytes_remaining = len;
700
701 unsigned int count = bytes_remaining / 4;
702
703 nulink_usb_init_buffer(handle, 8 + 12 * count);
704 /* set command ID */
705 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
706 h->cmdidx += 4;
707 /* Count of registers */
708 h->cmdbuf[h->cmdidx] = count;
709 h->cmdidx += 1;
710 /* Array of bool value (u8ReadOld) */
711 h->cmdbuf[h->cmdidx] = 0xFF;
712 h->cmdidx += 1;
713 /* Array of bool value (u8Verify) */
714 h->cmdbuf[h->cmdidx] = 0x00;
715 h->cmdidx += 1;
716 /* ignore */
717 h->cmdbuf[h->cmdidx] = 0;
718 h->cmdidx += 1;
719
720 for (unsigned int i = 0; i < count; i++) {
721 /* u32Addr */
722 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
723 h->cmdidx += 4;
724 /* u32Data */
725 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
726 h->cmdidx += 4;
727 /* u32Mask */
728 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
729 h->cmdidx += 4;
730 /* proceed to the next one */
731 addr += 4;
732 }
733
734 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
735
736 /* fill in the output buffer */
737 for (unsigned int i = 0; i < count; i++) {
738 memcpy(buffer, h->databuf + 4 * (2 * i + 1), 4);
739 buffer += 4;
740 }
741
742 if (len >= bytes_remaining)
743 len -= bytes_remaining;
744 else
745 len = 0;
746 }
747
748 return res;
749 }
750
751 static int nulink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
752 const uint8_t *buffer)
753 {
754 int res = ERROR_OK;
755 uint32_t bytes_remaining = 12;
756 struct nulink_usb_handle_s *h = handle;
757
758 assert(handle);
759
760 /* data must be a multiple of 4 and word aligned */
761 if (len % 4 || addr % 4) {
762 LOG_ERROR("Invalid data alignment");
763 return ERROR_TARGET_UNALIGNED_ACCESS;
764 }
765
766 while (len) {
767 if (len < bytes_remaining)
768 bytes_remaining = len;
769
770 unsigned int count = bytes_remaining / 4;
771
772 nulink_usb_init_buffer(handle, 8 + 12 * count);
773 /* set command ID */
774 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
775 h->cmdidx += 4;
776 /* Count of registers */
777 h->cmdbuf[h->cmdidx] = count;
778 h->cmdidx += 1;
779 /* Array of bool value (u8ReadOld) */
780 h->cmdbuf[h->cmdidx] = 0x00;
781 h->cmdidx += 1;
782 /* Array of bool value (u8Verify) */
783 h->cmdbuf[h->cmdidx] = 0x00;
784 h->cmdidx += 1;
785 /* ignore */
786 h->cmdbuf[h->cmdidx] = 0;
787 h->cmdidx += 1;
788
789 for (unsigned int i = 0; i < count; i++) {
790 /* u32Addr */
791 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
792 h->cmdidx += 4;
793 /* u32Data */
794 uint32_t u32buffer = buf_get_u32(buffer, 0, 32);
795 h_u32_to_le(h->cmdbuf + h->cmdidx, u32buffer);
796 h->cmdidx += 4;
797 /* u32Mask */
798 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000);
799 h->cmdidx += 4;
800
801 /* proceed to the next one */
802 addr += 4;
803 buffer += 4;
804 }
805
806 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
807
808 if (len >= bytes_remaining)
809 len -= bytes_remaining;
810 else
811 len = 0;
812 }
813
814 return res;
815 }
816
817 static uint32_t nulink_max_block_size(uint32_t tar_autoincr_block, uint32_t address)
818 {
819 uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address));
820
821 if (max_tar_block == 0)
822 max_tar_block = 4;
823
824 return max_tar_block;
825 }
826
827 static int nulink_usb_read_mem(void *handle, uint32_t addr, uint32_t size,
828 uint32_t count, uint8_t *buffer)
829 {
830 int retval = ERROR_OK;
831 struct nulink_usb_handle_s *h = handle;
832
833 /* calculate byte count */
834 count *= size;
835
836 while (count) {
837 uint32_t bytes_remaining = nulink_max_block_size(h->max_mem_packet, addr);
838
839 if (count < bytes_remaining)
840 bytes_remaining = count;
841
842 if (bytes_remaining >= 4)
843 size = 4;
844
845 /* the nulink only supports 8/32bit memory read/writes
846 * honour 32bit, all others will be handled as 8bit access */
847 if (size == 4) {
848 /* When in jtag mode the nulink uses the auto-increment functionality.
849 * However it expects us to pass the data correctly, this includes
850 * alignment and any page boundaries. We already do this as part of the
851 * adi_v5 implementation, but the nulink is a hla adapter and so this
852 * needs implementing manually.
853 * currently this only affects jtag mode, they do single
854 * access in SWD mode - but this may change and so we do it for both modes */
855
856 /* we first need to check for any unaligned bytes */
857 if (addr % 4) {
858 uint32_t head_bytes = 4 - (addr % 4);
859 retval = nulink_usb_read_mem8(handle, addr, head_bytes, buffer);
860 if (retval != ERROR_OK)
861 return retval;
862 buffer += head_bytes;
863 addr += head_bytes;
864 count -= head_bytes;
865 bytes_remaining -= head_bytes;
866 }
867
868 if (bytes_remaining % 4)
869 retval = nulink_usb_read_mem(handle, addr, 1, bytes_remaining, buffer);
870 else
871 retval = nulink_usb_read_mem32(handle, addr, bytes_remaining, buffer);
872 } else {
873 retval = nulink_usb_read_mem8(handle, addr, bytes_remaining, buffer);
874 }
875
876 if (retval != ERROR_OK)
877 return retval;
878
879 buffer += bytes_remaining;
880 addr += bytes_remaining;
881 count -= bytes_remaining;
882 }
883
884 return retval;
885 }
886
887 static int nulink_usb_write_mem(void *handle, uint32_t addr, uint32_t size,
888 uint32_t count, const uint8_t *buffer)
889 {
890 int retval = ERROR_OK;
891 struct nulink_usb_handle_s *h = handle;
892
893 if (addr < ARM_SRAM_BASE) {
894 LOG_DEBUG("nulink_usb_write_mem: address below ARM_SRAM_BASE, not supported.\n");
895 return retval;
896 }
897
898 /* calculate byte count */
899 count *= size;
900
901 while (count) {
902 uint32_t bytes_remaining = nulink_max_block_size(h->max_mem_packet, addr);
903
904 if (count < bytes_remaining)
905 bytes_remaining = count;
906
907 if (bytes_remaining >= 4)
908 size = 4;
909
910 /* the nulink only supports 8/32bit memory read/writes
911 * honour 32bit, all others will be handled as 8bit access */
912 if (size == 4) {
913 /* When in jtag mode the nulink uses the auto-increment functionality.
914 * However it expects us to pass the data correctly, this includes
915 * alignment and any page boundaries. We already do this as part of the
916 * adi_v5 implementation, but the nulink is a hla adapter and so this
917 * needs implementing manually.
918 * currently this only affects jtag mode, do single
919 * access in SWD mode - but this may change and so we do it for both modes */
920
921 /* we first need to check for any unaligned bytes */
922 if (addr % 4) {
923 uint32_t head_bytes = 4 - (addr % 4);
924 retval = nulink_usb_write_mem8(handle, addr, head_bytes, buffer);
925 if (retval != ERROR_OK)
926 return retval;
927 buffer += head_bytes;
928 addr += head_bytes;
929 count -= head_bytes;
930 bytes_remaining -= head_bytes;
931 }
932
933 if (bytes_remaining % 4)
934 retval = nulink_usb_write_mem(handle, addr, 1, bytes_remaining, buffer);
935 else
936 retval = nulink_usb_write_mem32(handle, addr, bytes_remaining, buffer);
937
938 } else {
939 retval = nulink_usb_write_mem8(handle, addr, bytes_remaining, buffer);
940 }
941
942 if (retval != ERROR_OK)
943 return retval;
944
945 buffer += bytes_remaining;
946 addr += bytes_remaining;
947 count -= bytes_remaining;
948 }
949
950 return retval;
951 }
952
953 static int nulink_usb_override_target(const char *targetname)
954 {
955 LOG_DEBUG("nulink_usb_override_target");
956
957 return !strcmp(targetname, "cortex_m");
958 }
959
960 static int nulink_speed(void *handle, int khz, bool query)
961 {
962 struct nulink_usb_handle_s *h = handle;
963 unsigned long max_ice_clock = khz;
964
965 LOG_DEBUG("nulink_speed: query %s", query ? "yes" : "no");
966
967 if (max_ice_clock > 12000)
968 max_ice_clock = 12000;
969 else if ((max_ice_clock == 3 * 512) || (max_ice_clock == 1500))
970 max_ice_clock = 1500;
971 else if (max_ice_clock >= 1000)
972 max_ice_clock = max_ice_clock / 1000 * 1000;
973 else
974 max_ice_clock = max_ice_clock / 100 * 100;
975
976 LOG_DEBUG("Nu-Link nulink_speed: %lu", max_ice_clock);
977
978 if (!query) {
979 nulink_usb_init_buffer(handle, 4 * 6);
980 /* set command ID */
981 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_SET_CONFIG);
982 h->cmdidx += 4;
983 /* set max SWD clock */
984 h_u32_to_le(h->cmdbuf + h->cmdidx, max_ice_clock);
985 h->cmdidx += 4;
986 /* chip type: NUC_CHIP_TYPE_GENERAL_V6M */
987 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
988 h->cmdidx += 4;
989 /* IO voltage */
990 h_u32_to_le(h->cmdbuf + h->cmdidx, 5000);
991 h->cmdidx += 4;
992 /* If supply voltage to target or not */
993 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
994 h->cmdidx += 4;
995 /* USB_FUNC_E: USB_FUNC_HID_BULK */
996 h_u32_to_le(h->cmdbuf + h->cmdidx, 2);
997 h->cmdidx += 4;
998
999 nulink_usb_xfer(handle, h->databuf, 4 * 3);
1000
1001 LOG_DEBUG("nulink_speed: h->hardware_config(%" PRId16 ")", h->hardware_config);
1002 if (h->hardware_config & HARDWARE_CONFIG_NULINKPRO)
1003 LOG_INFO("Nu-Link target_voltage_mv[0](%04" PRIx16 "), target_voltage_mv[1](%04" PRIx16
1004 "), target_voltage_mv[2](%04" PRIx16 "), if_target_power_supplied(%d)",
1005 le_to_h_u16(h->databuf + 4 * 1 + 0),
1006 le_to_h_u16(h->databuf + 4 * 1 + 2),
1007 le_to_h_u16(h->databuf + 4 * 2 + 0),
1008 le_to_h_u16(h->databuf + 4 * 2 + 2) & 1);
1009 }
1010
1011 return max_ice_clock;
1012 }
1013
1014 static int nulink_usb_close(void *handle)
1015 {
1016 struct nulink_usb_handle_s *h = handle;
1017
1018 LOG_DEBUG("nulink_usb_close");
1019
1020 if (h && h->dev_handle)
1021 hid_close(h->dev_handle);
1022
1023 free(h);
1024
1025 hid_exit();
1026
1027 return ERROR_OK;
1028 }
1029
1030 static int nulink_usb_open(struct hl_interface_param_s *param, void **fd)
1031 {
1032 struct hid_device_info *devs, *cur_dev;
1033 uint16_t target_vid = 0;
1034 uint16_t target_pid = 0;
1035 wchar_t *target_serial = NULL;
1036
1037 LOG_DEBUG("nulink_usb_open");
1038
1039 if (param->transport != HL_TRANSPORT_SWD)
1040 return TARGET_UNKNOWN;
1041
1042 if (!param->vid[0] && !param->pid[0]) {
1043 LOG_ERROR("Missing vid/pid");
1044 return ERROR_FAIL;
1045 }
1046
1047 if (hid_init() != 0) {
1048 LOG_ERROR("unable to open HIDAPI");
1049 return ERROR_FAIL;
1050 }
1051
1052 struct nulink_usb_handle_s *h = calloc(1, sizeof(*h));
1053 if (!h) {
1054 LOG_ERROR("Out of memory");
1055 goto error_open;
1056 }
1057
1058 const char *serial = adapter_get_required_serial();
1059 if (serial) {
1060 size_t len = mbstowcs(NULL, serial, 0);
1061
1062 target_serial = calloc(len + 1, sizeof(wchar_t));
1063 if (!target_serial) {
1064 LOG_ERROR("Out of memory");
1065 goto error_open;
1066 }
1067
1068 if (mbstowcs(target_serial, serial, len + 1) == (size_t)(-1)) {
1069 LOG_WARNING("unable to convert serial");
1070 free(target_serial);
1071 target_serial = NULL;
1072 }
1073 }
1074
1075 devs = hid_enumerate(0, 0);
1076 cur_dev = devs;
1077 while (cur_dev) {
1078 bool found = false;
1079
1080 for (unsigned int i = 0; param->vid[i] || param->pid[i]; i++) {
1081 if (param->vid[i] == cur_dev->vendor_id && param->pid[i] == cur_dev->product_id) {
1082 found = true;
1083 break;
1084 }
1085 }
1086
1087 if (found) {
1088 if (!target_serial)
1089 break;
1090 if (cur_dev->serial_number && wcscmp(target_serial, cur_dev->serial_number) == 0)
1091 break;
1092 }
1093
1094 cur_dev = cur_dev->next;
1095 }
1096 if (cur_dev) {
1097 target_vid = cur_dev->vendor_id;
1098 target_pid = cur_dev->product_id;
1099 }
1100
1101 hid_free_enumeration(devs);
1102
1103 if (target_vid == 0 && target_pid == 0) {
1104 LOG_ERROR("unable to find Nu-Link");
1105 goto error_open;
1106 }
1107
1108 hid_device *dev = hid_open(target_vid, target_pid, target_serial);
1109 if (!dev) {
1110 LOG_ERROR("unable to open Nu-Link device 0x%" PRIx16 ":0x%" PRIx16, target_vid, target_pid);
1111 goto error_open;
1112 }
1113
1114 h->dev_handle = dev;
1115 h->usbcmdidx = 0;
1116
1117 switch (target_pid) {
1118 case NULINK2_USB_PID1:
1119 case NULINK2_USB_PID2:
1120 h->hardware_config = HARDWARE_CONFIG_NULINK2;
1121 h->max_packet_size = NULINK2_HID_MAX_SIZE;
1122 h->init_buffer = nulink2_usb_init_buffer;
1123 h->xfer = nulink2_usb_xfer;
1124 break;
1125 default:
1126 h->hardware_config = 0;
1127 h->max_packet_size = NULINK_HID_MAX_SIZE;
1128 h->init_buffer = nulink1_usb_init_buffer;
1129 h->xfer = nulink1_usb_xfer;
1130 break;
1131 }
1132
1133 /* get the device version */
1134 h->cmdsize = 4 * 5;
1135 int err = nulink_usb_version(h);
1136 if (err != ERROR_OK) {
1137 LOG_DEBUG("nulink_usb_version failed with cmdSize(4 * 5)");
1138 h->cmdsize = 4 * 6;
1139 err = nulink_usb_version(h);
1140 if (err != ERROR_OK)
1141 LOG_DEBUG("nulink_usb_version failed with cmdSize(4 * 6)");
1142 }
1143
1144 /* SWD clock rate : 1MHz */
1145 nulink_speed(h, 1000, false);
1146
1147 /* get cpuid, so we can determine the max page size
1148 * start with a safe default */
1149 h->max_mem_packet = (1 << 10);
1150
1151 LOG_DEBUG("nulink_usb_open: we manually perform nulink_usb_reset");
1152 nulink_usb_reset(h);
1153
1154 *fd = h;
1155
1156 free(target_serial);
1157 return ERROR_OK;
1158
1159 error_open:
1160 nulink_usb_close(h);
1161 free(target_serial);
1162
1163 return ERROR_FAIL;
1164 }
1165
1166 struct hl_layout_api_s nulink_usb_layout_api = {
1167 .open = nulink_usb_open,
1168 .close = nulink_usb_close,
1169 .idcode = nulink_usb_idcode,
1170 .state = nulink_usb_state,
1171 .reset = nulink_usb_reset,
1172 .assert_srst = nulink_usb_assert_srst,
1173 .run = nulink_usb_run,
1174 .halt = nulink_usb_halt,
1175 .step = nulink_usb_step,
1176 .read_reg = nulink_usb_read_reg,
1177 .write_reg = nulink_usb_write_reg,
1178 .read_mem = nulink_usb_read_mem,
1179 .write_mem = nulink_usb_write_mem,
1180 .write_debug_reg = nulink_usb_write_debug_reg,
1181 .override_target = nulink_usb_override_target,
1182 .speed = nulink_speed,
1183 };

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)