nds32: support multi-target debugging
[openocd.git] / src / target / nds32_v3_common.c
1 /***************************************************************************
2 * Copyright (C) 2013 Andes Technology *
3 * Hsiangkai Wang <hkwang@andestech.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, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "breakpoints.h"
26 #include "nds32_reg.h"
27 #include "nds32_disassembler.h"
28 #include "nds32.h"
29 #include "nds32_aice.h"
30 #include "nds32_v3_common.h"
31
32 static struct nds32_v3_common_callback *v3_common_callback;
33
34 static int nds32_v3_register_mapping(struct nds32 *nds32, int reg_no)
35 {
36 if (reg_no == PC)
37 return IR11;
38
39 return reg_no;
40 }
41
42 static int nds32_v3_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
43 {
44 uint32_t edmsw;
45 struct aice_port_s *aice = target_to_aice(nds32->target);
46 aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &edmsw);
47
48 *reason = (edmsw >> 12) & 0x0F;
49
50 return ERROR_OK;
51 }
52
53 /**
54 * Save processor state. This is called after a HALT instruction
55 * succeeds, and on other occasions the processor enters debug mode
56 * (breakpoint, watchpoint, etc).
57 */
58 static int nds32_v3_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
59 {
60 LOG_DEBUG("nds32_v3_debug_entry");
61
62 enum target_state backup_state = nds32->target->state;
63 nds32->target->state = TARGET_HALTED;
64
65 if (nds32->init_arch_info_after_halted == false) {
66 /* init architecture info according to config registers */
67 CHECK_RETVAL(nds32_config(nds32));
68
69 nds32->init_arch_info_after_halted = true;
70 }
71
72 /* REVISIT entire cache should already be invalid !!! */
73 register_cache_invalidate(nds32->core_cache);
74
75 /* deactivate all hardware breakpoints */
76 CHECK_RETVAL(v3_common_callback->deactivate_hardware_breakpoint(nds32->target));
77
78 if (enable_watchpoint)
79 CHECK_RETVAL(v3_common_callback->deactivate_hardware_watchpoint(nds32->target));
80
81 struct breakpoint *syscall_break = &(nds32->syscall_break);
82 if (nds32->virtual_hosting) {
83 if (syscall_break->set) {
84 /** disable virtual hosting */
85
86 /* remove breakpoint at syscall entry */
87 target_remove_breakpoint(nds32->target, syscall_break);
88 syscall_break->set = 0;
89
90 uint32_t value_pc;
91 nds32_get_mapped_reg(nds32, PC, &value_pc);
92 if (value_pc == syscall_break->address)
93 /** process syscall for virtual hosting */
94 nds32->hit_syscall = true;
95 }
96 }
97
98 if (ERROR_OK != nds32_examine_debug_reason(nds32)) {
99 nds32->target->state = backup_state;
100
101 /* re-activate all hardware breakpoints & watchpoints */
102 CHECK_RETVAL(v3_common_callback->activate_hardware_breakpoint(nds32->target));
103
104 if (enable_watchpoint)
105 CHECK_RETVAL(v3_common_callback->activate_hardware_watchpoint(nds32->target));
106
107 return ERROR_FAIL;
108 }
109
110 /* Save registers. */
111 nds32_full_context(nds32);
112
113 /* check interrupt level */
114 v3_common_callback->check_interrupt_stack(nds32);
115
116 return ERROR_OK;
117 }
118
119 /**
120 * Restore processor state.
121 */
122 static int nds32_v3_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
123 {
124 LOG_DEBUG("nds32_v3_leave_debug_state");
125
126 struct target *target = nds32->target;
127
128 /* activate all hardware breakpoints */
129 CHECK_RETVAL(v3_common_callback->activate_hardware_breakpoint(target));
130
131 if (enable_watchpoint) {
132 /* activate all watchpoints */
133 CHECK_RETVAL(v3_common_callback->activate_hardware_watchpoint(target));
134 }
135
136 /* restore interrupt stack */
137 v3_common_callback->restore_interrupt_stack(nds32);
138
139 /* REVISIT once we start caring about MMU and cache state,
140 * address it here ...
141 */
142
143 /* restore PSW, PC, and R0 ... after flushing any modified
144 * registers.
145 */
146 CHECK_RETVAL(nds32_restore_context(target));
147
148 if (nds32->virtual_hosting) {
149 /** enable virtual hosting */
150 uint32_t value_ir3;
151 uint32_t entry_size;
152 uint32_t syscall_address;
153
154 /* get syscall entry address */
155 nds32_get_mapped_reg(nds32, IR3, &value_ir3);
156 entry_size = 0x4 << (((value_ir3 >> 14) & 0x3) << 1);
157 syscall_address = (value_ir3 & 0xFFFF0000) + entry_size * 8; /* The index of SYSCALL is 8 */
158
159 if (nds32->hit_syscall) {
160 /* single step to skip syscall entry */
161 /* use IRET to skip syscall */
162 struct aice_port_s *aice = target_to_aice(target);
163 uint32_t value_ir9;
164 uint32_t value_ir6;
165 uint32_t syscall_id;
166
167 nds32_get_mapped_reg(nds32, IR6, &value_ir6);
168 syscall_id = (value_ir6 >> 16) & 0x7FFF;
169
170 if (syscall_id == NDS32_SYSCALL_EXIT) {
171 /* If target hits exit syscall, do not use IRET to skip handler. */
172 aice_step(aice);
173 } else {
174 /* use api->read/write_reg to skip nds32 register cache */
175 uint32_t value_dimbr;
176 aice_read_debug_reg(aice, NDS_EDM_SR_DIMBR, &value_dimbr);
177 aice_write_register(aice, IR11, value_dimbr + 0xC);
178
179 aice_read_register(aice, IR9, &value_ir9);
180 value_ir9 += 4; /* syscall is always 4 bytes */
181 aice_write_register(aice, IR9, value_ir9);
182
183 /* backup hardware breakpoint 0 */
184 uint32_t backup_bpa, backup_bpam, backup_bpc;
185 aice_read_debug_reg(aice, NDS_EDM_SR_BPA0, &backup_bpa);
186 aice_read_debug_reg(aice, NDS_EDM_SR_BPAM0, &backup_bpam);
187 aice_read_debug_reg(aice, NDS_EDM_SR_BPC0, &backup_bpc);
188
189 /* use hardware breakpoint 0 to stop cpu after skipping syscall */
190 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, value_ir9);
191 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, 0);
192 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, 0xA);
193
194 /* Execute two IRET.
195 * First IRET is used to quit debug mode.
196 * Second IRET is used to quit current syscall. */
197 uint32_t dim_inst[4] = {NOP, NOP, IRET, IRET};
198 aice_execute(aice, dim_inst, 4);
199
200 /* restore origin hardware breakpoint 0 */
201 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, backup_bpa);
202 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, backup_bpam);
203 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, backup_bpc);
204 }
205
206 nds32->hit_syscall = false;
207 }
208
209 /* insert breakpoint at syscall entry */
210 struct breakpoint *syscall_break = &(nds32->syscall_break);
211
212 syscall_break->address = syscall_address;
213 syscall_break->type = BKPT_SOFT;
214 syscall_break->set = 1;
215 target_add_breakpoint(target, syscall_break);
216 }
217
218 return ERROR_OK;
219 }
220
221 static int nds32_v3_get_exception_address(struct nds32 *nds32,
222 uint32_t *address, uint32_t reason)
223 {
224 LOG_DEBUG("nds32_v3_get_exception_address");
225
226 struct aice_port_s *aice = target_to_aice(nds32->target);
227 struct target *target = nds32->target;
228 uint32_t edmsw;
229 uint32_t edm_cfg;
230 uint32_t match_bits;
231 uint32_t match_count;
232 int32_t i;
233 static int32_t number_of_hard_break;
234 uint32_t bp_control;
235
236 if (number_of_hard_break == 0) {
237 aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
238 number_of_hard_break = (edm_cfg & 0x7) + 1;
239 }
240
241 aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &edmsw);
242 /* clear matching bits (write-one-clear) */
243 aice_write_debug_reg(aice, NDS_EDM_SR_EDMSW, edmsw);
244 match_bits = (edmsw >> 4) & 0xFF;
245 match_count = 0;
246 for (i = 0 ; i < number_of_hard_break ; i++) {
247 if (match_bits & (1 << i)) {
248 aice_read_debug_reg(aice, NDS_EDM_SR_BPA0 + i, address);
249 match_count++;
250
251 /* If target hits multiple read/access watchpoint,
252 * select the first one. */
253 aice_read_debug_reg(aice, NDS_EDM_SR_BPC0 + i, &bp_control);
254 if (0x3 == (bp_control & 0x3)) {
255 match_count = 1;
256 break;
257 }
258 }
259 }
260
261 if (match_count > 1) { /* multiple hits */
262 *address = 0;
263 return ERROR_OK;
264 } else if (match_count == 1) {
265 uint32_t val_pc;
266 uint32_t opcode;
267 struct nds32_instruction instruction;
268 struct watchpoint *wp;
269 bool hit;
270
271 nds32_get_mapped_reg(nds32, PC, &val_pc);
272
273 if ((NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE == reason) ||
274 (NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE == reason)) {
275 if (edmsw & 0x4) /* check EDMSW.IS_16BIT */
276 val_pc -= 2;
277 else
278 val_pc -= 4;
279 }
280
281 nds32_read_opcode(nds32, val_pc, &opcode);
282 nds32_evaluate_opcode(nds32, opcode, val_pc, &instruction);
283
284 LOG_DEBUG("PC: 0x%08x, access start: 0x%08x, end: 0x%08x", val_pc,
285 instruction.access_start, instruction.access_end);
286
287 /* check if multiple hits in the access range */
288 uint32_t in_range_watch_count = 0;
289 for (wp = target->watchpoints; wp; wp = wp->next) {
290 if ((instruction.access_start <= wp->address) &&
291 (wp->address < instruction.access_end))
292 in_range_watch_count++;
293 }
294 if (in_range_watch_count > 1) {
295 /* Hit LSMW instruction. */
296 *address = 0;
297 return ERROR_OK;
298 }
299
300 /* dispel false match */
301 hit = false;
302 for (wp = target->watchpoints; wp; wp = wp->next) {
303 if (((*address ^ wp->address) & (~wp->mask)) == 0) {
304 uint32_t watch_start;
305 uint32_t watch_end;
306
307 watch_start = wp->address;
308 watch_end = wp->address + wp->length;
309
310 if ((watch_end <= instruction.access_start) ||
311 (instruction.access_end <= watch_start))
312 continue;
313
314 hit = true;
315 break;
316 }
317 }
318
319 if (hit)
320 return ERROR_OK;
321 else
322 return ERROR_FAIL;
323 } else if (match_count == 0) {
324 /* global stop is precise exception */
325 if ((NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP == reason) && nds32->global_stop) {
326 /* parse instruction to get correct access address */
327 uint32_t val_pc;
328 uint32_t opcode;
329 struct nds32_instruction instruction;
330
331 nds32_get_mapped_reg(nds32, PC, &val_pc);
332 nds32_read_opcode(nds32, val_pc, &opcode);
333 nds32_evaluate_opcode(nds32, opcode, val_pc, &instruction);
334
335 *address = instruction.access_start;
336
337 return ERROR_OK;
338 }
339 }
340
341 *address = 0xFFFFFFFF;
342 return ERROR_FAIL;
343 }
344
345 void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback)
346 {
347 v3_common_callback = callback;
348 }
349
350 /** target_type functions: */
351 /* target request support */
352 int nds32_v3_target_request_data(struct target *target,
353 uint32_t size, uint8_t *buffer)
354 {
355 /* AndesCore could use DTR register to communicate with OpenOCD
356 * to output messages
357 * Target data will be put in buffer
358 * The format of DTR is as follow
359 * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
360 * target_req_cmd has three possible values:
361 * TARGET_REQ_TRACEMSG
362 * TARGET_REQ_DEBUGMSG
363 * TARGET_REQ_DEBUGCHAR
364 * if size == 0, target will call target_asciimsg(),
365 * else call target_hexmsg()
366 */
367 LOG_WARNING("Not implemented: %s", __func__);
368
369 return ERROR_OK;
370 }
371
372 int nds32_v3_soft_reset_halt(struct target *target)
373 {
374 struct aice_port_s *aice = target_to_aice(target);
375 return aice_assert_srst(aice, AICE_RESET_HOLD);
376 }
377
378 int nds32_v3_checksum_memory(struct target *target,
379 uint32_t address, uint32_t count, uint32_t *checksum)
380 {
381 LOG_WARNING("Not implemented: %s", __func__);
382
383 return ERROR_FAIL;
384 }
385
386 /**
387 * find out which watchpoint hits
388 * get exception address and compare the address to watchpoints
389 */
390 int nds32_v3_hit_watchpoint(struct target *target,
391 struct watchpoint **hit_watchpoint)
392 {
393 static struct watchpoint scan_all_watchpoint;
394
395 uint32_t exception_address;
396 struct watchpoint *wp;
397 struct nds32 *nds32 = target_to_nds32(target);
398
399 exception_address = nds32->watched_address;
400
401 if (exception_address == 0xFFFFFFFF)
402 return ERROR_FAIL;
403
404 if (exception_address == 0) {
405 scan_all_watchpoint.address = 0;
406 scan_all_watchpoint.rw = WPT_WRITE;
407 scan_all_watchpoint.next = 0;
408 scan_all_watchpoint.unique_id = 0x5CA8;
409
410 *hit_watchpoint = &scan_all_watchpoint;
411 return ERROR_OK;
412 }
413
414 for (wp = target->watchpoints; wp; wp = wp->next) {
415 if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
416 *hit_watchpoint = wp;
417
418 return ERROR_OK;
419 }
420 }
421
422 return ERROR_FAIL;
423 }
424
425 int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32)
426 {
427 nds32->register_map = nds32_v3_register_mapping;
428 nds32->get_debug_reason = nds32_v3_get_debug_reason;
429 nds32->enter_debug_state = nds32_v3_debug_entry;
430 nds32->leave_debug_state = nds32_v3_leave_debug_state;
431 nds32->get_watched_address = nds32_v3_get_exception_address;
432
433 /* Init target->arch_info in nds32_init_arch_info().
434 * After this, user could use target_to_nds32() to get nds32 object */
435 nds32_init_arch_info(target, nds32);
436
437 return ERROR_OK;
438 }
439
440 int nds32_v3_run_algorithm(struct target *target,
441 int num_mem_params,
442 struct mem_param *mem_params,
443 int num_reg_params,
444 struct reg_param *reg_params,
445 uint32_t entry_point,
446 uint32_t exit_point,
447 int timeout_ms,
448 void *arch_info)
449 {
450 LOG_WARNING("Not implemented: %s", __func__);
451
452 return ERROR_FAIL;
453 }
454
455 int nds32_v3_read_buffer(struct target *target, uint32_t address,
456 uint32_t size, uint8_t *buffer)
457 {
458 struct nds32 *nds32 = target_to_nds32(target);
459 struct nds32_memory *memory = &(nds32->memory);
460
461 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
462 (target->state != TARGET_HALTED)) {
463 LOG_WARNING("target was not halted");
464 return ERROR_TARGET_NOT_HALTED;
465 }
466
467 uint32_t physical_address;
468 /* BUG: If access range crosses multiple pages, the translation will not correct
469 * for second page or so. */
470
471 /* When DEX is set to one, hardware will enforce the following behavior without
472 * modifying the corresponding control bits in PSW.
473 *
474 * Disable all interrupts
475 * Become superuser mode
476 * Turn off IT/DT
477 * Use MMU_CFG.DE as the data access endian
478 * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
479 * Disable audio special features
480 * Disable inline function call
481 *
482 * Because hardware will turn off IT/DT by default, it MUST translate virtual address
483 * to physical address.
484 */
485 if (ERROR_OK == target->type->virt2phys(target, address, &physical_address))
486 address = physical_address;
487 else
488 return ERROR_FAIL;
489
490 int result;
491 struct aice_port_s *aice = target_to_aice(target);
492 /* give arbitrary initial value to avoid warning messages */
493 enum nds_memory_access origin_access_channel = NDS_MEMORY_ACC_CPU;
494
495 if (nds32->hit_syscall) {
496 /* Use bus mode to access memory during virtual hosting */
497 origin_access_channel = memory->access_channel;
498 memory->access_channel = NDS_MEMORY_ACC_BUS;
499 aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
500 }
501
502 result = nds32_read_buffer(target, address, size, buffer);
503
504 if (nds32->hit_syscall) {
505 /* Restore access_channel after virtual hosting */
506 memory->access_channel = origin_access_channel;
507 aice_memory_access(aice, origin_access_channel);
508 }
509
510 return result;
511 }
512
513 int nds32_v3_write_buffer(struct target *target, uint32_t address,
514 uint32_t size, const uint8_t *buffer)
515 {
516 struct nds32 *nds32 = target_to_nds32(target);
517 struct nds32_memory *memory = &(nds32->memory);
518
519 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
520 (target->state != TARGET_HALTED)) {
521 LOG_WARNING("target was not halted");
522 return ERROR_TARGET_NOT_HALTED;
523 }
524
525 uint32_t physical_address;
526 /* BUG: If access range crosses multiple pages, the translation will not correct
527 * for second page or so. */
528
529 /* When DEX is set to one, hardware will enforce the following behavior without
530 * modifying the corresponding control bits in PSW.
531 *
532 * Disable all interrupts
533 * Become superuser mode
534 * Turn off IT/DT
535 * Use MMU_CFG.DE as the data access endian
536 * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
537 * Disable audio special features
538 * Disable inline function call
539 *
540 * Because hardware will turn off IT/DT by default, it MUST translate virtual address
541 * to physical address.
542 */
543 if (ERROR_OK == target->type->virt2phys(target, address, &physical_address))
544 address = physical_address;
545 else
546 return ERROR_FAIL;
547
548 if (nds32->hit_syscall) {
549 struct aice_port_s *aice = target_to_aice(target);
550 enum nds_memory_access origin_access_channel;
551 origin_access_channel = memory->access_channel;
552
553 /* If target has no cache, use BUS mode to access memory. */
554 if ((memory->dcache.line_size == 0)
555 || (memory->dcache.enable == false)) {
556 /* There is no Dcache or Dcache is disabled. */
557 memory->access_channel = NDS_MEMORY_ACC_BUS;
558 aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
559 }
560
561 int result;
562 result = nds32_gdb_fileio_write_memory(nds32, address, size, buffer);
563
564 if (NDS_MEMORY_ACC_CPU == origin_access_channel) {
565 memory->access_channel = NDS_MEMORY_ACC_CPU;
566 aice_memory_access(aice, NDS_MEMORY_ACC_CPU);
567 }
568
569 return result;
570 }
571
572 return nds32_write_buffer(target, address, size, buffer);
573 }
574
575 int nds32_v3_read_memory(struct target *target, uint32_t address,
576 uint32_t size, uint32_t count, uint8_t *buffer)
577 {
578 struct nds32 *nds32 = target_to_nds32(target);
579 struct nds32_memory *memory = &(nds32->memory);
580
581 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
582 (target->state != TARGET_HALTED)) {
583 LOG_WARNING("target was not halted");
584 return ERROR_TARGET_NOT_HALTED;
585 }
586
587 uint32_t physical_address;
588 /* BUG: If access range crosses multiple pages, the translation will not correct
589 * for second page or so. */
590
591 /* When DEX is set to one, hardware will enforce the following behavior without
592 * modifying the corresponding control bits in PSW.
593 *
594 * Disable all interrupts
595 * Become superuser mode
596 * Turn off IT/DT
597 * Use MMU_CFG.DE as the data access endian
598 * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
599 * Disable audio special features
600 * Disable inline function call
601 *
602 * Because hardware will turn off IT/DT by default, it MUST translate virtual address
603 * to physical address.
604 */
605 if (ERROR_OK == target->type->virt2phys(target, address, &physical_address))
606 address = physical_address;
607 else
608 return ERROR_FAIL;
609
610 struct aice_port_s *aice = target_to_aice(target);
611 /* give arbitrary initial value to avoid warning messages */
612 enum nds_memory_access origin_access_channel = NDS_MEMORY_ACC_CPU;
613 int result;
614
615 if (nds32->hit_syscall) {
616 /* Use bus mode to access memory during virtual hosting */
617 origin_access_channel = memory->access_channel;
618 memory->access_channel = NDS_MEMORY_ACC_BUS;
619 aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
620 }
621
622 result = nds32_read_memory(target, address, size, count, buffer);
623
624 if (nds32->hit_syscall) {
625 /* Restore access_channel after virtual hosting */
626 memory->access_channel = origin_access_channel;
627 aice_memory_access(aice, origin_access_channel);
628 }
629
630 return result;
631 }
632
633 int nds32_v3_write_memory(struct target *target, uint32_t address,
634 uint32_t size, uint32_t count, const uint8_t *buffer)
635 {
636 struct nds32 *nds32 = target_to_nds32(target);
637 struct nds32_memory *memory = &(nds32->memory);
638
639 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
640 (target->state != TARGET_HALTED)) {
641 LOG_WARNING("target was not halted");
642 return ERROR_TARGET_NOT_HALTED;
643 }
644
645 uint32_t physical_address;
646 /* BUG: If access range crosses multiple pages, the translation will not correct
647 * for second page or so. */
648
649 /* When DEX is set to one, hardware will enforce the following behavior without
650 * modifying the corresponding control bits in PSW.
651 *
652 * Disable all interrupts
653 * Become superuser mode
654 * Turn off IT/DT
655 * Use MMU_CFG.DE as the data access endian
656 * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
657 * Disable audio special features
658 * Disable inline function call
659 *
660 * Because hardware will turn off IT/DT by default, it MUST translate virtual address
661 * to physical address.
662 */
663 if (ERROR_OK == target->type->virt2phys(target, address, &physical_address))
664 address = physical_address;
665 else
666 return ERROR_FAIL;
667
668 return nds32_write_memory(target, address, size, count, buffer);
669 }
670
671 int nds32_v3_init_target(struct command_context *cmd_ctx,
672 struct target *target)
673 {
674 /* Initialize anything we can set up without talking to the target */
675 struct nds32 *nds32 = target_to_nds32(target);
676
677 nds32_init(nds32);
678
679 target->fileio_info = malloc(sizeof(struct gdb_fileio_info));
680 target->fileio_info->identifier = NULL;
681
682 return ERROR_OK;
683 }

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)