2 * Copyright (C) 2009 by David Brownell
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include <jtag/jtag.h>
28 #include "breakpoints.h"
29 #include "target_type.h"
30 #include "arm_opcodes.h"
35 * Implements various ARM DPM operations using architectural debug registers.
36 * These routines layer over core-specific communication methods to cope with
37 * implementation differences between cores like ARM1136 and Cortex-A8.
39 * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by
40 * Part C (Debug Architecture) of the ARM Architecture Reference Manual,
41 * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations
42 * are abstracted through internal programming interfaces to share code and
43 * to minimize needless differences in debug behavior between cores.
46 /*----------------------------------------------------------------------*/
52 /* Read coprocessor */
53 static int dpm_mrc(struct target
*target
, int cpnum
,
54 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
57 struct arm
*arm
= target_to_arm(target
);
58 struct arm_dpm
*dpm
= arm
->dpm
;
61 retval
= dpm
->prepare(dpm
);
62 if (retval
!= ERROR_OK
)
65 LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum
,
67 (int) CRm
, (int) op2
);
69 /* read coprocessor register into R0; return via DCC */
70 retval
= dpm
->instr_read_data_r0(dpm
,
71 ARMV4_5_MRC(cpnum
, op1
, 0, CRn
, CRm
, op2
),
74 /* (void) */ dpm
->finish(dpm
);
78 static int dpm_mcr(struct target
*target
, int cpnum
,
79 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
82 struct arm
*arm
= target_to_arm(target
);
83 struct arm_dpm
*dpm
= arm
->dpm
;
86 retval
= dpm
->prepare(dpm
);
87 if (retval
!= ERROR_OK
)
90 LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum
,
92 (int) CRm
, (int) op2
);
94 /* read DCC into r0; then write coprocessor register from R0 */
95 retval
= dpm
->instr_write_data_r0(dpm
,
96 ARMV4_5_MCR(cpnum
, op1
, 0, CRn
, CRm
, op2
),
99 /* (void) */ dpm
->finish(dpm
);
103 /*----------------------------------------------------------------------*/
106 * Register access utilities
109 /* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
110 * Routines *must* restore the original mode before returning!!
112 static int dpm_modeswitch(struct arm_dpm
*dpm
, enum arm_mode mode
)
117 /* restore previous mode */
118 if (mode
== ARM_MODE_ANY
)
119 cpsr
= buf_get_u32(dpm
->arm
->cpsr
->value
, 0, 32);
121 /* else force to the specified mode */
125 retval
= dpm
->instr_write_data_r0(dpm
, ARMV4_5_MSR_GP(0, 0xf, 0), cpsr
);
127 if (dpm
->instr_cpsr_sync
)
128 retval
= dpm
->instr_cpsr_sync(dpm
);
133 /* just read the register -- rely on the core mode being right */
134 static int dpm_read_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
141 /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
142 retval
= dpm
->instr_read_data_dcc(dpm
,
143 ARMV4_5_MCR(14, 0, regnum
, 0, 5, 0),
147 /* "MOV r0, pc"; then return via DCC */
148 retval
= dpm
->instr_read_data_r0(dpm
, 0xe1a0000f, &value
);
150 /* NOTE: this seems like a slightly awkward place to update
151 * this value ... but if the PC gets written (the only way
152 * to change what we compute), the arch spec says subsequent
153 * reads return values which are "unpredictable". So this
154 * is always right except in those broken-by-intent cases.
156 switch (dpm
->arm
->core_state
) {
160 case ARM_STATE_THUMB
:
161 case ARM_STATE_THUMB_EE
:
164 case ARM_STATE_JAZELLE
:
165 /* core-specific ... ? */
166 LOG_WARNING("Jazelle PC adjustment unknown");
171 /* 16: "MRS r0, CPSR"; then return via DCC
172 * 17: "MRS r0, SPSR"; then return via DCC
174 retval
= dpm
->instr_read_data_r0(dpm
,
175 ARMV4_5_MRS(0, regnum
& 1),
180 if (retval
== ERROR_OK
) {
181 buf_set_u32(r
->value
, 0, 32, value
);
184 LOG_DEBUG("READ: %s, %8.8x", r
->name
, (unsigned) value
);
190 /* just write the register -- rely on the core mode being right */
191 static int dpm_write_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
194 uint32_t value
= buf_get_u32(r
->value
, 0, 32);
198 /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
199 retval
= dpm
->instr_write_data_dcc(dpm
,
200 ARMV4_5_MRC(14, 0, regnum
, 0, 5, 0),
204 /* read r0 from DCC; then "MOV pc, r0" */
205 retval
= dpm
->instr_write_data_r0(dpm
, 0xe1a0f000, value
);
208 /* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf"
209 * 17: read r0 from DCC, then "MSR r0, SPSR_cxsf"
211 retval
= dpm
->instr_write_data_r0(dpm
,
212 ARMV4_5_MSR_GP(0, 0xf, regnum
& 1),
215 if (regnum
== 16 && dpm
->instr_cpsr_sync
)
216 retval
= dpm
->instr_cpsr_sync(dpm
);
221 if (retval
== ERROR_OK
) {
223 LOG_DEBUG("WRITE: %s, %8.8x", r
->name
, (unsigned) value
);
230 * Read basic registers of the the current context: R0 to R15, and CPSR;
231 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
232 * In normal operation this is called on entry to halting debug state,
233 * possibly after some other operations supporting restore of debug state
234 * or making sure the CPU is fully idle (drain write buffer, etc).
236 int arm_dpm_read_current_registers(struct arm_dpm
*dpm
)
238 struct arm
*arm
= dpm
->arm
;
243 retval
= dpm
->prepare(dpm
);
244 if (retval
!= ERROR_OK
)
247 /* read R0 first (it's used for scratch), then CPSR */
248 r
= arm
->core_cache
->reg_list
+ 0;
250 retval
= dpm_read_reg(dpm
, r
, 0);
251 if (retval
!= ERROR_OK
)
256 retval
= dpm
->instr_read_data_r0(dpm
, ARMV4_5_MRS(0, 0), &cpsr
);
257 if (retval
!= ERROR_OK
)
260 /* update core mode and state, plus shadow mapping for R8..R14 */
261 arm_set_cpsr(arm
, cpsr
);
263 /* REVISIT we can probably avoid reading R1..R14, saving time... */
264 for (unsigned i
= 1; i
< 16; i
++) {
265 r
= arm_reg_current(arm
, i
);
269 retval
= dpm_read_reg(dpm
, r
, i
);
270 if (retval
!= ERROR_OK
)
274 /* NOTE: SPSR ignored (if it's even relevant). */
276 /* REVISIT the debugger can trigger various exceptions. See the
277 * ARMv7A architecture spec, section C5.7, for more info about
278 * what defenses are needed; v6 debug has the most issues.
282 /* (void) */ dpm
->finish(dpm
);
286 /* Avoid needless I/O ... leave breakpoints and watchpoints alone
287 * unless they're removed, or need updating because of single-stepping
288 * or running debugger code.
290 static int dpm_maybe_update_bpwp(struct arm_dpm
*dpm
, bool bpwp
,
291 struct dpm_bpwp
*xp
, int *set_p
)
293 int retval
= ERROR_OK
;
300 /* removed or startup; we must disable it */
305 /* disabled, but we must set it */
306 xp
->dirty
= disable
= false;
311 /* set, but we must temporarily disable it */
312 xp
->dirty
= disable
= true;
317 retval
= dpm
->bpwp_disable(dpm
, xp
->number
);
319 retval
= dpm
->bpwp_enable(dpm
, xp
->number
,
320 xp
->address
, xp
->control
);
322 if (retval
!= ERROR_OK
)
323 LOG_ERROR("%s: can't %s HW bp/wp %d",
324 disable
? "disable" : "enable",
325 target_name(dpm
->arm
->target
),
332 * Writes all modified core registers for all processor modes. In normal
333 * operation this is called on exit from halting debug state.
335 * @param dpm: represents the processor
336 * @param bpwp: true ensures breakpoints and watchpoints are set,
337 * false ensures they are cleared
339 int arm_dpm_write_dirty_registers(struct arm_dpm
*dpm
, bool bpwp
)
341 struct arm
*arm
= dpm
->arm
;
342 struct reg_cache
*cache
= arm
->core_cache
;
346 retval
= dpm
->prepare(dpm
);
347 if (retval
!= ERROR_OK
)
350 /* If we're managing hardware breakpoints for this core, enable
351 * or disable them as requested.
353 * REVISIT We don't yet manage them for ANY cores. Eventually
354 * we should be able to assume we handle them; but until then,
355 * cope with the hand-crafted breakpoint code.
358 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
359 struct dpm_bp
*dbp
= dpm
->dbp
+ i
;
360 struct breakpoint
*bp
= dbp
->bp
;
362 retval
= dpm_maybe_update_bpwp(dpm
, bpwp
, &dbp
->bpwp
,
363 bp
? &bp
->set
: NULL
);
367 /* enable/disable watchpoints */
368 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
369 struct dpm_wp
*dwp
= dpm
->dwp
+ i
;
370 struct watchpoint
*wp
= dwp
->wp
;
372 retval
= dpm_maybe_update_bpwp(dpm
, bpwp
, &dwp
->bpwp
,
373 wp
? &wp
->set
: NULL
);
376 /* NOTE: writes to breakpoint and watchpoint registers might
377 * be queued, and need (efficient/batched) flushing later.
380 /* Scan the registers until we find one that's both dirty and
381 * eligible for flushing. Flush that and everything else that
382 * shares the same core mode setting. Typically this won't
383 * actually find anything to do...
386 enum arm_mode mode
= ARM_MODE_ANY
;
390 /* check everything except our scratch register R0 */
391 for (unsigned i
= 1; i
< cache
->num_regs
; i
++) {
395 /* also skip PC, CPSR, and non-dirty */
398 if (arm
->cpsr
== cache
->reg_list
+ i
)
400 if (!cache
->reg_list
[i
].dirty
)
403 r
= cache
->reg_list
[i
].arch_info
;
406 /* may need to pick and set a mode */
411 mode
= tmode
= r
->mode
;
413 /* cope with special cases */
416 /* r8..r12 "anything but FIQ" case;
417 * we "know" core mode is accurate
418 * since we haven't changed it yet
420 if (arm
->core_mode
== ARM_MODE_FIQ
423 tmode
= ARM_MODE_USR
;
431 /* REVISIT error checks */
432 if (tmode
!= ARM_MODE_ANY
)
433 retval
= dpm_modeswitch(dpm
, tmode
);
438 retval
= dpm_write_reg(dpm
,
446 /* Restore original CPSR ... assuming either that we changed it,
447 * or it's dirty. Must write PC to ensure the return address is
448 * defined, and must not write it before CPSR.
450 retval
= dpm_modeswitch(dpm
, ARM_MODE_ANY
);
451 arm
->cpsr
->dirty
= false;
453 retval
= dpm_write_reg(dpm
, &cache
->reg_list
[15], 15);
454 cache
->reg_list
[15].dirty
= false;
456 /* flush R0 -- it's *very* dirty by now */
457 retval
= dpm_write_reg(dpm
, &cache
->reg_list
[0], 0);
458 cache
->reg_list
[0].dirty
= false;
460 /* (void) */ dpm
->finish(dpm
);
465 /* Returns ARM_MODE_ANY or temporary mode to use while reading the
466 * specified register ... works around flakiness from ARM core calls.
467 * Caller already filtered out SPSR access; mode is never MODE_SYS
470 static enum arm_mode
dpm_mapmode(struct arm
*arm
,
471 unsigned num
, enum arm_mode mode
)
473 enum arm_mode amode
= arm
->core_mode
;
475 /* don't switch if the mode is already correct */
476 if (amode
== ARM_MODE_SYS
)
477 amode
= ARM_MODE_USR
;
482 /* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */
487 /* r8..r12 aren't shadowed for anything except FIQ */
489 if (mode
== ARM_MODE_FIQ
)
492 /* r13/sp, and r14/lr are always shadowed */
497 LOG_WARNING("invalid register #%u", num
);
505 * Standard ARM register accessors ... there are three methods
506 * in "struct arm", to support individual read/write and bulk read
510 static int arm_dpm_read_core_reg(struct target
*target
, struct reg
*r
,
511 int regnum
, enum arm_mode mode
)
513 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
516 if (regnum
< 0 || regnum
> 16)
517 return ERROR_INVALID_ARGUMENTS
;
520 if (mode
!= ARM_MODE_ANY
)
523 mode
= dpm_mapmode(dpm
->arm
, regnum
, mode
);
525 /* REVISIT what happens if we try to read SPSR in a core mode
526 * which has no such register?
529 retval
= dpm
->prepare(dpm
);
530 if (retval
!= ERROR_OK
)
533 if (mode
!= ARM_MODE_ANY
) {
534 retval
= dpm_modeswitch(dpm
, mode
);
535 if (retval
!= ERROR_OK
)
539 retval
= dpm_read_reg(dpm
, r
, regnum
);
540 /* always clean up, regardless of error */
542 if (mode
!= ARM_MODE_ANY
)
543 /* (void) */ dpm_modeswitch(dpm
, ARM_MODE_ANY
);
546 /* (void) */ dpm
->finish(dpm
);
550 static int arm_dpm_write_core_reg(struct target
*target
, struct reg
*r
,
551 int regnum
, enum arm_mode mode
, uint32_t value
)
553 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
557 if (regnum
< 0 || regnum
> 16)
558 return ERROR_INVALID_ARGUMENTS
;
561 if (mode
!= ARM_MODE_ANY
)
564 mode
= dpm_mapmode(dpm
->arm
, regnum
, mode
);
566 /* REVISIT what happens if we try to write SPSR in a core mode
567 * which has no such register?
570 retval
= dpm
->prepare(dpm
);
571 if (retval
!= ERROR_OK
)
574 if (mode
!= ARM_MODE_ANY
) {
575 retval
= dpm_modeswitch(dpm
, mode
);
576 if (retval
!= ERROR_OK
)
580 retval
= dpm_write_reg(dpm
, r
, regnum
);
581 /* always clean up, regardless of error */
583 if (mode
!= ARM_MODE_ANY
)
584 /* (void) */ dpm_modeswitch(dpm
, ARM_MODE_ANY
);
587 /* (void) */ dpm
->finish(dpm
);
591 static int arm_dpm_full_context(struct target
*target
)
593 struct arm
*arm
= target_to_arm(target
);
594 struct arm_dpm
*dpm
= arm
->dpm
;
595 struct reg_cache
*cache
= arm
->core_cache
;
599 retval
= dpm
->prepare(dpm
);
600 if (retval
!= ERROR_OK
)
604 enum arm_mode mode
= ARM_MODE_ANY
;
608 /* We "know" arm_dpm_read_current_registers() was called so
609 * the unmapped registers (R0..R7, PC, AND CPSR) and some
610 * view of R8..R14 are current. We also "know" oddities of
611 * register mapping: special cases for R8..R12 and SPSR.
613 * Pick some mode with unread registers and read them all.
616 for (unsigned i
= 0; i
< cache
->num_regs
; i
++) {
619 if (cache
->reg_list
[i
].valid
)
621 r
= cache
->reg_list
[i
].arch_info
;
623 /* may need to pick a mode and set CPSR */
628 /* For R8..R12 when we've entered debug
629 * state in FIQ mode... patch mode.
631 if (mode
== ARM_MODE_ANY
)
634 /* REVISIT error checks */
635 retval
= dpm_modeswitch(dpm
, mode
);
640 /* CPSR was read, so "R16" must mean SPSR */
641 retval
= dpm_read_reg(dpm
,
643 (r
->num
== 16) ? 17 : r
->num
);
649 retval
= dpm_modeswitch(dpm
, ARM_MODE_ANY
);
650 /* (void) */ dpm
->finish(dpm
);
656 /*----------------------------------------------------------------------*/
659 * Breakpoint and Watchpoint support.
661 * Hardware {break,watch}points are usually left active, to minimize
662 * debug entry/exit costs. When they are set or cleared, it's done in
663 * batches. Also, DPM-conformant hardware can update debug registers
664 * regardless of whether the CPU is running or halted ... though that
665 * fact isn't currently leveraged.
668 static int dpm_watchpoint_setup(struct arm_dpm
*dpm
, unsigned index
,
669 struct watchpoint
*wp
)
671 uint32_t addr
= wp
->address
;
674 /* this hardware doesn't support data value matching or masking */
675 if (wp
->value
|| wp
->mask
!= ~(uint32_t)0) {
676 LOG_DEBUG("watchpoint values and masking not supported");
677 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
680 control
= (1 << 0) /* enable */
681 | (3 << 1); /* both user and privileged access */
695 /* Match 1, 2, or all 4 byte addresses in this word.
697 * FIXME: v7 hardware allows lengths up to 2 GB, and has eight
698 * byte address select bits. Support larger wp->length, if addr
699 * is suitably aligned.
701 switch (wp
->length
) {
703 control
|= (1 << (addr
& 3)) << 5;
707 /* require 2-byte alignment */
709 control
|= (3 << (addr
& 2)) << 5;
714 /* require 4-byte alignment */
721 LOG_DEBUG("bad watchpoint length or alignment");
722 return ERROR_INVALID_ARGUMENTS
;
725 /* other control bits:
726 * bits 9:12 == 0 ... only checking up to four byte addresses (v7 only)
727 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
728 * bit 20 == 0 ... not linked to a context ID
729 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
732 dpm
->dwp
[index
].wp
= wp
;
733 dpm
->dwp
[index
].bpwp
.address
= addr
& ~3;
734 dpm
->dwp
[index
].bpwp
.control
= control
;
735 dpm
->dwp
[index
].bpwp
.dirty
= true;
737 /* hardware is updated in write_dirty_registers() */
742 static int dpm_add_watchpoint(struct target
*target
, struct watchpoint
*wp
)
744 struct arm
*arm
= target_to_arm(target
);
745 struct arm_dpm
*dpm
= arm
->dpm
;
746 int retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
748 if (dpm
->bpwp_enable
) {
749 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
750 if (!dpm
->dwp
[i
].wp
) {
751 retval
= dpm_watchpoint_setup(dpm
, i
, wp
);
760 static int dpm_remove_watchpoint(struct target
*target
, struct watchpoint
*wp
)
762 struct arm
*arm
= target_to_arm(target
);
763 struct arm_dpm
*dpm
= arm
->dpm
;
764 int retval
= ERROR_INVALID_ARGUMENTS
;
766 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
767 if (dpm
->dwp
[i
].wp
== wp
) {
768 dpm
->dwp
[i
].wp
= NULL
;
769 dpm
->dwp
[i
].bpwp
.dirty
= true;
771 /* hardware is updated in write_dirty_registers() */
780 void arm_dpm_report_wfar(struct arm_dpm
*dpm
, uint32_t addr
)
782 switch (dpm
->arm
->core_state
) {
786 case ARM_STATE_THUMB
:
787 case ARM_STATE_THUMB_EE
:
790 case ARM_STATE_JAZELLE
:
797 /*----------------------------------------------------------------------*/
800 * Other debug and support utilities
803 void arm_dpm_report_dscr(struct arm_dpm
*dpm
, uint32_t dscr
)
805 struct target
*target
= dpm
->arm
->target
;
809 /* Examine debug reason */
810 switch (DSCR_ENTRY(dscr
)) {
811 case 6: /* Data abort (v6 only) */
812 case 7: /* Prefetch abort (v6 only) */
813 /* FALL THROUGH -- assume a v6 core in abort mode */
814 case 0: /* HALT request from debugger */
816 target
->debug_reason
= DBG_REASON_DBGRQ
;
818 case 1: /* HW breakpoint */
819 case 3: /* SW BKPT */
820 case 5: /* vector catch */
821 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
823 case 2: /* asynch watchpoint */
824 case 10: /* precise watchpoint */
825 target
->debug_reason
= DBG_REASON_WATCHPOINT
;
828 target
->debug_reason
= DBG_REASON_UNDEFINED
;
833 /*----------------------------------------------------------------------*/
836 * Setup and management support.
840 * Hooks up this DPM to its associated target; call only once.
841 * Initially this only covers the register cache.
843 * Oh, and watchpoints. Yeah.
845 int arm_dpm_setup(struct arm_dpm
*dpm
)
847 struct arm
*arm
= dpm
->arm
;
848 struct target
*target
= arm
->target
;
849 struct reg_cache
*cache
;
853 /* register access setup */
854 arm
->full_context
= arm_dpm_full_context
;
855 arm
->read_core_reg
= arm_dpm_read_core_reg
;
856 arm
->write_core_reg
= arm_dpm_write_core_reg
;
858 cache
= arm_build_reg_cache(target
, arm
);
862 *register_get_last_cache_p(&target
->reg_cache
) = cache
;
864 /* coprocessor access setup */
868 /* breakpoint and watchpoint setup */
869 target
->type
->add_watchpoint
= dpm_add_watchpoint
;
870 target
->type
->remove_watchpoint
= dpm_remove_watchpoint
;
872 /* FIXME add breakpoint support */
873 /* FIXME add vector catch support */
875 dpm
->nbp
= 1 + ((dpm
->didr
>> 24) & 0xf);
876 dpm
->dbp
= calloc(dpm
->nbp
, sizeof *dpm
->dbp
);
878 dpm
->nwp
= 1 + ((dpm
->didr
>> 28) & 0xf);
879 dpm
->dwp
= calloc(dpm
->nwp
, sizeof *dpm
->dwp
);
881 if (!dpm
->dbp
|| !dpm
->dwp
) {
887 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
888 target_name(target
), dpm
->nbp
, dpm
->nwp
);
890 /* REVISIT ... and some of those breakpoints could match
891 * execution context IDs...
898 * Reinitializes DPM state at the beginning of a new debug session
899 * or after a reset which may have affected the debug module.
901 int arm_dpm_initialize(struct arm_dpm
*dpm
)
903 /* Disable all breakpoints and watchpoints at startup. */
904 if (dpm
->bpwp_disable
) {
907 for (i
= 0; i
< dpm
->nbp
; i
++) {
908 dpm
->dbp
[i
].bpwp
.number
= i
;
909 (void) dpm
->bpwp_disable(dpm
, i
);
911 for (i
= 0; i
< dpm
->nwp
; i
++) {
912 dpm
->dwp
[i
].bpwp
.number
= 16 + i
;
913 (void) dpm
->bpwp_disable(dpm
, 16 + i
);
916 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
917 target_name(dpm
->arm
->target
));
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)