1 /***************************************************************************
2 * Copyright (C) 2013 Andes Technology *
3 * Hsiangkai Wang <hkwang@andestech.com> *
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. *
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. *
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 ***************************************************************************/
25 #include "breakpoints.h"
26 #include "nds32_cmd.h"
27 #include "nds32_aice.h"
29 #include "nds32_v3_common.h"
31 static int nds32_v3_activate_hardware_breakpoint(struct target
*target
)
33 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
34 struct aice_port_s
*aice
= target_to_aice(target
);
35 struct breakpoint
*bp
;
36 int32_t hbr_index
= nds32_v3
->next_hbr_index
;
38 for (bp
= target
->breakpoints
; bp
; bp
= bp
->next
) {
39 if (bp
->type
== BKPT_SOFT
) {
40 /* already set at nds32_v3_add_breakpoint() */
42 } else if (bp
->type
== BKPT_HARD
) {
45 aice_write_debug_reg(aice
, NDS_EDM_SR_BPA0
+ hbr_index
, bp
->address
);
47 aice_write_debug_reg(aice
, NDS_EDM_SR_BPAM0
+ hbr_index
, 0);
49 aice_write_debug_reg(aice
, NDS_EDM_SR_BPV0
+ hbr_index
, 0);
51 if (nds32_v3
->nds32
.memory
.address_translation
)
52 /* enable breakpoint (virtual address) */
53 aice_write_debug_reg(aice
, NDS_EDM_SR_BPC0
+ hbr_index
, 0x2);
55 /* enable breakpoint (physical address) */
56 aice_write_debug_reg(aice
, NDS_EDM_SR_BPC0
+ hbr_index
, 0xA);
58 LOG_DEBUG("Add hardware BP %d at %08" PRIx32
, hbr_index
,
68 static int nds32_v3_deactivate_hardware_breakpoint(struct target
*target
)
70 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
71 struct aice_port_s
*aice
= target_to_aice(target
);
72 struct breakpoint
*bp
;
73 int32_t hbr_index
= nds32_v3
->next_hbr_index
;
75 for (bp
= target
->breakpoints
; bp
; bp
= bp
->next
) {
76 if (bp
->type
== BKPT_SOFT
) {
78 } else if (bp
->type
== BKPT_HARD
) {
80 /* disable breakpoint */
81 aice_write_debug_reg(aice
, NDS_EDM_SR_BPC0
+ hbr_index
, 0x0);
86 LOG_DEBUG("Remove hardware BP %d at %08" PRIx32
, hbr_index
,
93 static int nds32_v3_activate_hardware_watchpoint(struct target
*target
)
95 struct aice_port_s
*aice
= target_to_aice(target
);
96 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
97 struct watchpoint
*wp
;
99 uint32_t wp_config
= 0;
100 bool ld_stop
, st_stop
;
102 if (nds32_v3
->nds32
.global_stop
)
103 ld_stop
= st_stop
= false;
105 for (wp
= target
->watchpoints
; wp
; wp
= wp
->next
) {
107 if (wp_num
< nds32_v3
->used_n_wp
) {
108 wp
->mask
= wp
->length
- 1;
109 if ((wp
->address
% wp
->length
) != 0)
110 wp
->mask
= (wp
->mask
<< 1) + 1;
112 if (wp
->rw
== WPT_READ
)
114 else if (wp
->rw
== WPT_WRITE
)
116 else if (wp
->rw
== WPT_ACCESS
)
119 /* set/unset physical address bit of BPCn according to PSW.DT */
120 if (nds32_v3
->nds32
.memory
.address_translation
== false)
124 aice_write_debug_reg(aice
, NDS_EDM_SR_BPA0
+ wp_num
,
125 wp
->address
- (wp
->address
% wp
->length
));
127 aice_write_debug_reg(aice
, NDS_EDM_SR_BPAM0
+ wp_num
, wp
->mask
);
128 /* enable watchpoint */
129 aice_write_debug_reg(aice
, NDS_EDM_SR_BPC0
+ wp_num
, wp_config
);
131 aice_write_debug_reg(aice
, NDS_EDM_SR_BPV0
+ wp_num
, 0);
133 LOG_DEBUG("Add hardware wathcpoint %d at %08" PRIx32
" mask %08" PRIx32
,
134 wp_num
, wp
->address
, wp
->mask
);
137 } else if (nds32_v3
->nds32
.global_stop
) {
138 if (wp
->rw
== WPT_READ
)
140 else if (wp
->rw
== WPT_WRITE
)
142 else if (wp
->rw
== WPT_ACCESS
)
143 ld_stop
= st_stop
= true;
147 if (nds32_v3
->nds32
.global_stop
) {
149 aice_read_debug_reg(aice
, NDS_EDM_SR_EDM_CTL
, &edm_ctl
);
154 aice_write_debug_reg(aice
, NDS_EDM_SR_EDM_CTL
, edm_ctl
);
160 static int nds32_v3_deactivate_hardware_watchpoint(struct target
*target
)
162 struct aice_port_s
*aice
= target_to_aice(target
);
163 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
165 struct watchpoint
*wp
;
166 bool clean_global_stop
= false;
168 for (wp
= target
->watchpoints
; wp
; wp
= wp
->next
) {
170 if (wp_num
< nds32_v3
->used_n_wp
) {
171 /* disable watchpoint */
172 aice_write_debug_reg(aice
, NDS_EDM_SR_BPC0
+ wp_num
, 0x0);
174 LOG_DEBUG("Remove hardware wathcpoint %d at %08" PRIx32
175 " mask %08" PRIx32
, wp_num
,
176 wp
->address
, wp
->mask
);
178 } else if (nds32_v3
->nds32
.global_stop
) {
179 clean_global_stop
= true;
183 if (clean_global_stop
) {
185 aice_read_debug_reg(aice
, NDS_EDM_SR_EDM_CTL
, &edm_ctl
);
186 edm_ctl
= edm_ctl
& (~0x30);
187 aice_write_debug_reg(aice
, NDS_EDM_SR_EDM_CTL
, edm_ctl
);
193 static int nds32_v3_check_interrupt_stack(struct nds32
*nds32
)
198 /* Save interrupt level */
199 nds32_get_mapped_reg(nds32
, IR0
, &val_ir0
);
200 nds32
->current_interrupt_level
= (val_ir0
>> 1) & 0x3;
202 if (nds32_reach_max_interrupt_level(nds32
))
203 LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %d. -->",
204 nds32
->current_interrupt_level
);
206 /* backup $ir4 & $ir6 to avoid suppressed exception overwrite */
207 nds32_get_mapped_reg(nds32
, IR4
, &value
);
208 nds32_get_mapped_reg(nds32
, IR6
, &value
);
213 static int nds32_v3_restore_interrupt_stack(struct nds32
*nds32
)
217 /* get backup value from cache */
218 /* then set back to make the register dirty */
219 nds32_get_mapped_reg(nds32
, IR0
, &value
);
220 nds32_set_mapped_reg(nds32
, IR0
, value
);
222 nds32_get_mapped_reg(nds32
, IR4
, &value
);
223 nds32_set_mapped_reg(nds32
, IR4
, value
);
225 nds32_get_mapped_reg(nds32
, IR6
, &value
);
226 nds32_set_mapped_reg(nds32
, IR6
, value
);
231 static int nds32_v3_deassert_reset(struct target
*target
)
234 struct aice_port_s
*aice
= target_to_aice(target
);
235 bool switch_to_v3_stack
= false;
236 uint32_t value_edm_ctl
;
238 aice_read_debug_reg(aice
, NDS_EDM_SR_EDM_CTL
, &value_edm_ctl
);
239 if (((value_edm_ctl
>> 6) & 0x1) == 0) { /* reset to V2 EDM mode */
240 aice_write_debug_reg(aice
, NDS_EDM_SR_EDM_CTL
, value_edm_ctl
| (0x1 << 6));
241 aice_read_debug_reg(aice
, NDS_EDM_SR_EDM_CTL
, &value_edm_ctl
);
242 if (((value_edm_ctl
>> 6) & 0x1) == 1)
243 switch_to_v3_stack
= true;
245 switch_to_v3_stack
= false;
247 CHECK_RETVAL(nds32_poll(target
));
249 if (target
->state
!= TARGET_HALTED
) {
251 LOG_WARNING("%s: ran after reset and before halt ...",
252 target_name(target
));
253 retval
= target_halt(target
);
254 if (retval
!= ERROR_OK
)
257 /* call target_poll() to avoid "Halt timed out" */
258 CHECK_RETVAL(target_poll(target
));
261 jtag_poll_set_enabled(false);
263 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
264 struct nds32
*nds32
= &(nds32_v3
->nds32
);
266 uint32_t interrupt_level
;
268 if (switch_to_v3_stack
== true) {
270 nds32_get_mapped_reg(nds32
, IR0
, &value
);
271 interrupt_level
= (value
>> 1) & 0x3;
274 value
|= (interrupt_level
<< 1);
275 value
|= 0x400; /* set PSW.DEX */
276 nds32_set_mapped_reg(nds32
, IR0
, value
);
278 /* copy IPC to OIPC */
279 if ((interrupt_level
+ 1) < nds32
->max_interrupt_level
) {
280 nds32_get_mapped_reg(nds32
, IR9
, &value
);
281 nds32_set_mapped_reg(nds32
, IR11
, value
);
289 static int nds32_v3_add_breakpoint(struct target
*target
,
290 struct breakpoint
*breakpoint
)
292 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
293 struct nds32
*nds32
= &(nds32_v3
->nds32
);
296 if (breakpoint
->type
== BKPT_HARD
) {
297 /* check hardware resource */
298 if (nds32_v3
->n_hbr
<= nds32_v3
->next_hbr_index
) {
299 LOG_WARNING("<-- TARGET WARNING! Insert too many "
300 "hardware breakpoints/watchpoints! "
301 "The limit of combined hardware "
302 "breakpoints/watchpoints is %d. -->",
304 LOG_WARNING("<-- TARGET STATUS: Inserted number of "
305 "hardware breakpoint: %d, hardware "
306 "watchpoints: %d. -->",
307 nds32_v3
->next_hbr_index
- nds32_v3
->used_n_wp
,
308 nds32_v3
->used_n_wp
);
309 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
312 /* update next place to put hardware breakpoint */
313 nds32_v3
->next_hbr_index
++;
315 /* hardware breakpoint insertion occurs before 'continue' actually */
317 } else if (breakpoint
->type
== BKPT_SOFT
) {
318 result
= nds32_add_software_breakpoint(target
, breakpoint
);
319 if (ERROR_OK
!= result
) {
320 /* auto convert to hardware breakpoint if failed */
321 if (nds32
->auto_convert_hw_bp
) {
322 /* convert to hardware breakpoint */
323 breakpoint
->type
= BKPT_HARD
;
325 return nds32_v3_add_breakpoint(target
, breakpoint
);
330 } else /* unrecognized breakpoint type */
336 static int nds32_v3_remove_breakpoint(struct target
*target
,
337 struct breakpoint
*breakpoint
)
339 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
341 if (breakpoint
->type
== BKPT_HARD
) {
342 if (nds32_v3
->next_hbr_index
<= 0)
345 /* update next place to put hardware breakpoint */
346 nds32_v3
->next_hbr_index
--;
348 /* hardware breakpoint removal occurs after 'halted' actually */
350 } else if (breakpoint
->type
== BKPT_SOFT
) {
351 return nds32_remove_software_breakpoint(target
, breakpoint
);
352 } else /* unrecognized breakpoint type */
358 static int nds32_v3_add_watchpoint(struct target
*target
,
359 struct watchpoint
*watchpoint
)
361 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
363 /* check hardware resource */
364 if (nds32_v3
->n_hbr
<= nds32_v3
->next_hbr_index
) {
365 /* No hardware resource */
366 if (nds32_v3
->nds32
.global_stop
) {
367 LOG_WARNING("<-- TARGET WARNING! The number of "
368 "watchpoints exceeds the hardware "
369 "resources. Stop at every load/store "
370 "instruction to check for watchpoint matches. -->");
374 LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
375 "breakpoints/watchpoints! The limit of combined "
376 "hardware breakpoints/watchpoints is %d. -->",
378 LOG_WARNING("<-- TARGET STATUS: Inserted number of "
379 "hardware breakpoint: %d, hardware "
380 "watchpoints: %d. -->",
381 nds32_v3
->next_hbr_index
- nds32_v3
->used_n_wp
,
382 nds32_v3
->used_n_wp
);
384 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
387 /* update next place to put hardware watchpoint */
388 nds32_v3
->next_hbr_index
++;
389 nds32_v3
->used_n_wp
++;
394 static int nds32_v3_remove_watchpoint(struct target
*target
,
395 struct watchpoint
*watchpoint
)
397 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
399 if (nds32_v3
->next_hbr_index
<= 0) {
400 if (nds32_v3
->nds32
.global_stop
)
406 /* update next place to put hardware breakpoint */
407 nds32_v3
->next_hbr_index
--;
408 nds32_v3
->used_n_wp
--;
413 struct nds32_v3_common_callback nds32_v3_common_callback
= {
414 .check_interrupt_stack
= nds32_v3_check_interrupt_stack
,
415 .restore_interrupt_stack
= nds32_v3_restore_interrupt_stack
,
416 .activate_hardware_breakpoint
= nds32_v3_activate_hardware_breakpoint
,
417 .activate_hardware_watchpoint
= nds32_v3_activate_hardware_watchpoint
,
418 .deactivate_hardware_breakpoint
= nds32_v3_deactivate_hardware_breakpoint
,
419 .deactivate_hardware_watchpoint
= nds32_v3_deactivate_hardware_watchpoint
,
422 static int nds32_v3_target_create(struct target
*target
, Jim_Interp
*interp
)
424 struct nds32_v3_common
*nds32_v3
;
426 nds32_v3
= calloc(1, sizeof(*nds32_v3
));
430 nds32_v3_common_register_callback(&nds32_v3_common_callback
);
431 nds32_v3_target_create_common(target
, &(nds32_v3
->nds32
));
436 /* talk to the target and set things up */
437 static int nds32_v3_examine(struct target
*target
)
439 struct nds32_v3_common
*nds32_v3
= target_to_nds32_v3(target
);
440 struct nds32
*nds32
= &(nds32_v3
->nds32
);
441 struct aice_port_s
*aice
= target_to_aice(target
);
443 if (!target_was_examined(target
)) {
444 CHECK_RETVAL(nds32_edm_config(nds32
));
446 if (nds32
->reset_halt_as_examine
)
447 CHECK_RETVAL(nds32_reset_halt(nds32
));
451 aice_read_debug_reg(aice
, NDS_EDM_SR_EDM_CFG
, &edm_cfg
);
453 /* get the number of hardware breakpoints */
454 nds32_v3
->n_hbr
= (edm_cfg
& 0x7) + 1;
456 /* low interference profiling */
458 nds32_v3
->low_interference_profile
= true;
460 nds32_v3
->low_interference_profile
= false;
462 nds32_v3
->next_hbr_index
= 0;
463 nds32_v3
->used_n_wp
= 0;
465 LOG_INFO("%s: total hardware breakpoint %d", target_name(target
),
468 nds32
->target
->state
= TARGET_RUNNING
;
469 nds32
->target
->debug_reason
= DBG_REASON_NOTHALTED
;
471 target_set_examined(target
);
476 /** Holds methods for Andes1337 targets. */
477 struct target_type nds32_v3_target
= {
481 .arch_state
= nds32_arch_state
,
483 .target_request_data
= nds32_v3_target_request_data
,
486 .resume
= nds32_resume
,
489 .assert_reset
= nds32_assert_reset
,
490 .deassert_reset
= nds32_v3_deassert_reset
,
491 .soft_reset_halt
= nds32_v3_soft_reset_halt
,
493 /* register access */
494 .get_gdb_reg_list
= nds32_get_gdb_reg_list
,
497 .read_buffer
= nds32_v3_read_buffer
,
498 .write_buffer
= nds32_v3_write_buffer
,
499 .read_memory
= nds32_v3_read_memory
,
500 .write_memory
= nds32_v3_write_memory
,
502 .checksum_memory
= nds32_v3_checksum_memory
,
504 /* breakpoint/watchpoint */
505 .add_breakpoint
= nds32_v3_add_breakpoint
,
506 .remove_breakpoint
= nds32_v3_remove_breakpoint
,
507 .add_watchpoint
= nds32_v3_add_watchpoint
,
508 .remove_watchpoint
= nds32_v3_remove_watchpoint
,
512 .virt2phys
= nds32_virtual_to_physical
,
513 .read_phys_memory
= nds32_read_phys_memory
,
514 .write_phys_memory
= nds32_write_phys_memory
,
516 .run_algorithm
= nds32_v3_run_algorithm
,
518 .commands
= nds32_command_handlers
,
519 .target_create
= nds32_v3_target_create
,
520 .init_target
= nds32_v3_init_target
,
521 .examine
= nds32_v3_examine
,
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)