flash/nor/rp2040: check target halted before flash operation
[openocd.git] / src / target / nds32_v2.c
blob2149291179de1ee500937ca36bd0d03e91ab77af
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2013 Andes Technology *
5 * Hsiangkai Wang <hkwang@andestech.com> *
6 ***************************************************************************/
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
12 #include <helper/time_support.h>
13 #include <helper/binarybuffer.h>
14 #include "breakpoints.h"
15 #include "nds32_insn.h"
16 #include "nds32_reg.h"
17 #include "nds32_edm.h"
18 #include "nds32_cmd.h"
19 #include "nds32_v2.h"
20 #include "nds32_aice.h"
21 #include "target_type.h"
23 static int nds32_v2_register_mapping(struct nds32 *nds32, int reg_no)
25 uint32_t max_level = nds32->max_interrupt_level;
26 uint32_t cur_level = nds32->current_interrupt_level;
28 if ((cur_level >= 1) && (cur_level < max_level)) {
29 if (reg_no == IR0) {
30 LOG_DEBUG("Map PSW to IPSW");
31 return IR1;
32 } else if (reg_no == PC) {
33 LOG_DEBUG("Map PC to IPC");
34 return IR9;
36 } else if ((cur_level >= 2) && (cur_level < max_level)) {
37 if (reg_no == R26) {
38 LOG_DEBUG("Mapping P0 to P_P0");
39 return IR12;
40 } else if (reg_no == R27) {
41 LOG_DEBUG("Mapping P1 to P_P1");
42 return IR13;
43 } else if (reg_no == IR1) {
44 LOG_DEBUG("Mapping IPSW to P_IPSW");
45 return IR2;
46 } else if (reg_no == IR4) {
47 LOG_DEBUG("Mapping EVA to P_EVA");
48 return IR5;
49 } else if (reg_no == IR6) {
50 LOG_DEBUG("Mapping ITYPE to P_ITYPE");
51 return IR7;
52 } else if (reg_no == IR9) {
53 LOG_DEBUG("Mapping IPC to P_IPC");
54 return IR10;
56 } else if (cur_level == max_level) {
57 if (reg_no == PC) {
58 LOG_DEBUG("Mapping PC to O_IPC");
59 return IR11;
63 return reg_no;
66 static int nds32_v2_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
68 uint32_t val_itype;
69 struct aice_port_s *aice = target_to_aice(nds32->target);
71 aice_read_register(aice, IR6, &val_itype);
73 *reason = val_itype & 0x0F;
75 return ERROR_OK;
78 static int nds32_v2_activate_hardware_breakpoint(struct target *target)
80 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
81 struct aice_port_s *aice = target_to_aice(target);
82 struct breakpoint *bp;
83 int32_t hbr_index = 0;
85 for (bp = target->breakpoints; bp; bp = bp->next) {
86 if (bp->type == BKPT_SOFT) {
87 /* already set at nds32_v2_add_breakpoint() */
88 continue;
89 } else if (bp->type == BKPT_HARD) {
90 /* set address */
91 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address);
92 /* set mask */
93 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0);
94 /* set value */
95 aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0);
97 if (nds32_v2->nds32.memory.address_translation)
98 /* enable breakpoint (virtual address) */
99 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2);
100 else
101 /* enable breakpoint (physical address) */
102 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA);
104 LOG_DEBUG("Add hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index,
105 bp->address);
107 hbr_index++;
108 } else {
109 return ERROR_FAIL;
113 return ERROR_OK;
116 static int nds32_v2_deactivate_hardware_breakpoint(struct target *target)
118 struct aice_port_s *aice = target_to_aice(target);
119 struct breakpoint *bp;
120 int32_t hbr_index = 0;
122 for (bp = target->breakpoints; bp; bp = bp->next) {
123 if (bp->type == BKPT_SOFT)
124 continue;
125 else if (bp->type == BKPT_HARD)
126 /* disable breakpoint */
127 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0);
128 else
129 return ERROR_FAIL;
131 LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index,
132 bp->address);
134 hbr_index++;
137 return ERROR_OK;
140 static int nds32_v2_activate_hardware_watchpoint(struct target *target)
142 struct aice_port_s *aice = target_to_aice(target);
143 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
144 struct watchpoint *wp;
145 int32_t wp_num = nds32_v2->next_hbr_index;
146 uint32_t wp_config = 0;
148 for (wp = target->watchpoints; wp; wp = wp->next) {
150 wp_num--;
151 wp->mask = wp->length - 1;
152 if ((wp->address % wp->length) != 0)
153 wp->mask = (wp->mask << 1) + 1;
155 if (wp->rw == WPT_READ)
156 wp_config = 0x3;
157 else if (wp->rw == WPT_WRITE)
158 wp_config = 0x5;
159 else if (wp->rw == WPT_ACCESS)
160 wp_config = 0x7;
162 /* set/unset physical address bit of BPCn according to PSW.DT */
163 if (nds32_v2->nds32.memory.address_translation == false)
164 wp_config |= 0x8;
166 /* set address */
167 aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
168 wp->address - (wp->address % wp->length));
169 /* set mask */
170 aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
171 /* enable watchpoint */
172 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
173 /* set value */
174 aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0);
176 LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num,
177 wp->address, wp->mask);
181 return ERROR_OK;
184 static int nds32_v2_deactivate_hardware_watchpoint(struct target *target)
186 struct aice_port_s *aice = target_to_aice(target);
187 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
188 int32_t wp_num = nds32_v2->next_hbr_index;
189 struct watchpoint *wp;
191 for (wp = target->watchpoints; wp; wp = wp->next) {
192 wp_num--;
193 /* disable watchpoint */
194 aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
196 LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32,
197 wp_num, wp->address, wp->mask);
200 return ERROR_OK;
203 static int nds32_v2_check_interrupt_stack(struct nds32_v2_common *nds32_v2)
205 struct nds32 *nds32 = &(nds32_v2->nds32);
206 struct aice_port_s *aice = target_to_aice(nds32->target);
207 uint32_t val_ir0;
208 uint32_t val_ir1;
209 uint32_t val_ir2;
210 uint32_t modified_psw;
212 /* Save interrupt level */
213 aice_read_register(aice, IR0, &val_ir0); /* get $IR0 directly */
215 /* backup $IR0 */
216 nds32_v2->backup_ir0 = val_ir0;
218 nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
220 if (nds32_reach_max_interrupt_level(nds32)) {
221 LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
222 nds32->current_interrupt_level);
224 /* decrease interrupt level */
225 modified_psw = val_ir0 - 0x2;
227 /* disable GIE, IT, DT, HSS */
228 modified_psw &= (~0x8C1);
230 aice_write_register(aice, IR0, modified_psw);
232 return ERROR_OK;
235 /* There is a case that single step also trigger another interrupt,
236 then HSS bit in psw(ir0) will push to ipsw(ir1).
237 Then hit debug interrupt HSS bit in ipsw(ir1) will push to (p_ipsw)ir2
238 Therefore, HSS bit in p_ipsw(ir2) also need clear.
240 Only update $ir2 as current interrupt level is 2, because $ir2 will be random
241 value if the target never reaches interrupt level 2. */
242 if ((nds32->max_interrupt_level == 3) && (nds32->current_interrupt_level == 2)) {
243 aice_read_register(aice, IR2, &val_ir2); /* get $IR2 directly */
244 val_ir2 &= ~(0x01 << 11);
245 aice_write_register(aice, IR2, val_ir2);
248 /* get original DT bit and set to current state let debugger has same memory view
249 PSW.IT MUST be turned off. Otherwise, DIM could not operate normally. */
250 aice_read_register(aice, IR1, &val_ir1);
251 modified_psw = val_ir0 | (val_ir1 & 0x80);
252 aice_write_register(aice, IR0, modified_psw);
254 return ERROR_OK;
257 static int nds32_v2_restore_interrupt_stack(struct nds32_v2_common *nds32_v2)
259 struct nds32 *nds32 = &(nds32_v2->nds32);
260 struct aice_port_s *aice = target_to_aice(nds32->target);
262 /* restore origin $IR0 */
263 aice_write_register(aice, IR0, nds32_v2->backup_ir0);
265 return ERROR_OK;
269 * Save processor state. This is called after a HALT instruction
270 * succeeds, and on other occasions the processor enters debug mode
271 * (breakpoint, watchpoint, etc).
273 static int nds32_v2_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
275 LOG_DEBUG("nds32_v2_debug_entry");
277 if (nds32->virtual_hosting)
278 LOG_WARNING("<-- TARGET WARNING! Virtual hosting is not supported "
279 "under V1/V2 architecture. -->");
281 enum target_state backup_state = nds32->target->state;
282 nds32->target->state = TARGET_HALTED;
284 if (nds32->init_arch_info_after_halted == false) {
285 /* init architecture info according to config registers */
286 CHECK_RETVAL(nds32_config(nds32));
288 nds32->init_arch_info_after_halted = true;
291 /* REVISIT entire cache should already be invalid !!! */
292 register_cache_invalidate(nds32->core_cache);
294 /* deactivate all hardware breakpoints */
295 CHECK_RETVAL(nds32_v2_deactivate_hardware_breakpoint(nds32->target));
297 if (enable_watchpoint)
298 CHECK_RETVAL(nds32_v2_deactivate_hardware_watchpoint(nds32->target));
300 if (nds32_examine_debug_reason(nds32) != ERROR_OK) {
301 nds32->target->state = backup_state;
303 /* re-activate all hardware breakpoints & watchpoints */
304 CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
306 if (enable_watchpoint) {
307 /* activate all watchpoints */
308 CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
311 return ERROR_FAIL;
314 /* check interrupt level before .full_context(), because
315 * get_mapped_reg() in nds32_full_context() needs current_interrupt_level
316 * information */
317 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
318 nds32_v2_check_interrupt_stack(nds32_v2);
320 /* Save registers. */
321 nds32_full_context(nds32);
323 return ERROR_OK;
326 /* target request support */
327 static int nds32_v2_target_request_data(struct target *target,
328 uint32_t size, uint8_t *buffer)
330 /* AndesCore could use DTR register to communicate with OpenOCD
331 * to output messages
332 * Target data will be put in buffer
333 * The format of DTR is as follow
334 * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
335 * target_req_cmd has three possible values:
336 * TARGET_REQ_TRACEMSG
337 * TARGET_REQ_DEBUGMSG
338 * TARGET_REQ_DEBUGCHAR
339 * if size == 0, target will call target_asciimsg(),
340 * else call target_hexmsg()
342 LOG_WARNING("Not implemented: %s", __func__);
344 return ERROR_OK;
348 * Restore processor state.
350 static int nds32_v2_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
352 LOG_DEBUG("nds32_v2_leave_debug_state");
354 struct target *target = nds32->target;
356 /* activate all hardware breakpoints */
357 CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
359 if (enable_watchpoint) {
360 /* activate all watchpoints */
361 CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
364 /* restore interrupt stack */
365 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
366 nds32_v2_restore_interrupt_stack(nds32_v2);
368 /* restore PSW, PC, and R0 ... after flushing any modified
369 * registers.
371 CHECK_RETVAL(nds32_restore_context(target));
373 register_cache_invalidate(nds32->core_cache);
375 return ERROR_OK;
378 static int nds32_v2_deassert_reset(struct target *target)
380 int retval;
382 CHECK_RETVAL(nds32_poll(target));
384 if (target->state != TARGET_HALTED) {
385 /* reset only */
386 LOG_WARNING("%s: ran after reset and before halt ...",
387 target_name(target));
388 retval = target_halt(target);
389 if (retval != ERROR_OK)
390 return retval;
393 return ERROR_OK;
396 static int nds32_v2_checksum_memory(struct target *target,
397 target_addr_t address, uint32_t count, uint32_t *checksum)
399 LOG_WARNING("Not implemented: %s", __func__);
401 return ERROR_FAIL;
404 static int nds32_v2_add_breakpoint(struct target *target,
405 struct breakpoint *breakpoint)
407 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
408 struct nds32 *nds32 = &(nds32_v2->nds32);
409 int result;
411 if (breakpoint->type == BKPT_HARD) {
412 /* check hardware resource */
413 if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
414 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
415 "breakpoints/watchpoints! The limit of "
416 "combined hardware breakpoints/watchpoints "
417 "is %" PRId32 ". -->", nds32_v2->n_hbr);
418 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
421 /* update next place to put hardware breakpoint */
422 nds32_v2->next_hbr_index++;
424 /* hardware breakpoint insertion occurs before 'continue' actually */
425 return ERROR_OK;
426 } else if (breakpoint->type == BKPT_SOFT) {
427 result = nds32_add_software_breakpoint(target, breakpoint);
428 if (result != ERROR_OK) {
429 /* auto convert to hardware breakpoint if failed */
430 if (nds32->auto_convert_hw_bp) {
431 /* convert to hardware breakpoint */
432 breakpoint->type = BKPT_HARD;
434 return nds32_v2_add_breakpoint(target, breakpoint);
438 return result;
439 } else /* unrecognized breakpoint type */
440 return ERROR_FAIL;
442 return ERROR_OK;
445 static int nds32_v2_remove_breakpoint(struct target *target,
446 struct breakpoint *breakpoint)
448 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
450 if (breakpoint->type == BKPT_HARD) {
451 if (nds32_v2->next_hbr_index <= 0)
452 return ERROR_FAIL;
454 /* update next place to put hardware breakpoint */
455 nds32_v2->next_hbr_index--;
457 /* hardware breakpoint removal occurs after 'halted' actually */
458 return ERROR_OK;
459 } else if (breakpoint->type == BKPT_SOFT) {
460 return nds32_remove_software_breakpoint(target, breakpoint);
461 } else /* unrecognized breakpoint type */
462 return ERROR_FAIL;
464 return ERROR_OK;
467 static int nds32_v2_add_watchpoint(struct target *target,
468 struct watchpoint *watchpoint)
470 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
472 /* check hardware resource */
473 if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
474 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
475 "breakpoints/watchpoints! The limit of "
476 "combined hardware breakpoints/watchpoints is %" PRId32 ". -->", nds32_v2->n_hbr);
477 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
480 /* update next place to put hardware watchpoint */
481 nds32_v2->next_hbr_index++;
483 return ERROR_OK;
486 static int nds32_v2_remove_watchpoint(struct target *target,
487 struct watchpoint *watchpoint)
489 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
491 if (nds32_v2->next_hbr_index <= 0)
492 return ERROR_FAIL;
494 /* update next place to put hardware breakpoint */
495 nds32_v2->next_hbr_index--;
497 return ERROR_OK;
500 static int nds32_v2_get_exception_address(struct nds32 *nds32,
501 uint32_t *address, uint32_t reason)
503 struct aice_port_s *aice = target_to_aice(nds32->target);
505 aice_read_register(aice, IR4, address); /* read $EVA directly */
507 /* TODO: hit multiple watchpoints */
509 return ERROR_OK;
513 * find out which watchpoint hits
514 * get exception address and compare the address to watchpoints
516 static int nds32_v2_hit_watchpoint(struct target *target,
517 struct watchpoint **hit_watchpoint)
519 uint32_t exception_address;
520 struct watchpoint *wp;
521 static struct watchpoint scan_all_watchpoint;
522 struct nds32 *nds32 = target_to_nds32(target);
524 scan_all_watchpoint.address = 0;
525 scan_all_watchpoint.rw = WPT_WRITE;
526 scan_all_watchpoint.next = 0;
527 scan_all_watchpoint.unique_id = 0x5CA8;
529 exception_address = nds32->watched_address;
531 if (exception_address == 0) {
532 /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */
533 *hit_watchpoint = &scan_all_watchpoint;
534 return ERROR_OK;
537 for (wp = target->watchpoints; wp; wp = wp->next) {
538 if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
539 /* TODO: dispel false match */
540 *hit_watchpoint = wp;
541 return ERROR_OK;
545 return ERROR_FAIL;
548 static int nds32_v2_run_algorithm(struct target *target,
549 int num_mem_params,
550 struct mem_param *mem_params,
551 int num_reg_params,
552 struct reg_param *reg_params,
553 target_addr_t entry_point,
554 target_addr_t exit_point,
555 int timeout_ms,
556 void *arch_info)
558 LOG_WARNING("Not implemented: %s", __func__);
560 return ERROR_FAIL;
563 static int nds32_v2_target_create(struct target *target, Jim_Interp *interp)
565 struct nds32_v2_common *nds32_v2;
567 nds32_v2 = calloc(1, sizeof(*nds32_v2));
568 if (!nds32_v2)
569 return ERROR_FAIL;
571 nds32_v2->nds32.register_map = nds32_v2_register_mapping;
572 nds32_v2->nds32.get_debug_reason = nds32_v2_get_debug_reason;
573 nds32_v2->nds32.enter_debug_state = nds32_v2_debug_entry;
574 nds32_v2->nds32.leave_debug_state = nds32_v2_leave_debug_state;
575 nds32_v2->nds32.get_watched_address = nds32_v2_get_exception_address;
577 nds32_init_arch_info(target, &(nds32_v2->nds32));
579 return ERROR_OK;
582 static int nds32_v2_init_target(struct command_context *cmd_ctx,
583 struct target *target)
585 /* Initialize anything we can set up without talking to the target */
587 struct nds32 *nds32 = target_to_nds32(target);
589 nds32_init(nds32);
591 return ERROR_OK;
594 /* talk to the target and set things up */
595 static int nds32_v2_examine(struct target *target)
597 struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
598 struct nds32 *nds32 = &(nds32_v2->nds32);
599 struct aice_port_s *aice = target_to_aice(target);
601 if (!target_was_examined(target)) {
602 CHECK_RETVAL(nds32_edm_config(nds32));
604 if (nds32->reset_halt_as_examine)
605 CHECK_RETVAL(nds32_reset_halt(nds32));
608 uint32_t edm_cfg;
609 aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
611 /* get the number of hardware breakpoints */
612 nds32_v2->n_hbr = (edm_cfg & 0x7) + 1;
614 nds32_v2->next_hbr_index = 0;
616 LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target),
617 nds32_v2->n_hbr);
619 nds32->target->state = TARGET_RUNNING;
620 nds32->target->debug_reason = DBG_REASON_NOTHALTED;
622 target_set_examined(target);
624 return ERROR_OK;
627 static int nds32_v2_translate_address(struct target *target, target_addr_t *address)
629 struct nds32 *nds32 = target_to_nds32(target);
630 struct nds32_memory *memory = &(nds32->memory);
631 target_addr_t physical_address;
633 /* Following conditions need to do address translation
634 * 1. BUS mode
635 * 2. CPU mode under maximum interrupt level */
636 if ((memory->access_channel == NDS_MEMORY_ACC_BUS) ||
637 ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
638 nds32_reach_max_interrupt_level(nds32))) {
639 if (target->type->virt2phys(target, *address, &physical_address) == ERROR_OK)
640 *address = physical_address;
641 else
642 return ERROR_FAIL;
645 return ERROR_OK;
648 static int nds32_v2_read_buffer(struct target *target, target_addr_t address,
649 uint32_t size, uint8_t *buffer)
651 struct nds32 *nds32 = target_to_nds32(target);
652 struct nds32_memory *memory = &(nds32->memory);
654 if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
655 (target->state != TARGET_HALTED)) {
656 LOG_WARNING("target was not halted");
657 return ERROR_TARGET_NOT_HALTED;
660 /* BUG: If access range crosses multiple pages, the translation will not correct
661 * for second page or so. */
663 nds32_v2_translate_address(target, &address);
665 return nds32_read_buffer(target, address, size, buffer);
668 static int nds32_v2_write_buffer(struct target *target, target_addr_t address,
669 uint32_t size, const uint8_t *buffer)
671 struct nds32 *nds32 = target_to_nds32(target);
672 struct nds32_memory *memory = &(nds32->memory);
674 if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
675 (target->state != TARGET_HALTED)) {
676 LOG_WARNING("target was not halted");
677 return ERROR_TARGET_NOT_HALTED;
680 /* BUG: If access range crosses multiple pages, the translation will not correct
681 * for second page or so. */
683 nds32_v2_translate_address(target, &address);
685 return nds32_write_buffer(target, address, size, buffer);
688 static int nds32_v2_read_memory(struct target *target, target_addr_t address,
689 uint32_t size, uint32_t count, uint8_t *buffer)
691 struct nds32 *nds32 = target_to_nds32(target);
692 struct nds32_memory *memory = &(nds32->memory);
694 if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
695 (target->state != TARGET_HALTED)) {
696 LOG_WARNING("target was not halted");
697 return ERROR_TARGET_NOT_HALTED;
700 /* BUG: If access range crosses multiple pages, the translation will not correct
701 * for second page or so. */
703 nds32_v2_translate_address(target, &address);
705 return nds32_read_memory(target, address, size, count, buffer);
708 static int nds32_v2_write_memory(struct target *target, target_addr_t address,
709 uint32_t size, uint32_t count, const uint8_t *buffer)
711 struct nds32 *nds32 = target_to_nds32(target);
712 struct nds32_memory *memory = &(nds32->memory);
714 if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
715 (target->state != TARGET_HALTED)) {
716 LOG_WARNING("target was not halted");
717 return ERROR_TARGET_NOT_HALTED;
720 /* BUG: If access range crosses multiple pages, the translation will not correct
721 * for second page or so. */
723 nds32_v2_translate_address(target, &address);
725 return nds32_write_memory(target, address, size, count, buffer);
728 /** Holds methods for V2 targets. */
729 struct target_type nds32_v2_target = {
730 .name = "nds32_v2",
732 .poll = nds32_poll,
733 .arch_state = nds32_arch_state,
735 .target_request_data = nds32_v2_target_request_data,
737 .halt = nds32_halt,
738 .resume = nds32_resume,
739 .step = nds32_step,
741 .assert_reset = nds32_assert_reset,
742 .deassert_reset = nds32_v2_deassert_reset,
744 /* register access */
745 .get_gdb_reg_list = nds32_get_gdb_reg_list,
747 /* memory access */
748 .read_buffer = nds32_v2_read_buffer,
749 .write_buffer = nds32_v2_write_buffer,
750 .read_memory = nds32_v2_read_memory,
751 .write_memory = nds32_v2_write_memory,
753 .checksum_memory = nds32_v2_checksum_memory,
755 /* breakpoint/watchpoint */
756 .add_breakpoint = nds32_v2_add_breakpoint,
757 .remove_breakpoint = nds32_v2_remove_breakpoint,
758 .add_watchpoint = nds32_v2_add_watchpoint,
759 .remove_watchpoint = nds32_v2_remove_watchpoint,
760 .hit_watchpoint = nds32_v2_hit_watchpoint,
762 /* MMU */
763 .mmu = nds32_mmu,
764 .virt2phys = nds32_virtual_to_physical,
765 .read_phys_memory = nds32_read_phys_memory,
766 .write_phys_memory = nds32_write_phys_memory,
768 .run_algorithm = nds32_v2_run_algorithm,
770 .commands = nds32_command_handlers,
771 .target_create = nds32_v2_target_create,
772 .init_target = nds32_v2_init_target,
773 .examine = nds32_v2_examine,