nds32: refine nds32_v2 implement
[openocd.git] / src / target / nds32_v2.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 <helper/time_support.h>
26 #include <helper/binarybuffer.h>
27 #include "breakpoints.h"
28 #include "nds32_insn.h"
29 #include "nds32_reg.h"
30 #include "nds32_edm.h"
31 #include "nds32_cmd.h"
32 #include "nds32_v2.h"
33 #include "nds32_aice.h"
34 #include "target_type.h"
35
36 static int nds32_v2_register_mapping(struct nds32 *nds32, int reg_no)
37 {
38 uint32_t max_level = nds32->max_interrupt_level;
39 uint32_t cur_level = nds32->current_interrupt_level;
40
41 if ((1 <= cur_level) && (cur_level < max_level)) {
42 if (IR0 == reg_no) {
43 LOG_DEBUG("Map PSW to IPSW");
44 return IR1;
45 } else if (PC == reg_no) {
46 LOG_DEBUG("Map PC to IPC");
47 return IR9;
48 }
49 } else if ((2 <= cur_level) && (cur_level < max_level)) {
50 if (R26 == reg_no) {
51 LOG_DEBUG("Mapping P0 to P_P0");
52 return IR12;
53 } else if (R27 == reg_no) {
54 LOG_DEBUG("Mapping P1 to P_P1");
55 return IR13;
56 } else if (IR1 == reg_no) {
57 LOG_DEBUG("Mapping IPSW to P_IPSW");
58 return IR2;
59 } else if (IR4 == reg_no) {
60 LOG_DEBUG("Mapping EVA to P_EVA");
61 return IR5;
62 } else if (IR6 == reg_no) {
63 LOG_DEBUG("Mapping ITYPE to P_ITYPE");
64 return IR7;
65 } else if (IR9 == reg_no) {
66 LOG_DEBUG("Mapping IPC to P_IPC");
67 return IR10;
68 }
69 } else if (cur_level == max_level) {
70 if (PC == reg_no) {
71 LOG_DEBUG("Mapping PC to O_IPC");
72 return IR11;
73 }
74 }
75
76 return reg_no;
77 }
78
79 static int nds32_v2_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
80 {
81 uint32_t val_itype;
82 struct aice_port_s *aice = target_to_aice(nds32->target);
83
84 aice_read_register(aice, IR6, &val_itype);
85
86 *reason = val_itype & 0x0F;
87
88 return ERROR_OK;
89 }
90
91 static int nds32_v2_activate_hardware_breakpoint(struct target *target)
92 {
93 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
94 struct aice_port_s *aice = target_to_aice(target);
95 struct breakpoint *bp;
96 int32_t hbr_index = 0;
97
98 for (bp = target->breakpoints; bp; bp = bp->next) {
99 if (bp->type == BKPT_SOFT) {
100 /* already set at nds32_v2_add_breakpoint() */
101 continue;
102 } else if (bp->type == BKPT_HARD) {
103 /* set address */
104 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address);
105 /* set mask */
106 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0);
107 /* set value */
108 aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0);
109
110 if (nds32_v2->nds32.memory.address_translation)
111 /* enable breakpoint (virtual address) */
112 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2);
113 else
114 /* enable breakpoint (physical address) */
115 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA);
116
117 LOG_DEBUG("Add hardware BP %d at %08" PRIx32, hbr_index,
118 bp->address);
119
120 hbr_index++;
121 } else {
122 return ERROR_FAIL;
123 }
124 }
125
126 return ERROR_OK;
127 }
128
129 static int nds32_v2_deactivate_hardware_breakpoint(struct target *target)
130 {
131 struct aice_port_s *aice = target_to_aice(target);
132 struct breakpoint *bp;
133 int32_t hbr_index = 0;
134
135 for (bp = target->breakpoints; bp; bp = bp->next) {
136 if (bp->type == BKPT_SOFT)
137 continue;
138 else if (bp->type == BKPT_HARD)
139 /* disable breakpoint */
140 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0);
141 else
142 return ERROR_FAIL;
143
144 LOG_DEBUG("Remove hardware BP %d at %08" PRIx32, hbr_index,
145 bp->address);
146
147 hbr_index++;
148 }
149
150 return ERROR_OK;
151 }
152
153 static int nds32_v2_activate_hardware_watchpoint(struct target *target)
154 {
155 struct aice_port_s *aice = target_to_aice(target);
156 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
157 struct watchpoint *wp;
158 int32_t wp_num = nds32_v2->next_hbr_index;
159 uint32_t wp_config = 0;
160
161 for (wp = target->watchpoints; wp; wp = wp->next) {
162
163 wp_num--;
164 wp->mask = wp->length - 1;
165 if ((wp->address % wp->length) != 0)
166 wp->mask = (wp->mask << 1) + 1;
167
168 if (wp->rw == WPT_READ)
169 wp_config = 0x3;
170 else if (wp->rw == WPT_WRITE)
171 wp_config = 0x5;
172 else if (wp->rw == WPT_ACCESS)
173 wp_config = 0x7;
174
175 /* set/unset physical address bit of BPCn according to PSW.DT */
176 if (nds32_v2->nds32.memory.address_translation == false)
177 wp_config |= 0x8;
178
179 /* set address */
180 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
181 wp->address - (wp->address % wp->length));
182 /* set mask */
183 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
184 /* enable watchpoint */
185 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
186 /* set value */
187 aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0);
188
189 LOG_DEBUG("Add hardware wathcpoint %d at %08" PRIx32 " mask %08" PRIx32, wp_num,
190 wp->address, wp->mask);
191
192 }
193
194 return ERROR_OK;
195 }
196
197 static int nds32_v2_deactivate_hardware_watchpoint(struct target *target)
198 {
199 struct aice_port_s *aice = target_to_aice(target);
200 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
201 int32_t wp_num = nds32_v2->next_hbr_index;
202 struct watchpoint *wp;
203
204 for (wp = target->watchpoints; wp; wp = wp->next) {
205 wp_num--;
206 /* disable watchpoint */
207 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
208
209 LOG_DEBUG("Remove hardware wathcpoint %d at %08" PRIx32 " mask %08" PRIx32,
210 wp_num, wp->address, wp->mask);
211 }
212
213 return ERROR_OK;
214 }
215
216 static int nds32_v2_check_interrupt_stack(struct nds32_v2_common *nds32_v2)
217 {
218 struct nds32 *nds32 = &(nds32_v2->nds32);
219 struct aice_port_s *aice = target_to_aice(nds32->target);
220 uint32_t val_ir0;
221 uint32_t val_ir1;
222 uint32_t val_ir2;
223 uint32_t modified_psw;
224
225 /* Save interrupt level */
226 aice_read_register(aice, IR0, &val_ir0); /* get $IR0 directly */
227
228 /* backup $IR0 */
229 nds32_v2->backup_ir0 = val_ir0;
230
231 nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
232
233 if (nds32_reach_max_interrupt_level(nds32)) {
234 LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %d. -->",
235 nds32->current_interrupt_level);
236
237 /* decrease interrupt level */
238 modified_psw = val_ir0 - 0x2;
239
240 /* disable GIE, IT, DT, HSS */
241 modified_psw &= (~0x8C1);
242
243 aice_write_register(aice, IR0, modified_psw);
244
245 return ERROR_OK;
246 }
247
248 /* There is a case that single step also trigger another interrupt,
249 then HSS bit in psw(ir0) will push to ipsw(ir1).
250 Then hit debug interrupt HSS bit in ipsw(ir1) will push to (p_ipsw)ir2
251 Therefore, HSS bit in p_ipsw(ir2) also need clear.
252
253 Only update $ir2 as current interrupt level is 2, because $ir2 will be random
254 value if the target never reaches interrupt level 2. */
255 if ((nds32->max_interrupt_level == 3) && (nds32->current_interrupt_level == 2)) {
256 aice_read_register(aice, IR2, &val_ir2); /* get $IR2 directly */
257 val_ir2 &= ~(0x01 << 11);
258 aice_write_register(aice, IR2, val_ir2);
259 }
260
261 /* get origianl DT bit and set to current state let debugger has same memory view
262 PSW.IT MUST be turned off. Otherwise, DIM could not operate normally. */
263 aice_read_register(aice, IR1, &val_ir1);
264 modified_psw = val_ir0 | (val_ir1 & 0x80);
265 aice_write_register(aice, IR0, modified_psw);
266
267 return ERROR_OK;
268 }
269
270 static int nds32_v2_restore_interrupt_stack(struct nds32_v2_common *nds32_v2)
271 {
272 struct nds32 *nds32 = &(nds32_v2->nds32);
273 struct aice_port_s *aice = target_to_aice(nds32->target);
274
275 /* restore origin $IR0 */
276 aice_write_register(aice, IR0, nds32_v2->backup_ir0);
277
278 return ERROR_OK;
279 }
280
281 /**
282 * Save processor state. This is called after a HALT instruction
283 * succeeds, and on other occasions the processor enters debug mode
284 * (breakpoint, watchpoint, etc).
285 */
286 static int nds32_v2_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
287 {
288 LOG_DEBUG("nds32_v2_debug_entry");
289
290 jtag_poll_set_enabled(false);
291
292 if (nds32->virtual_hosting)
293 LOG_WARNING("<-- TARGET WARNING! Virtual hosting is not supported "
294 "under V1/V2 architecture. -->");
295
296 enum target_state backup_state = nds32->target->state;
297 nds32->target->state = TARGET_HALTED;
298
299 if (nds32->init_arch_info_after_halted == false) {
300 /* init architecture info according to config registers */
301 CHECK_RETVAL(nds32_config(nds32));
302
303 nds32->init_arch_info_after_halted = true;
304 }
305
306 /* REVISIT entire cache should already be invalid !!! */
307 register_cache_invalidate(nds32->core_cache);
308
309 /* deactivate all hardware breakpoints */
310 CHECK_RETVAL(nds32_v2_deactivate_hardware_breakpoint(nds32->target));
311
312 if (enable_watchpoint)
313 CHECK_RETVAL(nds32_v2_deactivate_hardware_watchpoint(nds32->target));
314
315 if (ERROR_OK != nds32_examine_debug_reason(nds32)) {
316 nds32->target->state = backup_state;
317
318 /* re-activate all hardware breakpoints & watchpoints */
319 CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
320
321 if (enable_watchpoint) {
322 /* activate all watchpoints */
323 CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
324 }
325
326 return ERROR_FAIL;
327 }
328
329 /* check interrupt level before .full_context(), because
330 * get_mapped_reg() in nds32_full_context() needs current_interrupt_level
331 * information */
332 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
333 nds32_v2_check_interrupt_stack(nds32_v2);
334
335 /* Save registers. */
336 nds32_full_context(nds32);
337
338 return ERROR_OK;
339 }
340
341 /* target request support */
342 static int nds32_v2_target_request_data(struct target *target,
343 uint32_t size, uint8_t *buffer)
344 {
345 /* AndesCore could use DTR register to communicate with OpenOCD
346 * to output messages
347 * Target data will be put in buffer
348 * The format of DTR is as follow
349 * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
350 * target_req_cmd has three possible values:
351 * TARGET_REQ_TRACEMSG
352 * TARGET_REQ_DEBUGMSG
353 * TARGET_REQ_DEBUGCHAR
354 * if size == 0, target will call target_asciimsg(),
355 * else call target_hexmsg()
356 */
357 LOG_WARNING("Not implemented: %s", __func__);
358
359 return ERROR_OK;
360 }
361
362 /**
363 * Restore processor state.
364 */
365 static int nds32_v2_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
366 {
367 LOG_DEBUG("nds32_v2_leave_debug_state");
368
369 struct target *target = nds32->target;
370
371 /* activate all hardware breakpoints */
372 CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
373
374 if (enable_watchpoint) {
375 /* activate all watchpoints */
376 CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
377 }
378
379 /* restore interrupt stack */
380 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
381 nds32_v2_restore_interrupt_stack(nds32_v2);
382
383 /* restore PSW, PC, and R0 ... after flushing any modified
384 * registers.
385 */
386 CHECK_RETVAL(nds32_restore_context(target));
387
388 register_cache_invalidate(nds32->core_cache);
389
390 jtag_poll_set_enabled(true);
391
392 return ERROR_OK;
393 }
394
395 static int nds32_v2_soft_reset_halt(struct target *target)
396 {
397 /* TODO: test it */
398 struct nds32 *nds32 = target_to_nds32(target);
399 struct aice_port_s *aice = target_to_aice(target);
400
401 aice_assert_srst(aice, AICE_SRST);
402
403 /* halt core and set pc to 0x0 */
404 int retval = target_halt(target);
405 if (retval != ERROR_OK)
406 return retval;
407
408 /* start fetching from IVB */
409 uint32_t value_ir3;
410 nds32_get_mapped_reg(nds32, IR3, &value_ir3);
411 nds32_set_mapped_reg(nds32, PC, value_ir3 & 0xFFFF0000);
412
413 return ERROR_OK;
414 }
415
416 static int nds32_v2_deassert_reset(struct target *target)
417 {
418 int retval;
419
420 CHECK_RETVAL(nds32_poll(target));
421
422 if (target->state != TARGET_HALTED) {
423 /* reset only */
424 LOG_WARNING("%s: ran after reset and before halt ...",
425 target_name(target));
426 retval = target_halt(target);
427 if (retval != ERROR_OK)
428 return retval;
429 /* call target_poll() to avoid "Halt timed out" */
430 CHECK_RETVAL(target_poll(target));
431 } else {
432 jtag_poll_set_enabled(false);
433 }
434
435 return ERROR_OK;
436 }
437
438 static int nds32_v2_checksum_memory(struct target *target,
439 uint32_t address, uint32_t count, uint32_t *checksum)
440 {
441 LOG_WARNING("Not implemented: %s", __func__);
442
443 return ERROR_FAIL;
444 }
445
446 static int nds32_v2_add_breakpoint(struct target *target,
447 struct breakpoint *breakpoint)
448 {
449 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
450 struct nds32 *nds32 = &(nds32_v2->nds32);
451 int result;
452
453 if (breakpoint->type == BKPT_HARD) {
454 /* check hardware resource */
455 if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
456 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
457 "breakpoints/watchpoints! The limit of "
458 "combined hardware breakpoints/watchpoints "
459 "is %d. -->", nds32_v2->n_hbr);
460 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
461 }
462
463 /* update next place to put hardware breakpoint */
464 nds32_v2->next_hbr_index++;
465
466 /* hardware breakpoint insertion occurs before 'continue' actually */
467 return ERROR_OK;
468 } else if (breakpoint->type == BKPT_SOFT) {
469 result = nds32_add_software_breakpoint(target, breakpoint);
470 if (ERROR_OK != result) {
471 /* auto convert to hardware breakpoint if failed */
472 if (nds32->auto_convert_hw_bp) {
473 /* convert to hardware breakpoint */
474 breakpoint->type = BKPT_HARD;
475
476 return nds32_v2_add_breakpoint(target, breakpoint);
477 }
478 }
479
480 return result;
481 } else /* unrecognized breakpoint type */
482 return ERROR_FAIL;
483
484 return ERROR_OK;
485 }
486
487 static int nds32_v2_remove_breakpoint(struct target *target,
488 struct breakpoint *breakpoint)
489 {
490 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
491
492 if (breakpoint->type == BKPT_HARD) {
493 if (nds32_v2->next_hbr_index <= 0)
494 return ERROR_FAIL;
495
496 /* update next place to put hardware breakpoint */
497 nds32_v2->next_hbr_index--;
498
499 /* hardware breakpoint removal occurs after 'halted' actually */
500 return ERROR_OK;
501 } else if (breakpoint->type == BKPT_SOFT) {
502 return nds32_remove_software_breakpoint(target, breakpoint);
503 } else /* unrecognized breakpoint type */
504 return ERROR_FAIL;
505
506 return ERROR_OK;
507 }
508
509 static int nds32_v2_add_watchpoint(struct target *target,
510 struct watchpoint *watchpoint)
511 {
512 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
513
514 /* check hardware resource */
515 if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
516 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
517 "breakpoints/watchpoints! The limit of "
518 "combined hardware breakpoints/watchpoints is %d. -->", nds32_v2->n_hbr);
519 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
520 }
521
522 /* update next place to put hardware watchpoint */
523 nds32_v2->next_hbr_index++;
524
525 return ERROR_OK;
526 }
527
528 static int nds32_v2_remove_watchpoint(struct target *target,
529 struct watchpoint *watchpoint)
530 {
531 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
532
533 if (nds32_v2->next_hbr_index <= 0)
534 return ERROR_FAIL;
535
536 /* update next place to put hardware breakpoint */
537 nds32_v2->next_hbr_index--;
538
539 return ERROR_OK;
540 }
541
542 static int nds32_v2_get_exception_address(struct nds32 *nds32,
543 uint32_t *address, uint32_t reason)
544 {
545 struct aice_port_s *aice = target_to_aice(nds32->target);
546
547 aice_read_register(aice, IR4, address); /* read $EVA directly */
548
549 /* TODO: hit multiple watchpoints */
550
551 return ERROR_OK;
552 }
553
554 /**
555 * find out which watchpoint hits
556 * get exception address and compare the address to watchpoints
557 */
558 static int nds32_v2_hit_watchpoint(struct target *target,
559 struct watchpoint **hit_watchpoint)
560 {
561 uint32_t exception_address;
562 struct watchpoint *wp;
563 static struct watchpoint scan_all_watchpoint;
564 struct nds32 *nds32 = target_to_nds32(target);
565
566 scan_all_watchpoint.address = 0;
567 scan_all_watchpoint.rw = WPT_WRITE;
568 scan_all_watchpoint.next = 0;
569 scan_all_watchpoint.unique_id = 0x5CA8;
570
571 exception_address = nds32->watched_address;
572
573 if (exception_address == 0) {
574 /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */
575 *hit_watchpoint = &scan_all_watchpoint;
576 return ERROR_OK;
577 }
578
579 for (wp = target->watchpoints; wp; wp = wp->next) {
580 if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
581 /* TODO: dispel false match */
582 *hit_watchpoint = wp;
583 return ERROR_OK;
584 }
585 }
586
587 return ERROR_FAIL;
588 }
589
590 static int nds32_v2_run_algorithm(struct target *target,
591 int num_mem_params,
592 struct mem_param *mem_params,
593 int num_reg_params,
594 struct reg_param *reg_params,
595 uint32_t entry_point,
596 uint32_t exit_point,
597 int timeout_ms,
598 void *arch_info)
599 {
600 LOG_WARNING("Not implemented: %s", __func__);
601
602 return ERROR_FAIL;
603 }
604
605 static int nds32_v2_target_create(struct target *target, Jim_Interp *interp)
606 {
607 struct nds32_v2_common *nds32_v2;
608
609 nds32_v2 = calloc(1, sizeof(*nds32_v2));
610 if (!nds32_v2)
611 return ERROR_FAIL;
612
613 nds32_v2->nds32.register_map = nds32_v2_register_mapping;
614 nds32_v2->nds32.get_debug_reason = nds32_v2_get_debug_reason;
615 nds32_v2->nds32.enter_debug_state = nds32_v2_debug_entry;
616 nds32_v2->nds32.leave_debug_state = nds32_v2_leave_debug_state;
617 nds32_v2->nds32.get_watched_address = nds32_v2_get_exception_address;
618
619 nds32_init_arch_info(target, &(nds32_v2->nds32));
620
621 return ERROR_OK;
622 }
623
624 static int nds32_v2_init_target(struct command_context *cmd_ctx,
625 struct target *target)
626 {
627 /* Initialize anything we can set up without talking to the target */
628
629 struct nds32 *nds32 = target_to_nds32(target);
630
631 nds32_init(nds32);
632
633 return ERROR_OK;
634 }
635
636 /* talk to the target and set things up */
637 static int nds32_v2_examine(struct target *target)
638 {
639 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
640 struct nds32 *nds32 = &(nds32_v2->nds32);
641 struct aice_port_s *aice = target_to_aice(target);
642
643 if (!target_was_examined(target)) {
644 CHECK_RETVAL(nds32_edm_config(nds32));
645
646 if (nds32->reset_halt_as_examine)
647 CHECK_RETVAL(nds32_reset_halt(nds32));
648 }
649
650 uint32_t edm_cfg;
651 aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
652
653 /* get the number of hardware breakpoints */
654 nds32_v2->n_hbr = (edm_cfg & 0x7) + 1;
655
656 nds32_v2->next_hbr_index = 0;
657
658 LOG_INFO("%s: total hardware breakpoint %d", target_name(target),
659 nds32_v2->n_hbr);
660
661 nds32->target->state = TARGET_RUNNING;
662 nds32->target->debug_reason = DBG_REASON_NOTHALTED;
663
664 target_set_examined(target);
665
666 return ERROR_OK;
667 }
668
669 static int nds32_v2_translate_address(struct target *target, uint32_t *address)
670 {
671 struct nds32 *nds32 = target_to_nds32(target);
672 struct nds32_memory *memory = &(nds32->memory);
673 uint32_t physical_address;
674
675 /* Following conditions need to do address translation
676 * 1. BUS mode
677 * 2. CPU mode under maximum interrupt level */
678 if ((NDS_MEMORY_ACC_BUS == memory->access_channel) ||
679 ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
680 nds32_reach_max_interrupt_level(nds32))) {
681 if (ERROR_OK == target->type->virt2phys(target, *address, &physical_address))
682 *address = physical_address;
683 else
684 return ERROR_FAIL;
685 }
686
687 return ERROR_OK;
688 }
689
690 static int nds32_v2_read_buffer(struct target *target, uint32_t address,
691 uint32_t size, uint8_t *buffer)
692 {
693 struct nds32 *nds32 = target_to_nds32(target);
694 struct nds32_memory *memory = &(nds32->memory);
695
696 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
697 (target->state != TARGET_HALTED)) {
698 LOG_WARNING("target was not halted");
699 return ERROR_TARGET_NOT_HALTED;
700 }
701
702 /* BUG: If access range crosses multiple pages, the translation will not correct
703 * for second page or so. */
704
705 nds32_v2_translate_address(target, &address);
706
707 return nds32_read_buffer(target, address, size, buffer);
708 }
709
710 static int nds32_v2_write_buffer(struct target *target, uint32_t address,
711 uint32_t size, const uint8_t *buffer)
712 {
713 struct nds32 *nds32 = target_to_nds32(target);
714 struct nds32_memory *memory = &(nds32->memory);
715
716 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
717 (target->state != TARGET_HALTED)) {
718 LOG_WARNING("target was not halted");
719 return ERROR_TARGET_NOT_HALTED;
720 }
721
722 /* BUG: If access range crosses multiple pages, the translation will not correct
723 * for second page or so. */
724
725 nds32_v2_translate_address(target, &address);
726
727 return nds32_write_buffer(target, address, size, buffer);
728 }
729
730 static int nds32_v2_read_memory(struct target *target, uint32_t address,
731 uint32_t size, uint32_t count, uint8_t *buffer)
732 {
733 struct nds32 *nds32 = target_to_nds32(target);
734 struct nds32_memory *memory = &(nds32->memory);
735
736 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
737 (target->state != TARGET_HALTED)) {
738 LOG_WARNING("target was not halted");
739 return ERROR_TARGET_NOT_HALTED;
740 }
741
742 /* BUG: If access range crosses multiple pages, the translation will not correct
743 * for second page or so. */
744
745 nds32_v2_translate_address(target, &address);
746
747 return nds32_read_memory(target, address, size, count, buffer);
748 }
749
750 static int nds32_v2_write_memory(struct target *target, uint32_t address,
751 uint32_t size, uint32_t count, const uint8_t *buffer)
752 {
753 struct nds32 *nds32 = target_to_nds32(target);
754 struct nds32_memory *memory = &(nds32->memory);
755
756 if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
757 (target->state != TARGET_HALTED)) {
758 LOG_WARNING("target was not halted");
759 return ERROR_TARGET_NOT_HALTED;
760 }
761
762 /* BUG: If access range crosses multiple pages, the translation will not correct
763 * for second page or so. */
764
765 nds32_v2_translate_address(target, &address);
766
767 return nds32_write_memory(target, address, size, count, buffer);
768 }
769
770 /** Holds methods for V2 targets. */
771 struct target_type nds32_v2_target = {
772 .name = "nds32_v2",
773
774 .poll = nds32_poll,
775 .arch_state = nds32_arch_state,
776
777 .target_request_data = nds32_v2_target_request_data,
778
779 .halt = nds32_halt,
780 .resume = nds32_resume,
781 .step = nds32_step,
782
783 .assert_reset = nds32_assert_reset,
784 .deassert_reset = nds32_v2_deassert_reset,
785 .soft_reset_halt = nds32_v2_soft_reset_halt,
786
787 /* register access */
788 .get_gdb_reg_list = nds32_get_gdb_reg_list,
789
790 /* memory access */
791 .read_buffer = nds32_v2_read_buffer,
792 .write_buffer = nds32_v2_write_buffer,
793 .read_memory = nds32_v2_read_memory,
794 .write_memory = nds32_v2_write_memory,
795
796 .checksum_memory = nds32_v2_checksum_memory,
797
798 /* breakpoint/watchpoint */
799 .add_breakpoint = nds32_v2_add_breakpoint,
800 .remove_breakpoint = nds32_v2_remove_breakpoint,
801 .add_watchpoint = nds32_v2_add_watchpoint,
802 .remove_watchpoint = nds32_v2_remove_watchpoint,
803 .hit_watchpoint = nds32_v2_hit_watchpoint,
804
805 /* MMU */
806 .mmu = nds32_mmu,
807 .virt2phys = nds32_virtual_to_physical,
808 .read_phys_memory = nds32_read_phys_memory,
809 .write_phys_memory = nds32_write_phys_memory,
810
811 .run_algorithm = nds32_v2_run_algorithm,
812
813 .commands = nds32_command_handlers,
814 .target_create = nds32_v2_target_create,
815 .init_target = nds32_v2_init_target,
816 .examine = nds32_v2_examine,
817 };

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)