jtag/drivers: add support for Nu-Link (Nuvoton ICE) over usb
[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/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>
30
31 #include <target/cortex_m.h>
32
33 #include <hidapi.h>
34
35 #define NULINK_READ_TIMEOUT 1000
36
37 #define NULINK_HID_MAX_SIZE (64)
38 #define V6M_MAX_COMMAND_LENGTH (NULINK_HID_MAX_SIZE - 2)
39
40 struct nulink_usb_handle_s {
41 hid_device *dev_handle;
42 uint16_t max_packet_size;
43 uint8_t usbcmdidx;
44 uint8_t cmdidx;
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 */
50 };
51
52 /* ICE Command */
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
64
65 #define ARM_SRAM_BASE 0x20000000UL
66
67 #define HARDWARE_CONFIG_NULINKPRO 1
68
69 enum nulink_reset {
70 RESET_AUTO = 0,
71 RESET_HW = 1,
72 RESET_SYSRESETREQ = 2,
73 RESET_VECTRESET = 3,
74 RESET_FAST_RESCUE = 4, /* Rescue and erase the chip, need very fast speed */
75 };
76
77 enum nulink_connect {
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*/
84 };
85
86 static int nulink_usb_xfer_rw(void *handle, uint8_t *buf)
87 {
88 struct nulink_usb_handle_s *h = handle;
89
90 assert(handle);
91
92 int ret = hid_write(h->dev_handle, h->cmdbuf, h->max_packet_size + 1);
93 if (ret < 0) {
94 LOG_ERROR("hid_write");
95 return ERROR_FAIL;
96 }
97
98 ret = hid_read_timeout(h->dev_handle, buf, h->max_packet_size, NULINK_READ_TIMEOUT);
99 if (ret < 0) {
100 LOG_ERROR("hid_read_timeout");
101 return ERROR_FAIL;
102 }
103 return ERROR_OK;
104 }
105
106 static int nulink_usb_xfer(void *handle, uint8_t *buf, int size)
107 {
108 struct nulink_usb_handle_s *h = handle;
109
110 assert(handle);
111
112 int err = nulink_usb_xfer_rw(h, h->tempbuf);
113
114 memcpy(buf, h->tempbuf + 2, V6M_MAX_COMMAND_LENGTH);
115
116 return err;
117 }
118
119 static void nulink_usb_init_buffer(void *handle, uint32_t size)
120 {
121 struct nulink_usb_handle_s *h = handle;
122
123 h->cmdidx = 0;
124
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);
128
129 h->cmdbuf[0] = 0; /* report number */
130 h->cmdbuf[1] = ++h->usbcmdidx & 0x7F;
131 h->cmdbuf[2] = size;
132 h->cmdidx += 3;
133 }
134
135 static int nulink_usb_version(void *handle)
136 {
137 struct nulink_usb_handle_s *h = handle;
138
139 LOG_DEBUG("nulink_usb_version");
140
141 assert(handle);
142
143 nulink_usb_init_buffer(handle, V6M_MAX_COMMAND_LENGTH);
144
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;
148
149 int res = nulink_usb_xfer(handle, h->databuf, 4 * 5);
150 if (res != ERROR_OK)
151 return res;
152
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));
156
157 const bool is_nulinkpro = !!(le_to_h_u32(h->databuf + 4 * 2) & 1);
158 if (is_nulinkpro) {
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));
162
163 h->hardware_config |= HARDWARE_CONFIG_NULINKPRO;
164 } else {
165 LOG_INFO("Adapter is Nu-Link");
166 }
167
168 return ERROR_OK;
169 }
170
171 static int nulink_usb_idcode(void *handle, uint32_t *idcode)
172 {
173 struct nulink_usb_handle_s *h = handle;
174
175 LOG_DEBUG("nulink_usb_idcode");
176
177 assert(handle);
178
179 nulink_usb_init_buffer(handle, 4 * 1);
180 /* set command ID */
181 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_CHECK_ID);
182 h->cmdidx += 4;
183
184 int res = nulink_usb_xfer(handle, h->databuf, 4 * 2);
185 if (res != ERROR_OK)
186 return res;
187
188 *idcode = le_to_h_u32(h->databuf + 4 * 1);
189
190 LOG_INFO("IDCODE: 0x%08" PRIX32, *idcode);
191
192 return ERROR_OK;
193 }
194
195 static int nulink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val)
196 {
197 struct nulink_usb_handle_s *h = handle;
198
199 LOG_DEBUG("nulink_usb_write_debug_reg 0x%08" PRIX32 "0x%08" PRIX32, addr, val);
200
201 nulink_usb_init_buffer(handle, 8 + 12 * 1);
202 /* set command ID */
203 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
204 h->cmdidx += 4;
205 /* Count of registers */
206 h->cmdbuf[h->cmdidx] = 1;
207 h->cmdidx += 1;
208 /* Array of bool value (u8ReadOld) */
209 h->cmdbuf[h->cmdidx] = 0x00;
210 h->cmdidx += 1;
211 /* Array of bool value (u8Verify) */
212 h->cmdbuf[h->cmdidx] = 0x00;
213 h->cmdidx += 1;
214 /* ignore */
215 h->cmdbuf[h->cmdidx] = 0;
216 h->cmdidx += 1;
217 /* u32Addr */
218 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
219 h->cmdidx += 4;
220 /* u32Data */
221 h_u32_to_le(h->cmdbuf + h->cmdidx, val);
222 h->cmdidx += 4;
223 /* u32Mask */
224 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
225 h->cmdidx += 4;
226
227 return nulink_usb_xfer(handle, h->databuf, 4 * 2);
228 }
229
230 static enum target_state nulink_usb_state(void *handle)
231 {
232 struct nulink_usb_handle_s *h = handle;
233
234 assert(handle);
235
236 nulink_usb_init_buffer(handle, 4 * 1);
237 /* set command ID */
238 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_CHECK_MCU_STOP);
239 h->cmdidx += 4;
240
241 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
242 if (res != ERROR_OK)
243 return TARGET_UNKNOWN;
244
245 if (!le_to_h_u32(h->databuf + 4 * 2))
246 return TARGET_HALTED;
247 else
248 return TARGET_RUNNING;
249 }
250
251 static int nulink_usb_assert_srst(void *handle, int srst)
252 {
253 struct nulink_usb_handle_s *h = handle;
254
255 LOG_DEBUG("nulink_usb_assert_srst");
256
257 assert(handle);
258
259 nulink_usb_init_buffer(handle, 4 * 4);
260 /* set command ID */
261 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_RESET);
262 h->cmdidx += 4;
263 /* set reset type */
264 h_u32_to_le(h->cmdbuf + h->cmdidx, RESET_SYSRESETREQ);
265 h->cmdidx += 4;
266 /* set connect type */
267 h_u32_to_le(h->cmdbuf + h->cmdidx, CONNECT_NORMAL);
268 h->cmdidx += 4;
269 /* set extMode */
270 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
271 h->cmdidx += 4;
272
273 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
274 }
275
276 static int nulink_usb_reset(void *handle)
277 {
278 struct nulink_usb_handle_s *h = handle;
279
280 LOG_DEBUG("nulink_usb_reset");
281
282 assert(handle);
283
284 nulink_usb_init_buffer(handle, 4 * 4);
285 /* set command ID */
286 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_RESET);
287 h->cmdidx += 4;
288 /* set reset type */
289 h_u32_to_le(h->cmdbuf + h->cmdidx, RESET_HW);
290 h->cmdidx += 4;
291 /* set connect type */
292 h_u32_to_le(h->cmdbuf + h->cmdidx, CONNECT_NORMAL);
293 h->cmdidx += 4;
294 /* set extMode */
295 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
296 h->cmdidx += 4;
297
298 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
299 }
300
301 static int nulink_usb_run(void *handle)
302 {
303 struct nulink_usb_handle_s *h = handle;
304
305 LOG_DEBUG("nulink_usb_run");
306
307 assert(handle);
308
309 nulink_usb_init_buffer(handle, 4 * 1);
310 /* set command ID */
311 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_FREE_RUN);
312 h->cmdidx += 4;
313
314 return nulink_usb_xfer(handle, h->databuf, 4 * 4);
315 }
316
317 static int nulink_usb_halt(void *handle)
318 {
319 struct nulink_usb_handle_s *h = handle;
320
321 LOG_DEBUG("nulink_usb_halt");
322
323 assert(handle);
324
325 nulink_usb_init_buffer(handle, 4 * 1);
326 /* set command ID */
327 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_STOP_RUN);
328 h->cmdidx += 4;
329
330 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
331
332 LOG_DEBUG("Nu-Link stop_pc 0x%08" PRIx32, le_to_h_u32(h->databuf + 4));
333
334 return res;
335 }
336
337 static int nulink_usb_step(void *handle)
338 {
339 struct nulink_usb_handle_s *h = handle;
340
341 LOG_DEBUG("nulink_usb_step");
342
343 assert(handle);
344
345 nulink_usb_init_buffer(handle, 4 * 1);
346 /* set command ID */
347 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_MCU_STEP_RUN);
348 h->cmdidx += 4;
349
350 int res = nulink_usb_xfer(handle, h->databuf, 4 * 4);
351
352 LOG_DEBUG("Nu-Link pc 0x%08" PRIx32, le_to_h_u32(h->databuf + 4));
353
354 return res;
355 }
356
357 static int nulink_usb_read_reg(void *handle, int num, uint32_t *val)
358 {
359 struct nulink_usb_handle_s *h = handle;
360
361 assert(handle);
362
363 nulink_usb_init_buffer(handle, 8 + 12 * 1);
364 /* set command ID */
365 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_REG);
366 h->cmdidx += 4;
367 /* Count of registers */
368 h->cmdbuf[h->cmdidx] = 1;
369 h->cmdidx += 1;
370 /* Array of bool value (u8ReadOld) */
371 h->cmdbuf[h->cmdidx] = 0xFF;
372 h->cmdidx += 1;
373 /* Array of bool value (u8Verify) */
374 h->cmdbuf[h->cmdidx] = 0x00;
375 h->cmdidx += 1;
376 /* ignore */
377 h->cmdbuf[h->cmdidx] = 0;
378 h->cmdidx += 1;
379 /* u32Addr */
380 h_u32_to_le(h->cmdbuf + h->cmdidx, num);
381 h->cmdidx += 4;
382 /* u32Data */
383 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
384 h->cmdidx += 4;
385 /* u32Mask */
386 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
387 h->cmdidx += 4;
388
389 int res = nulink_usb_xfer(handle, h->databuf, 4 * 2);
390
391 *val = le_to_h_u32(h->databuf + 4 * 1);
392
393 return res;
394 }
395
396 static int nulink_usb_write_reg(void *handle, int num, uint32_t val)
397 {
398 struct nulink_usb_handle_s *h = handle;
399
400 assert(handle);
401
402 nulink_usb_init_buffer(handle, 8 + 12 * 1);
403 /* set command ID */
404 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_REG);
405 h->cmdidx += 4;
406 /* Count of registers */
407 h->cmdbuf[h->cmdidx] = 1;
408 h->cmdidx += 1;
409 /* Array of bool value (u8ReadOld) */
410 h->cmdbuf[h->cmdidx] = 0x00;
411 h->cmdidx += 1;
412 /* Array of bool value (u8Verify) */
413 h->cmdbuf[h->cmdidx] = 0x00;
414 h->cmdidx += 1;
415 /* ignore */
416 h->cmdbuf[h->cmdidx] = 0;
417 h->cmdidx += 1;
418 /* u32Addr */
419 h_u32_to_le(h->cmdbuf + h->cmdidx, num);
420 h->cmdidx += 4;
421 /* u32Data */
422 h_u32_to_le(h->cmdbuf + h->cmdidx, val);
423 h->cmdidx += 4;
424 /* u32Mask */
425 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
426 h->cmdidx += 4;
427
428 return nulink_usb_xfer(handle, h->databuf, 4 * 2);
429 }
430
431 static int nulink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len,
432 uint8_t *buffer)
433 {
434 int res = ERROR_OK;
435 uint32_t offset = 0;
436 uint32_t bytes_remaining = 12;
437 struct nulink_usb_handle_s *h = handle;
438
439 LOG_DEBUG("nulink_usb_read_mem8: addr 0x%08" PRIx32 ", len %" PRId16, addr, len);
440
441 assert(handle);
442
443 /* check whether data is word aligned */
444 if (addr % 4) {
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);
451
452 addr = aligned_addr;
453 }
454
455 while (len) {
456 unsigned int count;
457
458 if (len < bytes_remaining)
459 bytes_remaining = len;
460
461 if (len < 4)
462 count = 1;
463 else
464 count = 2;
465
466 nulink_usb_init_buffer(handle, 8 + 12 * count);
467 /* set command ID */
468 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
469 h->cmdidx += 4;
470 /* Count of registers */
471 h->cmdbuf[h->cmdidx] = count;
472 h->cmdidx += 1;
473 /* Array of bool value (u8ReadOld) */
474 h->cmdbuf[h->cmdidx] = 0xFF;
475 h->cmdidx += 1;
476 /* Array of bool value (u8Verify) */
477 h->cmdbuf[h->cmdidx] = 0x00;
478 h->cmdidx += 1;
479 /* ignore */
480 h->cmdbuf[h->cmdidx] = 0;
481 h->cmdidx += 1;
482
483 for (unsigned int i = 0; i < count; i++) {
484 /* u32Addr */
485 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
486 h->cmdidx += 4;
487 /* u32Data */
488 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
489 h->cmdidx += 4;
490 /* u32Mask */
491 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
492 h->cmdidx += 4;
493 /* proceed to the next one */
494 addr += 4;
495 }
496
497 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
498 if (res != ERROR_OK)
499 break;
500
501 /* fill in the output buffer */
502 for (unsigned int i = 0; i < count; i++) {
503 if (i == 0)
504 memcpy(buffer, h->databuf + 4 + offset, len);
505 else
506 memcpy(buffer + 2 * i, h->databuf + 4 * (2 * i + 1), len - 2);
507 }
508
509 if (len >= bytes_remaining)
510 len -= bytes_remaining;
511 }
512
513 return res;
514 }
515
516 static int nulink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len,
517 const uint8_t *buffer)
518 {
519 int res = ERROR_OK;
520 uint32_t offset = 0;
521 uint32_t bytes_remaining = 12;
522 struct nulink_usb_handle_s *h = handle;
523
524 LOG_DEBUG("nulink_usb_write_mem8: addr 0x%08" PRIx32 ", len %" PRIu16, addr, len);
525
526 assert(handle);
527
528 /* check whether data is word aligned */
529 if (addr % 4) {
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);
536
537 addr = aligned_addr;
538 }
539
540 while (len) {
541 unsigned int count;
542
543 if (len < bytes_remaining)
544 bytes_remaining = len;
545
546 if (len < 4)
547 count = 1;
548 else
549 count = 2;
550
551 nulink_usb_init_buffer(handle, 8 + 12 * count);
552 /* set command ID */
553 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
554 h->cmdidx += 4;
555 /* Count of registers */
556 h->cmdbuf[h->cmdidx] = count;
557 h->cmdidx += 1;
558 /* Array of bool value (u8ReadOld) */
559 h->cmdbuf[h->cmdidx] = 0x00;
560 h->cmdidx += 1;
561 /* Array of bool value (u8Verify) */
562 h->cmdbuf[h->cmdidx] = 0x00;
563 h->cmdidx += 1;
564 /* ignore */
565 h->cmdbuf[h->cmdidx] = 0;
566 h->cmdidx += 1;
567
568 for (unsigned int i = 0; i < count; i++) {
569 /* u32Addr */
570 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
571 h->cmdidx += 4;
572 /* u32Data */
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);
576 h->cmdidx += 4;
577 /* u32Mask */
578 if (i == 0) {
579 if (offset == 0) {
580 if (len == 1) {
581 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFF00UL);
582 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFFFF00", i);
583 } else {
584 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFF0000UL);
585 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFF0000", i);
586 }
587 } else {
588 if (len == 1) {
589 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFF00FFFFUL);
590 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFF00FFFF", i);
591
592 } else {
593 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x0000FFFFUL);
594 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x0000FFFF", i);
595 }
596 }
597 } else {
598 if (len == 4) {
599 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFF0000UL);
600 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0xFFFF0000", i);
601 } else {
602 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000UL);
603 LOG_DEBUG("nulink_usb_write_mem8: count(%u), mask: 0x00000000", i);
604 }
605 }
606 h->cmdidx += 4;
607
608 /* proceed to the next one */
609 addr += 4;
610 buffer += 4;
611 }
612
613 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
614 if (res != ERROR_OK)
615 break;
616
617 if (len >= bytes_remaining)
618 len -= bytes_remaining;
619 }
620
621 return res;
622 }
623
624 static int nulink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len,
625 uint8_t *buffer)
626 {
627 int res = ERROR_OK;
628 uint32_t bytes_remaining = 12;
629 struct nulink_usb_handle_s *h = handle;
630
631 assert(handle);
632
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;
637 }
638
639 while (len) {
640 if (len < bytes_remaining)
641 bytes_remaining = len;
642
643 unsigned int count = bytes_remaining / 4;
644
645 nulink_usb_init_buffer(handle, 8 + 12 * count);
646 /* set command ID */
647 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
648 h->cmdidx += 4;
649 /* Count of registers */
650 h->cmdbuf[h->cmdidx] = count;
651 h->cmdidx += 1;
652 /* Array of bool value (u8ReadOld) */
653 h->cmdbuf[h->cmdidx] = 0xFF;
654 h->cmdidx += 1;
655 /* Array of bool value (u8Verify) */
656 h->cmdbuf[h->cmdidx] = 0x00;
657 h->cmdidx += 1;
658 /* ignore */
659 h->cmdbuf[h->cmdidx] = 0;
660 h->cmdidx += 1;
661
662 for (unsigned int i = 0; i < count; i++) {
663 /* u32Addr */
664 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
665 h->cmdidx += 4;
666 /* u32Data */
667 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
668 h->cmdidx += 4;
669 /* u32Mask */
670 h_u32_to_le(h->cmdbuf + h->cmdidx, 0xFFFFFFFFUL);
671 h->cmdidx += 4;
672 /* proceed to the next one */
673 addr += 4;
674 }
675
676 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
677
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);
681 buffer += 4;
682 }
683
684 if (len >= bytes_remaining)
685 len -= bytes_remaining;
686 else
687 len = 0;
688 }
689
690 return res;
691 }
692
693 static int nulink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len,
694 const uint8_t *buffer)
695 {
696 int res = ERROR_OK;
697 uint32_t bytes_remaining = 12;
698 struct nulink_usb_handle_s *h = handle;
699
700 assert(handle);
701
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;
706 }
707
708 while (len) {
709 if (len < bytes_remaining)
710 bytes_remaining = len;
711
712 unsigned int count = bytes_remaining / 4;
713
714 nulink_usb_init_buffer(handle, 8 + 12 * count);
715 /* set command ID */
716 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_WRITE_RAM);
717 h->cmdidx += 4;
718 /* Count of registers */
719 h->cmdbuf[h->cmdidx] = count;
720 h->cmdidx += 1;
721 /* Array of bool value (u8ReadOld) */
722 h->cmdbuf[h->cmdidx] = 0x00;
723 h->cmdidx += 1;
724 /* Array of bool value (u8Verify) */
725 h->cmdbuf[h->cmdidx] = 0x00;
726 h->cmdidx += 1;
727 /* ignore */
728 h->cmdbuf[h->cmdidx] = 0;
729 h->cmdidx += 1;
730
731 for (unsigned int i = 0; i < count; i++) {
732 /* u32Addr */
733 h_u32_to_le(h->cmdbuf + h->cmdidx, addr);
734 h->cmdidx += 4;
735 /* u32Data */
736 uint32_t u32buffer = buf_get_u32(buffer, 0, 32);
737 h_u32_to_le(h->cmdbuf + h->cmdidx, u32buffer);
738 h->cmdidx += 4;
739 /* u32Mask */
740 h_u32_to_le(h->cmdbuf + h->cmdidx, 0x00000000);
741 h->cmdidx += 4;
742
743 /* proceed to the next one */
744 addr += 4;
745 buffer += 4;
746 }
747
748 res = nulink_usb_xfer(handle, h->databuf, 4 * count * 2);
749
750 if (len >= bytes_remaining)
751 len -= bytes_remaining;
752 else
753 len = 0;
754 }
755
756 return res;
757 }
758
759 static uint32_t nulink_max_block_size(uint32_t tar_autoincr_block, uint32_t address)
760 {
761 uint32_t max_tar_block = (tar_autoincr_block - ((tar_autoincr_block - 1) & address));
762
763 if (max_tar_block == 0)
764 max_tar_block = 4;
765
766 return max_tar_block;
767 }
768
769 static int nulink_usb_read_mem(void *handle, uint32_t addr, uint32_t size,
770 uint32_t count, uint8_t *buffer)
771 {
772 int retval = ERROR_OK;
773 struct nulink_usb_handle_s *h = handle;
774
775 /* calculate byte count */
776 count *= size;
777
778 while (count) {
779 uint32_t bytes_remaining = nulink_max_block_size(h->max_mem_packet, addr);
780
781 if (count < bytes_remaining)
782 bytes_remaining = count;
783
784 if (bytes_remaining >= 4)
785 size = 4;
786
787 /* the nulink only supports 8/32bit memory read/writes
788 * honour 32bit, all others will be handled as 8bit access */
789 if (size == 4) {
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 */
797
798 /* we first need to check for any unaligned bytes */
799 if (addr % 4) {
800 uint32_t head_bytes = 4 - (addr % 4);
801 retval = nulink_usb_read_mem8(handle, addr, head_bytes, buffer);
802 if (retval != ERROR_OK)
803 return retval;
804 buffer += head_bytes;
805 addr += head_bytes;
806 count -= head_bytes;
807 bytes_remaining -= head_bytes;
808 }
809
810 if (bytes_remaining % 4)
811 retval = nulink_usb_read_mem(handle, addr, 1, bytes_remaining, buffer);
812 else
813 retval = nulink_usb_read_mem32(handle, addr, bytes_remaining, buffer);
814 } else {
815 retval = nulink_usb_read_mem8(handle, addr, bytes_remaining, buffer);
816 }
817
818 if (retval != ERROR_OK)
819 return retval;
820
821 buffer += bytes_remaining;
822 addr += bytes_remaining;
823 count -= bytes_remaining;
824 }
825
826 return retval;
827 }
828
829 static int nulink_usb_write_mem(void *handle, uint32_t addr, uint32_t size,
830 uint32_t count, const uint8_t *buffer)
831 {
832 int retval = ERROR_OK;
833 struct nulink_usb_handle_s *h = handle;
834
835 if (addr < ARM_SRAM_BASE) {
836 LOG_DEBUG("nulink_usb_write_mem: address below ARM_SRAM_BASE, not supported.\n");
837 return retval;
838 }
839
840 /* calculate byte count */
841 count *= size;
842
843 while (count) {
844 uint32_t bytes_remaining = nulink_max_block_size(h->max_mem_packet, addr);
845
846 if (count < bytes_remaining)
847 bytes_remaining = count;
848
849 if (bytes_remaining >= 4)
850 size = 4;
851
852 /* the nulink only supports 8/32bit memory read/writes
853 * honour 32bit, all others will be handled as 8bit access */
854 if (size == 4) {
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 */
862
863 /* we first need to check for any unaligned bytes */
864 if (addr % 4) {
865 uint32_t head_bytes = 4 - (addr % 4);
866 retval = nulink_usb_write_mem8(handle, addr, head_bytes, buffer);
867 if (retval != ERROR_OK)
868 return retval;
869 buffer += head_bytes;
870 addr += head_bytes;
871 count -= head_bytes;
872 bytes_remaining -= head_bytes;
873 }
874
875 if (bytes_remaining % 4)
876 retval = nulink_usb_write_mem(handle, addr, 1, bytes_remaining, buffer);
877 else
878 retval = nulink_usb_write_mem32(handle, addr, bytes_remaining, buffer);
879
880 } else {
881 retval = nulink_usb_write_mem8(handle, addr, bytes_remaining, buffer);
882 }
883
884 if (retval != ERROR_OK)
885 return retval;
886
887 buffer += bytes_remaining;
888 addr += bytes_remaining;
889 count -= bytes_remaining;
890 }
891
892 return retval;
893 }
894
895 static int nulink_usb_override_target(const char *targetname)
896 {
897 LOG_DEBUG("nulink_usb_override_target");
898
899 return !strcmp(targetname, "cortex_m");
900 }
901
902 static int nulink_speed(void *handle, int khz, bool query)
903 {
904 struct nulink_usb_handle_s *h = handle;
905 unsigned long max_ice_clock = khz;
906
907 LOG_DEBUG("nulink_speed: query %s", query ? "yes" : "no");
908
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;
915 else
916 max_ice_clock = max_ice_clock / 100 * 100;
917
918 LOG_DEBUG("Nu-Link nulink_speed: %lu", max_ice_clock);
919
920 if (!query) {
921 nulink_usb_init_buffer(handle, 4 * 6);
922 /* set command ID */
923 h_u32_to_le(h->cmdbuf + h->cmdidx, CMD_SET_CONFIG);
924 h->cmdidx += 4;
925 /* set max SWD clock */
926 h_u32_to_le(h->cmdbuf + h->cmdidx, max_ice_clock);
927 h->cmdidx += 4;
928 /* chip type: NUC_CHIP_TYPE_GENERAL_V6M */
929 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
930 h->cmdidx += 4;
931 /* IO voltage */
932 h_u32_to_le(h->cmdbuf + h->cmdidx, 5000);
933 h->cmdidx += 4;
934 /* If supply voltage to target or not */
935 h_u32_to_le(h->cmdbuf + h->cmdidx, 0);
936 h->cmdidx += 4;
937 /* USB_FUNC_E: USB_FUNC_HID_BULK */
938 h_u32_to_le(h->cmdbuf + h->cmdidx, 2);
939 h->cmdidx += 4;
940
941 nulink_usb_xfer(handle, h->databuf, 4 * 3);
942
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);
951 }
952
953 return max_ice_clock;
954 }
955
956 static int nulink_usb_close(void *handle)
957 {
958 struct nulink_usb_handle_s *h = handle;
959
960 LOG_DEBUG("nulink_usb_close");
961
962 if (h && h->dev_handle)
963 hid_close(h->dev_handle);
964
965 free(h);
966
967 hid_exit();
968
969 return ERROR_OK;
970 }
971
972 static int nulink_usb_open(struct hl_interface_param_s *param, void **fd)
973 {
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;
978
979 LOG_DEBUG("nulink_usb_open");
980
981 if (param->transport != HL_TRANSPORT_SWD)
982 return TARGET_UNKNOWN;
983
984 if (!param->vid[0] && !param->pid[0]) {
985 LOG_ERROR("Missing vid/pid");
986 return ERROR_FAIL;
987 }
988
989 if (hid_init() != 0) {
990 LOG_ERROR("unable to open HIDAPI");
991 return ERROR_FAIL;
992 }
993
994 struct nulink_usb_handle_s *h = calloc(1, sizeof(*h));
995 if (!h) {
996 LOG_ERROR("Out of memory");
997 goto error_open;
998 }
999
1000 if (param->serial) {
1001 size_t len = mbstowcs(NULL, param->serial, 0);
1002
1003 target_serial = calloc(len + 1, sizeof(wchar_t));
1004 if (!target_serial) {
1005 LOG_ERROR("Out of memory");
1006 goto error_open;
1007 }
1008
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;
1013 }
1014 }
1015
1016 devs = hid_enumerate(0, 0);
1017 cur_dev = devs;
1018 while (cur_dev) {
1019 bool found = false;
1020
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) {
1023 found = true;
1024 break;
1025 }
1026 }
1027
1028 if (found) {
1029 if (!target_serial)
1030 break;
1031 if (cur_dev->serial_number && wcscmp(target_serial, cur_dev->serial_number) == 0)
1032 break;
1033 }
1034
1035 cur_dev = cur_dev->next;
1036 }
1037 if (cur_dev) {
1038 target_vid = cur_dev->vendor_id;
1039 target_pid = cur_dev->product_id;
1040 }
1041
1042 hid_free_enumeration(devs);
1043
1044 if (target_vid == 0 && target_pid == 0) {
1045 LOG_ERROR("unable to find Nu-Link");
1046 goto error_open;
1047 }
1048
1049 hid_device *dev = hid_open(target_vid, target_pid, target_serial);
1050 if (!dev) {
1051 LOG_ERROR("unable to open Nu-Link device 0x%" PRIx16 ":0x%" PRIx16, target_vid, target_pid);
1052 goto error_open;
1053 }
1054
1055 h->dev_handle = dev;
1056 h->usbcmdidx = 0;
1057 h->hardware_config = 0;
1058 h->max_packet_size = NULINK_HID_MAX_SIZE;
1059
1060 /* get the device version */
1061 int err = nulink_usb_version(h);
1062 if (err != ERROR_OK)
1063 goto error_open;
1064
1065 /* SWD clock rate : 1MHz */
1066 nulink_speed(h, 1000, false);
1067
1068 /* get cpuid, so we can determine the max page size
1069 * start with a safe default */
1070 h->max_mem_packet = (1 << 10);
1071
1072 LOG_DEBUG("nulink_usb_open: we manually perform nulink_usb_reset");
1073 nulink_usb_reset(h);
1074
1075 *fd = h;
1076
1077 free(target_serial);
1078 return ERROR_OK;
1079
1080 error_open:
1081 nulink_usb_close(h);
1082 free(target_serial);
1083
1084 return ERROR_FAIL;
1085 }
1086
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,
1104 };

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)