1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2006 by Magnus Lundin *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
27 * Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0) *
29 ***************************************************************************/
34 #include "breakpoints.h"
35 #include "cortex_m3.h"
36 #include "target_request.h"
37 #include "target_type.h"
38 #include "arm_disassembler.h"
40 #include "arm_opcodes.h"
41 #include "arm_semihosting.h"
43 /* NOTE: most of this should work fine for the Cortex-M1 and
44 * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
45 * Some differences: M0/M1 doesn't have FBP remapping or the
46 * DWT tracing/profiling support. (So the cycle counter will
47 * not be usable; the other stuff isn't currently used here.)
49 * Although there are some workarounds for errata seen only in r0p0
50 * silicon, such old parts are hard to find and thus not much tested
55 /* forward declarations */
56 static int cortex_m3_set_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
);
57 static int cortex_m3_unset_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
);
58 static void cortex_m3_enable_watchpoints(struct target
*target
);
59 static int cortex_m3_store_core_reg_u32(struct target
*target
,
60 enum armv7m_regtype type
, uint32_t num
, uint32_t value
);
62 static int cortexm3_dap_read_coreregister_u32(struct swjdp_common
*swjdp
,
63 uint32_t *value
, int regnum
)
68 /* because the DCB_DCRDR is used for the emulated dcc channel
69 * we have to save/restore the DCB_DCRDR when used */
71 mem_ap_read_u32(swjdp
, DCB_DCRDR
, &dcrdr
);
73 /* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */
74 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRSR
& 0xFFFFFFF0);
75 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRSR
& 0xC), regnum
);
77 /* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */
78 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRDR
& 0xFFFFFFF0);
79 dap_ap_read_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRDR
& 0xC), value
);
81 retval
= jtagdp_transaction_endcheck(swjdp
);
83 /* restore DCB_DCRDR - this needs to be in a seperate
84 * transaction otherwise the emulated DCC channel breaks */
85 if (retval
== ERROR_OK
)
86 retval
= mem_ap_write_atomic_u32(swjdp
, DCB_DCRDR
, dcrdr
);
91 static int cortexm3_dap_write_coreregister_u32(struct swjdp_common
*swjdp
,
92 uint32_t value
, int regnum
)
97 /* because the DCB_DCRDR is used for the emulated dcc channel
98 * we have to save/restore the DCB_DCRDR when used */
100 mem_ap_read_u32(swjdp
, DCB_DCRDR
, &dcrdr
);
102 /* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */
103 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRDR
& 0xFFFFFFF0);
104 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRDR
& 0xC), value
);
106 /* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */
107 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRSR
& 0xFFFFFFF0);
108 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRSR
& 0xC), regnum
| DCRSR_WnR
);
110 retval
= jtagdp_transaction_endcheck(swjdp
);
112 /* restore DCB_DCRDR - this needs to be in a seperate
113 * transaction otherwise the emulated DCC channel breaks */
114 if (retval
== ERROR_OK
)
115 retval
= mem_ap_write_atomic_u32(swjdp
, DCB_DCRDR
, dcrdr
);
120 static int cortex_m3_write_debug_halt_mask(struct target
*target
,
121 uint32_t mask_on
, uint32_t mask_off
)
123 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
124 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
126 /* mask off status bits */
127 cortex_m3
->dcb_dhcsr
&= ~((0xFFFF << 16) | mask_off
);
128 /* create new register mask */
129 cortex_m3
->dcb_dhcsr
|= DBGKEY
| C_DEBUGEN
| mask_on
;
131 return mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
, cortex_m3
->dcb_dhcsr
);
134 static int cortex_m3_clear_halt(struct target
*target
)
136 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
137 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
139 /* clear step if any */
140 cortex_m3_write_debug_halt_mask(target
, C_HALT
, C_STEP
);
142 /* Read Debug Fault Status Register */
143 mem_ap_read_atomic_u32(swjdp
, NVIC_DFSR
, &cortex_m3
->nvic_dfsr
);
145 /* Clear Debug Fault Status */
146 mem_ap_write_atomic_u32(swjdp
, NVIC_DFSR
, cortex_m3
->nvic_dfsr
);
147 LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32
"", cortex_m3
->nvic_dfsr
);
152 static int cortex_m3_single_step_core(struct target
*target
)
154 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
155 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
158 /* backup dhcsr reg */
159 dhcsr_save
= cortex_m3
->dcb_dhcsr
;
161 /* Mask interrupts before clearing halt, if done already. This avoids
162 * Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
163 * HALT can put the core into an unknown state.
165 if (!(cortex_m3
->dcb_dhcsr
& C_MASKINTS
))
166 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
,
167 DBGKEY
| C_MASKINTS
| C_HALT
| C_DEBUGEN
);
168 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
,
169 DBGKEY
| C_MASKINTS
| C_STEP
| C_DEBUGEN
);
172 /* restore dhcsr reg */
173 cortex_m3
->dcb_dhcsr
= dhcsr_save
;
174 cortex_m3_clear_halt(target
);
179 static int cortex_m3_endreset_event(struct target
*target
)
183 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
184 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
185 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
186 struct cortex_m3_fp_comparator
*fp_list
= cortex_m3
->fp_comparator_list
;
187 struct cortex_m3_dwt_comparator
*dwt_list
= cortex_m3
->dwt_comparator_list
;
189 /* REVISIT The four debug monitor bits are currently ignored... */
190 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &dcb_demcr
);
191 LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32
"",dcb_demcr
);
193 /* this register is used for emulated dcc channel */
194 mem_ap_write_u32(swjdp
, DCB_DCRDR
, 0);
196 /* Enable debug requests */
197 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
198 if (!(cortex_m3
->dcb_dhcsr
& C_DEBUGEN
))
199 mem_ap_write_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_DEBUGEN
);
201 /* clear any interrupt masking */
202 cortex_m3_write_debug_halt_mask(target
, 0, C_MASKINTS
);
204 /* Enable features controlled by ITM and DWT blocks, and catch only
205 * the vectors we were told to pay attention to.
207 * Target firmware is responsible for all fault handling policy
208 * choices *EXCEPT* explicitly scripted overrides like "vector_catch"
209 * or manual updates to the NVIC SHCSR and CCR registers.
211 mem_ap_write_u32(swjdp
, DCB_DEMCR
, TRCENA
| armv7m
->demcr
);
213 /* Paranoia: evidently some (early?) chips don't preserve all the
214 * debug state (including FBP, DWT, etc) across reset...
218 target_write_u32(target
, FP_CTRL
, 3);
219 cortex_m3
->fpb_enabled
= 1;
221 /* Restore FPB registers */
222 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++)
224 target_write_u32(target
, fp_list
[i
].fpcr_address
, fp_list
[i
].fpcr_value
);
227 /* Restore DWT registers */
228 for (i
= 0; i
< cortex_m3
->dwt_num_comp
; i
++)
230 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 0,
232 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 4,
234 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 8,
235 dwt_list
[i
].function
);
237 jtagdp_transaction_endcheck(swjdp
);
239 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
241 /* make sure we have latest dhcsr flags */
242 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
247 static int cortex_m3_examine_debug_reason(struct target
*target
)
249 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
251 /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
252 /* only check the debug reason if we don't know it already */
254 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
255 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
))
257 if (cortex_m3
->nvic_dfsr
& DFSR_BKPT
)
259 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
260 if (cortex_m3
->nvic_dfsr
& DFSR_DWTTRAP
)
261 target
->debug_reason
= DBG_REASON_WPTANDBKPT
;
263 else if (cortex_m3
->nvic_dfsr
& DFSR_DWTTRAP
)
264 target
->debug_reason
= DBG_REASON_WATCHPOINT
;
265 else if (cortex_m3
->nvic_dfsr
& DFSR_VCATCH
)
266 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
267 else /* EXTERNAL, HALTED */
268 target
->debug_reason
= DBG_REASON_UNDEFINED
;
274 static int cortex_m3_examine_exception_reason(struct target
*target
)
276 uint32_t shcsr
, except_sr
, cfsr
= -1, except_ar
= -1;
277 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
278 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
280 mem_ap_read_u32(swjdp
, NVIC_SHCSR
, &shcsr
);
281 switch (armv7m
->exception_number
)
285 case 3: /* Hard Fault */
286 mem_ap_read_atomic_u32(swjdp
, NVIC_HFSR
, &except_sr
);
287 if (except_sr
& 0x40000000)
289 mem_ap_read_u32(swjdp
, NVIC_CFSR
, &cfsr
);
292 case 4: /* Memory Management */
293 mem_ap_read_u32(swjdp
, NVIC_CFSR
, &except_sr
);
294 mem_ap_read_u32(swjdp
, NVIC_MMFAR
, &except_ar
);
296 case 5: /* Bus Fault */
297 mem_ap_read_u32(swjdp
, NVIC_CFSR
, &except_sr
);
298 mem_ap_read_u32(swjdp
, NVIC_BFAR
, &except_ar
);
300 case 6: /* Usage Fault */
301 mem_ap_read_u32(swjdp
, NVIC_CFSR
, &except_sr
);
303 case 11: /* SVCall */
305 case 12: /* Debug Monitor */
306 mem_ap_read_u32(swjdp
, NVIC_DFSR
, &except_sr
);
308 case 14: /* PendSV */
310 case 15: /* SysTick */
316 jtagdp_transaction_endcheck(swjdp
);
317 LOG_DEBUG("%s SHCSR 0x%" PRIx32
", SR 0x%" PRIx32
", CFSR 0x%" PRIx32
", AR 0x%" PRIx32
"", armv7m_exception_string(armv7m
->exception_number
), \
318 shcsr
, except_sr
, cfsr
, except_ar
);
322 /* PSP is used in some thread modes */
323 static const int armv7m_psp_reg_map
[17] = {
324 ARMV7M_R0
, ARMV7M_R1
, ARMV7M_R2
, ARMV7M_R3
,
325 ARMV7M_R4
, ARMV7M_R5
, ARMV7M_R6
, ARMV7M_R7
,
326 ARMV7M_R8
, ARMV7M_R9
, ARMV7M_R10
, ARMV7M_R11
,
327 ARMV7M_R12
, ARMV7M_PSP
, ARMV7M_R14
, ARMV7M_PC
,
331 /* MSP is used in handler and some thread modes */
332 static const int armv7m_msp_reg_map
[17] = {
333 ARMV7M_R0
, ARMV7M_R1
, ARMV7M_R2
, ARMV7M_R3
,
334 ARMV7M_R4
, ARMV7M_R5
, ARMV7M_R6
, ARMV7M_R7
,
335 ARMV7M_R8
, ARMV7M_R9
, ARMV7M_R10
, ARMV7M_R11
,
336 ARMV7M_R12
, ARMV7M_MSP
, ARMV7M_R14
, ARMV7M_PC
,
340 static int cortex_m3_debug_entry(struct target
*target
)
345 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
346 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
347 struct arm
*arm
= &armv7m
->arm
;
348 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
353 cortex_m3_clear_halt(target
);
354 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
356 if ((retval
= armv7m
->examine_debug_reason(target
)) != ERROR_OK
)
359 /* Examine target state and mode */
360 /* First load register acessible through core debug port*/
361 int num_regs
= armv7m
->core_cache
->num_regs
;
363 for (i
= 0; i
< num_regs
; i
++)
365 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
366 armv7m
->read_core_reg(target
, i
);
369 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
370 xPSR
= buf_get_u32(r
->value
, 0, 32);
372 #ifdef ARMV7_GDB_HACKS
373 /* FIXME this breaks on scan chains with more than one Cortex-M3.
374 * Instead, each CM3 should have its own dummy value...
376 /* copy real xpsr reg for gdb, setting thumb bit */
377 buf_set_u32(armv7m_gdb_dummy_cpsr_value
, 0, 32, xPSR
);
378 buf_set_u32(armv7m_gdb_dummy_cpsr_value
, 5, 1, 1);
379 armv7m_gdb_dummy_cpsr_reg
.valid
= r
->valid
;
380 armv7m_gdb_dummy_cpsr_reg
.dirty
= r
->dirty
;
383 /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
387 cortex_m3_store_core_reg_u32(target
, ARMV7M_REGISTER_CORE_GP
, 16, xPSR
&~ 0xff);
390 /* Are we in an exception handler */
393 armv7m
->core_mode
= ARMV7M_MODE_HANDLER
;
394 armv7m
->exception_number
= (xPSR
& 0x1FF);
396 arm
->core_mode
= ARM_MODE_HANDLER
;
397 arm
->map
= armv7m_msp_reg_map
;
401 unsigned control
= buf_get_u32(armv7m
->core_cache
402 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 2);
404 /* is this thread privileged? */
405 armv7m
->core_mode
= control
& 1;
406 arm
->core_mode
= armv7m
->core_mode
407 ? ARM_MODE_USER_THREAD
410 /* which stack is it using? */
412 arm
->map
= armv7m_psp_reg_map
;
414 arm
->map
= armv7m_msp_reg_map
;
416 armv7m
->exception_number
= 0;
419 if (armv7m
->exception_number
)
421 cortex_m3_examine_exception_reason(target
);
424 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32
", target->state: %s",
425 armv7m_mode_strings
[armv7m
->core_mode
],
426 *(uint32_t*)(arm
->pc
->value
),
427 target_state_name(target
));
429 if (armv7m
->post_debug_entry
)
430 armv7m
->post_debug_entry(target
);
435 static int cortex_m3_poll(struct target
*target
)
438 enum target_state prev_target_state
= target
->state
;
439 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
440 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
442 /* Read from Debug Halting Control and Status Register */
443 retval
= mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
444 if (retval
!= ERROR_OK
)
446 target
->state
= TARGET_UNKNOWN
;
450 /* Recover from lockup. See ARMv7-M architecture spec,
451 * section B1.5.15 "Unrecoverable exception cases".
453 * REVISIT Is there a better way to report and handle this?
455 if (cortex_m3
->dcb_dhcsr
& S_LOCKUP
) {
456 LOG_WARNING("%s -- clearing lockup after double fault",
457 target_name(target
));
458 cortex_m3_write_debug_halt_mask(target
, C_HALT
, 0);
459 target
->debug_reason
= DBG_REASON_DBGRQ
;
461 /* refresh status bits */
462 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
465 if (cortex_m3
->dcb_dhcsr
& S_RESET_ST
)
467 /* check if still in reset */
468 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
470 if (cortex_m3
->dcb_dhcsr
& S_RESET_ST
)
472 target
->state
= TARGET_RESET
;
477 if (target
->state
== TARGET_RESET
)
479 /* Cannot switch context while running so endreset is
480 * called with target->state == TARGET_RESET
482 LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32
,
483 cortex_m3
->dcb_dhcsr
);
484 cortex_m3_endreset_event(target
);
485 target
->state
= TARGET_RUNNING
;
486 prev_target_state
= TARGET_RUNNING
;
489 if (cortex_m3
->dcb_dhcsr
& S_HALT
)
491 target
->state
= TARGET_HALTED
;
493 if ((prev_target_state
== TARGET_RUNNING
) || (prev_target_state
== TARGET_RESET
))
495 if ((retval
= cortex_m3_debug_entry(target
)) != ERROR_OK
)
498 if (arm_semihosting(target
, &retval
) != 0)
501 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
503 if (prev_target_state
== TARGET_DEBUG_RUNNING
)
506 if ((retval
= cortex_m3_debug_entry(target
)) != ERROR_OK
)
509 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
513 /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
514 * How best to model low power modes?
517 if (target
->state
== TARGET_UNKNOWN
)
519 /* check if processor is retiring instructions */
520 if (cortex_m3
->dcb_dhcsr
& S_RETIRE_ST
)
522 target
->state
= TARGET_RUNNING
;
530 static int cortex_m3_halt(struct target
*target
)
532 LOG_DEBUG("target->state: %s",
533 target_state_name(target
));
535 if (target
->state
== TARGET_HALTED
)
537 LOG_DEBUG("target was already halted");
541 if (target
->state
== TARGET_UNKNOWN
)
543 LOG_WARNING("target was in unknown state when halt was requested");
546 if (target
->state
== TARGET_RESET
)
548 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST
) && jtag_get_srst())
550 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
551 return ERROR_TARGET_FAILURE
;
555 /* we came here in a reset_halt or reset_init sequence
556 * debug entry was already prepared in cortex_m3_prepare_reset_halt()
558 target
->debug_reason
= DBG_REASON_DBGRQ
;
564 /* Write to Debug Halting Control and Status Register */
565 cortex_m3_write_debug_halt_mask(target
, C_HALT
, 0);
567 target
->debug_reason
= DBG_REASON_DBGRQ
;
572 static int cortex_m3_soft_reset_halt(struct target
*target
)
574 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
575 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
576 uint32_t dcb_dhcsr
= 0;
577 int retval
, timeout
= 0;
579 /* Enter debug state on reset; restore DEMCR in endreset_event() */
580 mem_ap_write_u32(swjdp
, DCB_DEMCR
,
581 TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
583 /* Request a core-only reset */
584 mem_ap_write_atomic_u32(swjdp
, NVIC_AIRCR
,
585 AIRCR_VECTKEY
| AIRCR_VECTRESET
);
586 target
->state
= TARGET_RESET
;
588 /* registers are now invalid */
589 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
591 while (timeout
< 100)
593 retval
= mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &dcb_dhcsr
);
594 if (retval
== ERROR_OK
)
596 mem_ap_read_atomic_u32(swjdp
, NVIC_DFSR
,
597 &cortex_m3
->nvic_dfsr
);
598 if ((dcb_dhcsr
& S_HALT
)
599 && (cortex_m3
->nvic_dfsr
& DFSR_VCATCH
))
601 LOG_DEBUG("system reset-halted, DHCSR 0x%08x, "
603 (unsigned) dcb_dhcsr
,
604 (unsigned) cortex_m3
->nvic_dfsr
);
605 cortex_m3_poll(target
);
606 /* FIXME restore user's vector catch config */
610 LOG_DEBUG("waiting for system reset-halt, "
611 "DHCSR 0x%08x, %d ms",
612 (unsigned) dcb_dhcsr
, timeout
);
621 static void cortex_m3_enable_breakpoints(struct target
*target
)
623 struct breakpoint
*breakpoint
= target
->breakpoints
;
625 /* set any pending breakpoints */
628 if (!breakpoint
->set
)
629 cortex_m3_set_breakpoint(target
, breakpoint
);
630 breakpoint
= breakpoint
->next
;
634 static int cortex_m3_resume(struct target
*target
, int current
,
635 uint32_t address
, int handle_breakpoints
, int debug_execution
)
637 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
638 struct breakpoint
*breakpoint
= NULL
;
642 if (target
->state
!= TARGET_HALTED
)
644 LOG_WARNING("target not halted");
645 return ERROR_TARGET_NOT_HALTED
;
648 if (!debug_execution
)
650 target_free_all_working_areas(target
);
651 cortex_m3_enable_breakpoints(target
);
652 cortex_m3_enable_watchpoints(target
);
657 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_PRIMASK
;
659 /* Disable interrupts */
660 /* We disable interrupts in the PRIMASK register instead of
661 * masking with C_MASKINTS. This is probably the same issue
662 * as Cortex-M3 Erratum 377493 (fixed in r1p0): C_MASKINTS
663 * in parallel with disabled interrupts can cause local faults
666 * REVISIT this clearly breaks non-debug execution, since the
667 * PRIMASK register state isn't saved/restored... workaround
668 * by never resuming app code after debug execution.
670 buf_set_u32(r
->value
, 0, 1, 1);
674 /* Make sure we are in Thumb mode */
675 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
676 buf_set_u32(r
->value
, 24, 1, 1);
681 /* current = 1: continue on current pc, otherwise continue at <address> */
685 buf_set_u32(r
->value
, 0, 32, address
);
690 /* if we halted last time due to a bkpt instruction
691 * then we have to manually step over it, otherwise
692 * the core will break again */
694 if (!breakpoint_find(target
, buf_get_u32(r
->value
, 0, 32))
697 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
700 resume_pc
= buf_get_u32(r
->value
, 0, 32);
702 armv7m_restore_context(target
);
704 /* the front-end may request us not to handle breakpoints */
705 if (handle_breakpoints
)
707 /* Single step past breakpoint at current address */
708 if ((breakpoint
= breakpoint_find(target
, resume_pc
)))
710 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
712 breakpoint
->unique_id
);
713 cortex_m3_unset_breakpoint(target
, breakpoint
);
714 cortex_m3_single_step_core(target
);
715 cortex_m3_set_breakpoint(target
, breakpoint
);
720 cortex_m3_write_debug_halt_mask(target
, 0, C_HALT
);
722 target
->debug_reason
= DBG_REASON_NOTHALTED
;
724 /* registers are now invalid */
725 register_cache_invalidate(armv7m
->core_cache
);
727 if (!debug_execution
)
729 target
->state
= TARGET_RUNNING
;
730 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
731 LOG_DEBUG("target resumed at 0x%" PRIx32
"", resume_pc
);
735 target
->state
= TARGET_DEBUG_RUNNING
;
736 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
737 LOG_DEBUG("target debug resumed at 0x%" PRIx32
"", resume_pc
);
743 /* int irqstepcount = 0; */
744 static int cortex_m3_step(struct target
*target
, int current
,
745 uint32_t address
, int handle_breakpoints
)
747 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
748 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
749 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
750 struct breakpoint
*breakpoint
= NULL
;
751 struct reg
*pc
= armv7m
->arm
.pc
;
752 bool bkpt_inst_found
= false;
754 if (target
->state
!= TARGET_HALTED
)
756 LOG_WARNING("target not halted");
757 return ERROR_TARGET_NOT_HALTED
;
760 /* current = 1: continue on current pc, otherwise continue at <address> */
762 buf_set_u32(pc
->value
, 0, 32, address
);
764 /* the front-end may request us not to handle breakpoints */
765 if (handle_breakpoints
) {
766 breakpoint
= breakpoint_find(target
,
767 buf_get_u32(pc
->value
, 0, 32));
769 cortex_m3_unset_breakpoint(target
, breakpoint
);
772 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
774 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
776 armv7m_restore_context(target
);
778 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
780 /* if no bkpt instruction is found at pc then we can perform
781 * a normal step, otherwise we have to manually step over the bkpt
782 * instruction - as such simulate a step */
783 if (bkpt_inst_found
== false)
785 /* set step and clear halt */
786 cortex_m3_write_debug_halt_mask(target
, C_STEP
, C_HALT
);
789 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
791 /* registers are now invalid */
792 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
795 cortex_m3_set_breakpoint(target
, breakpoint
);
797 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
798 " nvic_icsr = 0x%" PRIx32
,
799 cortex_m3
->dcb_dhcsr
, cortex_m3
->nvic_icsr
);
801 cortex_m3_debug_entry(target
);
802 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
804 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
805 " nvic_icsr = 0x%" PRIx32
,
806 cortex_m3
->dcb_dhcsr
, cortex_m3
->nvic_icsr
);
811 static int cortex_m3_assert_reset(struct target
*target
)
813 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
814 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
817 LOG_DEBUG("target->state: %s",
818 target_state_name(target
));
820 enum reset_types jtag_reset_config
= jtag_get_reset_config();
823 * We can reset Cortex-M3 targets using just the NVIC without
824 * requiring SRST, getting a SoC reset (or a core-only reset)
825 * instead of a system reset.
827 if (!(jtag_reset_config
& RESET_HAS_SRST
))
830 /* Enable debug requests */
831 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
832 if (!(cortex_m3
->dcb_dhcsr
& C_DEBUGEN
))
833 mem_ap_write_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_DEBUGEN
);
835 mem_ap_write_u32(swjdp
, DCB_DCRDR
, 0);
837 if (!target
->reset_halt
)
839 /* Set/Clear C_MASKINTS in a separate operation */
840 if (cortex_m3
->dcb_dhcsr
& C_MASKINTS
)
841 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
,
842 DBGKEY
| C_DEBUGEN
| C_HALT
);
844 /* clear any debug flags before resuming */
845 cortex_m3_clear_halt(target
);
847 /* clear C_HALT in dhcsr reg */
848 cortex_m3_write_debug_halt_mask(target
, 0, C_HALT
);
852 /* Halt in debug on reset; endreset_event() restores DEMCR.
854 * REVISIT catching BUSERR presumably helps to defend against
855 * bad vector table entries. Should this include MMERR or
858 mem_ap_write_atomic_u32(swjdp
, DCB_DEMCR
,
859 TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
863 * When nRST is asserted on most Stellaris devices, it clears some of
864 * the debug state. The ARMv7M and Cortex-M3 TRMs say that's wrong;
865 * and OpenOCD depends on those TRMs. So we won't use SRST on those
866 * chips. (Only power-on reset should affect debug state, beyond a
867 * few specified bits; not the chip's nRST input, wired to SRST.)
869 * REVISIT current errata specs don't seem to cover this issue.
870 * Do we have more details than this email?
871 * https://lists.berlios.de/pipermail
872 * /openocd-development/2008-August/003065.html
874 if (strcmp(target
->variant
, "lm3s") == 0)
876 /* Check for silicon revisions with the issue. */
879 if (target_read_u32(target
, 0x400fe000, &did0
) == ERROR_OK
)
881 switch ((did0
>> 16) & 0xff)
884 /* all Sandstorm suffer issue */
890 /* Fury and DustDevil rev A have
891 * this nRST problem. It should
892 * be fixed in rev B silicon.
894 if (((did0
>> 8) & 0xff) == 0)
898 /* Tempest should be fine. */
906 /* default to asserting srst */
907 if (jtag_reset_config
& RESET_SRST_PULLS_TRST
)
909 jtag_add_reset(1, 1);
913 jtag_add_reset(0, 1);
918 /* Use a standard Cortex-M3 software reset mechanism.
919 * SYSRESETREQ will reset SoC peripherals outside the
920 * core, like watchdog timers, if the SoC wires it up
921 * correctly. Else VECRESET can reset just the core.
923 mem_ap_write_atomic_u32(swjdp
, NVIC_AIRCR
,
924 AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
925 LOG_DEBUG("Using Cortex-M3 SYSRESETREQ");
928 /* I do not know why this is necessary, but it
929 * fixes strange effects (step/resume cause NMI
930 * after reset) on LM3S6918 -- Michael Schwingen
933 mem_ap_read_atomic_u32(swjdp
, NVIC_AIRCR
, &tmp
);
937 target
->state
= TARGET_RESET
;
938 jtag_add_sleep(50000);
940 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
942 if (target
->reset_halt
)
945 if ((retval
= target_halt(target
)) != ERROR_OK
)
952 static int cortex_m3_deassert_reset(struct target
*target
)
954 LOG_DEBUG("target->state: %s",
955 target_state_name(target
));
957 /* deassert reset lines */
958 jtag_add_reset(0, 0);
964 cortex_m3_set_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
969 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
970 struct cortex_m3_fp_comparator
*comparator_list
= cortex_m3
->fp_comparator_list
;
974 LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint
->unique_id
);
978 if (cortex_m3
->auto_bp_type
)
980 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
983 if (breakpoint
->type
== BKPT_HARD
)
985 while (comparator_list
[fp_num
].used
&& (fp_num
< cortex_m3
->fp_num_code
))
987 if (fp_num
>= cortex_m3
->fp_num_code
)
989 LOG_ERROR("Can not find free FPB Comparator!");
992 breakpoint
->set
= fp_num
+ 1;
993 hilo
= (breakpoint
->address
& 0x2) ? FPCR_REPLACE_BKPT_HIGH
: FPCR_REPLACE_BKPT_LOW
;
994 comparator_list
[fp_num
].used
= 1;
995 comparator_list
[fp_num
].fpcr_value
= (breakpoint
->address
& 0x1FFFFFFC) | hilo
| 1;
996 target_write_u32(target
, comparator_list
[fp_num
].fpcr_address
, comparator_list
[fp_num
].fpcr_value
);
997 LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32
"", fp_num
, comparator_list
[fp_num
].fpcr_value
);
998 if (!cortex_m3
->fpb_enabled
)
1000 LOG_DEBUG("FPB wasn't enabled, do it now");
1001 target_write_u32(target
, FP_CTRL
, 3);
1004 else if (breakpoint
->type
== BKPT_SOFT
)
1008 /* NOTE: on ARMv6-M and ARMv7-M, BKPT(0xab) is used for
1009 * semihosting; don't use that. Otherwise the BKPT
1010 * parameter is arbitrary.
1012 buf_set_u32(code
, 0, 32, ARMV5_T_BKPT(0x11));
1013 retval
= target_read_memory(target
,
1014 breakpoint
->address
& 0xFFFFFFFE,
1015 breakpoint
->length
, 1,
1016 breakpoint
->orig_instr
);
1017 if (retval
!= ERROR_OK
)
1019 retval
= target_write_memory(target
,
1020 breakpoint
->address
& 0xFFFFFFFE,
1021 breakpoint
->length
, 1,
1023 if (retval
!= ERROR_OK
)
1025 breakpoint
->set
= true;
1028 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32
" Length: %d (set=%d)",
1029 breakpoint
->unique_id
,
1030 (int)(breakpoint
->type
),
1031 breakpoint
->address
,
1039 cortex_m3_unset_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1042 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1043 struct cortex_m3_fp_comparator
* comparator_list
= cortex_m3
->fp_comparator_list
;
1045 if (!breakpoint
->set
)
1047 LOG_WARNING("breakpoint not set");
1051 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32
" Length: %d (set=%d)",
1052 breakpoint
->unique_id
,
1053 (int)(breakpoint
->type
),
1054 breakpoint
->address
,
1058 if (breakpoint
->type
== BKPT_HARD
)
1060 int fp_num
= breakpoint
->set
- 1;
1061 if ((fp_num
< 0) || (fp_num
>= cortex_m3
->fp_num_code
))
1063 LOG_DEBUG("Invalid FP Comparator number in breakpoint");
1066 comparator_list
[fp_num
].used
= 0;
1067 comparator_list
[fp_num
].fpcr_value
= 0;
1068 target_write_u32(target
, comparator_list
[fp_num
].fpcr_address
, comparator_list
[fp_num
].fpcr_value
);
1072 /* restore original instruction (kept in target endianness) */
1073 if (breakpoint
->length
== 4)
1075 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, 4, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
1082 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, 2, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
1088 breakpoint
->set
= false;
1094 cortex_m3_add_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1096 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1098 if (cortex_m3
->auto_bp_type
)
1100 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
1101 #ifdef ARMV7_GDB_HACKS
1102 if (breakpoint
->length
!= 2) {
1103 /* XXX Hack: Replace all breakpoints with length != 2 with
1104 * a hardware breakpoint. */
1105 breakpoint
->type
= BKPT_HARD
;
1106 breakpoint
->length
= 2;
1111 if ((breakpoint
->type
== BKPT_HARD
) && (breakpoint
->address
>= 0x20000000))
1113 LOG_INFO("flash patch comparator requested outside code memory region");
1114 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1117 if ((breakpoint
->type
== BKPT_SOFT
) && (breakpoint
->address
< 0x20000000))
1119 LOG_INFO("soft breakpoint requested in code (flash) memory region");
1120 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1123 if ((breakpoint
->type
== BKPT_HARD
) && (cortex_m3
->fp_code_available
< 1))
1125 LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
1126 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1129 if ((breakpoint
->length
!= 2))
1131 LOG_INFO("only breakpoints of two bytes length supported");
1132 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1135 if (breakpoint
->type
== BKPT_HARD
)
1136 cortex_m3
->fp_code_available
--;
1137 cortex_m3_set_breakpoint(target
, breakpoint
);
1143 cortex_m3_remove_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1145 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1147 /* REVISIT why check? FBP can be updated with core running ... */
1148 if (target
->state
!= TARGET_HALTED
)
1150 LOG_WARNING("target not halted");
1151 return ERROR_TARGET_NOT_HALTED
;
1154 if (cortex_m3
->auto_bp_type
)
1156 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
1159 if (breakpoint
->set
)
1161 cortex_m3_unset_breakpoint(target
, breakpoint
);
1164 if (breakpoint
->type
== BKPT_HARD
)
1165 cortex_m3
->fp_code_available
++;
1171 cortex_m3_set_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1174 uint32_t mask
, temp
;
1175 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1177 /* watchpoint params were validated earlier */
1179 temp
= watchpoint
->length
;
1186 /* REVISIT Don't fully trust these "not used" records ... users
1187 * may set up breakpoints by hand, e.g. dual-address data value
1188 * watchpoint using comparator #1; comparator #0 matching cycle
1189 * count; send data trace info through ITM and TPIU; etc
1191 struct cortex_m3_dwt_comparator
*comparator
;
1193 for (comparator
= cortex_m3
->dwt_comparator_list
;
1194 comparator
->used
&& dwt_num
< cortex_m3
->dwt_num_comp
;
1195 comparator
++, dwt_num
++)
1197 if (dwt_num
>= cortex_m3
->dwt_num_comp
)
1199 LOG_ERROR("Can not find free DWT Comparator");
1202 comparator
->used
= 1;
1203 watchpoint
->set
= dwt_num
+ 1;
1205 comparator
->comp
= watchpoint
->address
;
1206 target_write_u32(target
, comparator
->dwt_comparator_address
+ 0,
1209 comparator
->mask
= mask
;
1210 target_write_u32(target
, comparator
->dwt_comparator_address
+ 4,
1213 switch (watchpoint
->rw
) {
1215 comparator
->function
= 5;
1218 comparator
->function
= 6;
1221 comparator
->function
= 7;
1224 target_write_u32(target
, comparator
->dwt_comparator_address
+ 8,
1225 comparator
->function
);
1227 LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x",
1228 watchpoint
->unique_id
, dwt_num
,
1229 (unsigned) comparator
->comp
,
1230 (unsigned) comparator
->mask
,
1231 (unsigned) comparator
->function
);
1236 cortex_m3_unset_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1238 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1239 struct cortex_m3_dwt_comparator
*comparator
;
1242 if (!watchpoint
->set
)
1244 LOG_WARNING("watchpoint (wpid: %d) not set",
1245 watchpoint
->unique_id
);
1249 dwt_num
= watchpoint
->set
- 1;
1251 LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
1252 watchpoint
->unique_id
, dwt_num
,
1253 (unsigned) watchpoint
->address
);
1255 if ((dwt_num
< 0) || (dwt_num
>= cortex_m3
->dwt_num_comp
))
1257 LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
1261 comparator
= cortex_m3
->dwt_comparator_list
+ dwt_num
;
1262 comparator
->used
= 0;
1263 comparator
->function
= 0;
1264 target_write_u32(target
, comparator
->dwt_comparator_address
+ 8,
1265 comparator
->function
);
1267 watchpoint
->set
= false;
1273 cortex_m3_add_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1275 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1277 if (cortex_m3
->dwt_comp_available
< 1)
1279 LOG_DEBUG("no comparators?");
1280 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1283 /* hardware doesn't support data value masking */
1284 if (watchpoint
->mask
!= ~(uint32_t)0) {
1285 LOG_DEBUG("watchpoint value masks not supported");
1286 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1289 /* hardware allows address masks of up to 32K */
1292 for (mask
= 0; mask
< 16; mask
++) {
1293 if ((1u << mask
) == watchpoint
->length
)
1297 LOG_DEBUG("unsupported watchpoint length");
1298 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1300 if (watchpoint
->address
& ((1 << mask
) - 1)) {
1301 LOG_DEBUG("watchpoint address is unaligned");
1302 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1305 /* Caller doesn't seem to be able to describe watching for data
1306 * values of zero; that flags "no value".
1308 * REVISIT This DWT may well be able to watch for specific data
1309 * values. Requires comparator #1 to set DATAVMATCH and match
1310 * the data, and another comparator (DATAVADDR0) matching addr.
1312 if (watchpoint
->value
) {
1313 LOG_DEBUG("data value watchpoint not YET supported");
1314 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1317 cortex_m3
->dwt_comp_available
--;
1318 LOG_DEBUG("dwt_comp_available: %d", cortex_m3
->dwt_comp_available
);
1324 cortex_m3_remove_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1326 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1328 /* REVISIT why check? DWT can be updated with core running ... */
1329 if (target
->state
!= TARGET_HALTED
)
1331 LOG_WARNING("target not halted");
1332 return ERROR_TARGET_NOT_HALTED
;
1335 if (watchpoint
->set
)
1337 cortex_m3_unset_watchpoint(target
, watchpoint
);
1340 cortex_m3
->dwt_comp_available
++;
1341 LOG_DEBUG("dwt_comp_available: %d", cortex_m3
->dwt_comp_available
);
1346 static void cortex_m3_enable_watchpoints(struct target
*target
)
1348 struct watchpoint
*watchpoint
= target
->watchpoints
;
1350 /* set any pending watchpoints */
1353 if (!watchpoint
->set
)
1354 cortex_m3_set_watchpoint(target
, watchpoint
);
1355 watchpoint
= watchpoint
->next
;
1359 static int cortex_m3_load_core_reg_u32(struct target
*target
,
1360 enum armv7m_regtype type
, uint32_t num
, uint32_t * value
)
1363 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1364 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1366 /* NOTE: we "know" here that the register identifiers used
1367 * in the v7m header match the Cortex-M3 Debug Core Register
1368 * Selector values for R0..R15, xPSR, MSP, and PSP.
1372 /* read a normal core register */
1373 retval
= cortexm3_dap_read_coreregister_u32(swjdp
, value
, num
);
1375 if (retval
!= ERROR_OK
)
1377 LOG_ERROR("JTAG failure %i",retval
);
1378 return ERROR_JTAG_DEVICE_ERROR
;
1380 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"",(int)num
,*value
);
1383 case ARMV7M_PRIMASK
:
1384 case ARMV7M_BASEPRI
:
1385 case ARMV7M_FAULTMASK
:
1386 case ARMV7M_CONTROL
:
1387 /* Cortex-M3 packages these four registers as bitfields
1388 * in one Debug Core register. So say r0 and r2 docs;
1389 * it was removed from r1 docs, but still works.
1391 cortexm3_dap_read_coreregister_u32(swjdp
, value
, 20);
1395 case ARMV7M_PRIMASK
:
1396 *value
= buf_get_u32((uint8_t*)value
, 0, 1);
1399 case ARMV7M_BASEPRI
:
1400 *value
= buf_get_u32((uint8_t*)value
, 8, 8);
1403 case ARMV7M_FAULTMASK
:
1404 *value
= buf_get_u32((uint8_t*)value
, 16, 1);
1407 case ARMV7M_CONTROL
:
1408 *value
= buf_get_u32((uint8_t*)value
, 24, 2);
1412 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"", (int)num
, *value
);
1416 return ERROR_INVALID_ARGUMENTS
;
1422 static int cortex_m3_store_core_reg_u32(struct target
*target
,
1423 enum armv7m_regtype type
, uint32_t num
, uint32_t value
)
1427 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1428 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1430 #ifdef ARMV7_GDB_HACKS
1431 /* If the LR register is being modified, make sure it will put us
1432 * in "thumb" mode, or an INVSTATE exception will occur. This is a
1433 * hack to deal with the fact that gdb will sometimes "forge"
1434 * return addresses, and doesn't set the LSB correctly (i.e., when
1435 * printing expressions containing function calls, it sets LR = 0.)
1436 * Valid exception return codes have bit 0 set too.
1438 if (num
== ARMV7M_R14
)
1442 /* NOTE: we "know" here that the register identifiers used
1443 * in the v7m header match the Cortex-M3 Debug Core Register
1444 * Selector values for R0..R15, xPSR, MSP, and PSP.
1448 retval
= cortexm3_dap_write_coreregister_u32(swjdp
, value
, num
);
1449 if (retval
!= ERROR_OK
)
1453 LOG_ERROR("JTAG failure %i", retval
);
1454 r
= armv7m
->core_cache
->reg_list
+ num
;
1455 r
->dirty
= r
->valid
;
1456 return ERROR_JTAG_DEVICE_ERROR
;
1458 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
1461 case ARMV7M_PRIMASK
:
1462 case ARMV7M_BASEPRI
:
1463 case ARMV7M_FAULTMASK
:
1464 case ARMV7M_CONTROL
:
1465 /* Cortex-M3 packages these four registers as bitfields
1466 * in one Debug Core register. So say r0 and r2 docs;
1467 * it was removed from r1 docs, but still works.
1469 cortexm3_dap_read_coreregister_u32(swjdp
, ®
, 20);
1473 case ARMV7M_PRIMASK
:
1474 buf_set_u32((uint8_t*)®
, 0, 1, value
);
1477 case ARMV7M_BASEPRI
:
1478 buf_set_u32((uint8_t*)®
, 8, 8, value
);
1481 case ARMV7M_FAULTMASK
:
1482 buf_set_u32((uint8_t*)®
, 16, 1, value
);
1485 case ARMV7M_CONTROL
:
1486 buf_set_u32((uint8_t*)®
, 24, 2, value
);
1490 cortexm3_dap_write_coreregister_u32(swjdp
, reg
, 20);
1492 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
1496 return ERROR_INVALID_ARGUMENTS
;
1502 static int cortex_m3_read_memory(struct target
*target
, uint32_t address
,
1503 uint32_t size
, uint32_t count
, uint8_t *buffer
)
1505 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1506 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1507 int retval
= ERROR_INVALID_ARGUMENTS
;
1509 /* cortex_m3 handles unaligned memory access */
1510 if (count
&& buffer
) {
1513 retval
= mem_ap_read_buf_u32(swjdp
, buffer
, 4 * count
, address
);
1516 retval
= mem_ap_read_buf_u16(swjdp
, buffer
, 2 * count
, address
);
1519 retval
= mem_ap_read_buf_u8(swjdp
, buffer
, count
, address
);
1527 static int cortex_m3_write_memory(struct target
*target
, uint32_t address
,
1528 uint32_t size
, uint32_t count
, uint8_t *buffer
)
1530 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1531 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1532 int retval
= ERROR_INVALID_ARGUMENTS
;
1534 if (count
&& buffer
) {
1537 retval
= mem_ap_write_buf_u32(swjdp
, buffer
, 4 * count
, address
);
1540 retval
= mem_ap_write_buf_u16(swjdp
, buffer
, 2 * count
, address
);
1543 retval
= mem_ap_write_buf_u8(swjdp
, buffer
, count
, address
);
1551 static int cortex_m3_bulk_write_memory(struct target
*target
, uint32_t address
,
1552 uint32_t count
, uint8_t *buffer
)
1554 return cortex_m3_write_memory(target
, address
, 4, count
, buffer
);
1557 static int cortex_m3_init_target(struct command_context
*cmd_ctx
,
1558 struct target
*target
)
1560 armv7m_build_reg_cache(target
);
1564 /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid"
1565 * on r/w if the core is not running, and clear on resume or reset ... or
1566 * at least, in a post_restore_context() method.
1569 struct dwt_reg_state
{
1570 struct target
*target
;
1572 uint32_t value
; /* scratch/cache */
1575 static int cortex_m3_dwt_get_reg(struct reg
*reg
)
1577 struct dwt_reg_state
*state
= reg
->arch_info
;
1579 return target_read_u32(state
->target
, state
->addr
, &state
->value
);
1582 static int cortex_m3_dwt_set_reg(struct reg
*reg
, uint8_t *buf
)
1584 struct dwt_reg_state
*state
= reg
->arch_info
;
1586 return target_write_u32(state
->target
, state
->addr
,
1587 buf_get_u32(buf
, 0, reg
->size
));
1596 static struct dwt_reg dwt_base_regs
[] = {
1597 { DWT_CTRL
, "dwt_ctrl", 32, },
1598 /* NOTE that Erratum 532314 (fixed r2p0) affects CYCCNT: it wrongly
1599 * increments while the core is asleep.
1601 { DWT_CYCCNT
, "dwt_cyccnt", 32, },
1602 /* plus some 8 bit counters, useful for profiling with TPIU */
1605 static struct dwt_reg dwt_comp
[] = {
1606 #define DWT_COMPARATOR(i) \
1607 { DWT_COMP0 + 0x10 * (i), "dwt_" #i "_comp", 32, }, \
1608 { DWT_MASK0 + 0x10 * (i), "dwt_" #i "_mask", 4, }, \
1609 { DWT_FUNCTION0 + 0x10 * (i), "dwt_" #i "_function", 32, }
1614 #undef DWT_COMPARATOR
1617 static const struct reg_arch_type dwt_reg_type
= {
1618 .get
= cortex_m3_dwt_get_reg
,
1619 .set
= cortex_m3_dwt_set_reg
,
1623 cortex_m3_dwt_addreg(struct target
*t
, struct reg
*r
, struct dwt_reg
*d
)
1625 struct dwt_reg_state
*state
;
1627 state
= calloc(1, sizeof *state
);
1630 state
->addr
= d
->addr
;
1635 r
->value
= &state
->value
;
1636 r
->arch_info
= state
;
1637 r
->type
= &dwt_reg_type
;
1641 cortex_m3_dwt_setup(struct cortex_m3_common
*cm3
, struct target
*target
)
1644 struct reg_cache
*cache
;
1645 struct cortex_m3_dwt_comparator
*comparator
;
1648 target_read_u32(target
, DWT_CTRL
, &dwtcr
);
1650 LOG_DEBUG("no DWT");
1654 cm3
->dwt_num_comp
= (dwtcr
>> 28) & 0xF;
1655 cm3
->dwt_comp_available
= cm3
->dwt_num_comp
;
1656 cm3
->dwt_comparator_list
= calloc(cm3
->dwt_num_comp
,
1657 sizeof(struct cortex_m3_dwt_comparator
));
1658 if (!cm3
->dwt_comparator_list
) {
1660 cm3
->dwt_num_comp
= 0;
1661 LOG_ERROR("out of mem");
1665 cache
= calloc(1, sizeof *cache
);
1668 free(cm3
->dwt_comparator_list
);
1671 cache
->name
= "cortex-m3 dwt registers";
1672 cache
->num_regs
= 2 + cm3
->dwt_num_comp
* 3;
1673 cache
->reg_list
= calloc(cache
->num_regs
, sizeof *cache
->reg_list
);
1674 if (!cache
->reg_list
) {
1679 for (reg
= 0; reg
< 2; reg
++)
1680 cortex_m3_dwt_addreg(target
, cache
->reg_list
+ reg
,
1681 dwt_base_regs
+ reg
);
1683 comparator
= cm3
->dwt_comparator_list
;
1684 for (i
= 0; i
< cm3
->dwt_num_comp
; i
++, comparator
++) {
1687 comparator
->dwt_comparator_address
= DWT_COMP0
+ 0x10 * i
;
1688 for (j
= 0; j
< 3; j
++, reg
++)
1689 cortex_m3_dwt_addreg(target
, cache
->reg_list
+ reg
,
1690 dwt_comp
+ 3 * i
+ j
);
1693 *register_get_last_cache_p(&target
->reg_cache
) = cache
;
1694 cm3
->dwt_cache
= cache
;
1696 LOG_DEBUG("DWT dwtcr 0x%" PRIx32
", comp %d, watch%s",
1697 dwtcr
, cm3
->dwt_num_comp
,
1698 (dwtcr
& (0xf << 24)) ? " only" : "/trigger");
1700 /* REVISIT: if num_comp > 1, check whether comparator #1 can
1701 * implement single-address data value watchpoints ... so we
1702 * won't need to check it later, when asked to set one up.
1706 static int cortex_m3_examine(struct target
*target
)
1709 uint32_t cpuid
, fpcr
;
1711 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1712 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
1714 if ((retval
= ahbap_debugport_init(swjdp
)) != ERROR_OK
)
1717 if (!target_was_examined(target
))
1719 target_set_examined(target
);
1721 /* Read from Device Identification Registers */
1722 retval
= target_read_u32(target
, CPUID
, &cpuid
);
1723 if (retval
!= ERROR_OK
)
1726 if (((cpuid
>> 4) & 0xc3f) == 0xc23)
1727 LOG_DEBUG("Cortex-M3 r%" PRId8
"p%" PRId8
" processor detected",
1728 (uint8_t)((cpuid
>> 20) & 0xf), (uint8_t)((cpuid
>> 0) & 0xf));
1729 LOG_DEBUG("cpuid: 0x%8.8" PRIx32
"", cpuid
);
1731 /* NOTE: FPB and DWT are both optional. */
1734 target_read_u32(target
, FP_CTRL
, &fpcr
);
1735 cortex_m3
->auto_bp_type
= 1;
1736 cortex_m3
->fp_num_code
= ((fpcr
>> 8) & 0x70) | ((fpcr
>> 4) & 0xF); /* bits [14:12] and [7:4] */
1737 cortex_m3
->fp_num_lit
= (fpcr
>> 8) & 0xF;
1738 cortex_m3
->fp_code_available
= cortex_m3
->fp_num_code
;
1739 cortex_m3
->fp_comparator_list
= calloc(cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
, sizeof(struct cortex_m3_fp_comparator
));
1740 cortex_m3
->fpb_enabled
= fpcr
& 1;
1741 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++)
1743 cortex_m3
->fp_comparator_list
[i
].type
= (i
< cortex_m3
->fp_num_code
) ? FPCR_CODE
: FPCR_LITERAL
;
1744 cortex_m3
->fp_comparator_list
[i
].fpcr_address
= FP_COMP0
+ 4 * i
;
1746 LOG_DEBUG("FPB fpcr 0x%" PRIx32
", numcode %i, numlit %i", fpcr
, cortex_m3
->fp_num_code
, cortex_m3
->fp_num_lit
);
1749 cortex_m3_dwt_setup(cortex_m3
, target
);
1751 /* These hardware breakpoints only work for code in flash! */
1752 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
1753 target_name(target
),
1754 cortex_m3
->fp_num_code
,
1755 cortex_m3
->dwt_num_comp
);
1761 static int cortex_m3_dcc_read(struct swjdp_common
*swjdp
, uint8_t *value
, uint8_t *ctrl
)
1765 mem_ap_read_buf_u16(swjdp
, (uint8_t*)&dcrdr
, 1, DCB_DCRDR
);
1766 *ctrl
= (uint8_t)dcrdr
;
1767 *value
= (uint8_t)(dcrdr
>> 8);
1769 LOG_DEBUG("data 0x%x ctrl 0x%x", *value
, *ctrl
);
1771 /* write ack back to software dcc register
1772 * signify we have read data */
1773 if (dcrdr
& (1 << 0))
1776 mem_ap_write_buf_u16(swjdp
, (uint8_t*)&dcrdr
, 1, DCB_DCRDR
);
1782 static int cortex_m3_target_request_data(struct target
*target
,
1783 uint32_t size
, uint8_t *buffer
)
1785 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1786 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1791 for (i
= 0; i
< (size
* 4); i
++)
1793 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1800 static int cortex_m3_handle_target_request(void *priv
)
1802 struct target
*target
= priv
;
1803 if (!target_was_examined(target
))
1805 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1806 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1808 if (!target
->dbg_msg_enabled
)
1811 if (target
->state
== TARGET_RUNNING
)
1816 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1818 /* check if we have data */
1819 if (ctrl
& (1 << 0))
1823 /* we assume target is quick enough */
1825 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1826 request
|= (data
<< 8);
1827 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1828 request
|= (data
<< 16);
1829 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1830 request
|= (data
<< 24);
1831 target_request(target
, request
);
1838 static int cortex_m3_init_arch_info(struct target
*target
,
1839 struct cortex_m3_common
*cortex_m3
, struct jtag_tap
*tap
)
1842 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
1844 armv7m_init_arch_info(target
, armv7m
);
1846 /* prepare JTAG information for the new target */
1847 cortex_m3
->jtag_info
.tap
= tap
;
1848 cortex_m3
->jtag_info
.scann_size
= 4;
1850 /* Leave (only) generic DAP stuff for debugport_init(); */
1851 armv7m
->swjdp_info
.jtag_info
= &cortex_m3
->jtag_info
;
1852 armv7m
->swjdp_info
.memaccess_tck
= 8;
1853 /* Cortex-M3 has 4096 bytes autoincrement range */
1854 armv7m
->swjdp_info
.tar_autoincr_block
= (1 << 12);
1856 /* register arch-specific functions */
1857 armv7m
->examine_debug_reason
= cortex_m3_examine_debug_reason
;
1859 armv7m
->post_debug_entry
= NULL
;
1861 armv7m
->pre_restore_context
= NULL
;
1862 armv7m
->post_restore_context
= NULL
;
1864 armv7m
->load_core_reg_u32
= cortex_m3_load_core_reg_u32
;
1865 armv7m
->store_core_reg_u32
= cortex_m3_store_core_reg_u32
;
1867 target_register_timer_callback(cortex_m3_handle_target_request
, 1, 1, target
);
1869 if ((retval
= arm_jtag_setup_connection(&cortex_m3
->jtag_info
)) != ERROR_OK
)
1877 static int cortex_m3_target_create(struct target
*target
, Jim_Interp
*interp
)
1879 struct cortex_m3_common
*cortex_m3
= calloc(1,sizeof(struct cortex_m3_common
));
1881 cortex_m3
->common_magic
= CORTEX_M3_COMMON_MAGIC
;
1882 cortex_m3_init_arch_info(target
, cortex_m3
, target
->tap
);
1887 /*--------------------------------------------------------------------------*/
1889 static int cortex_m3_verify_pointer(struct command_context
*cmd_ctx
,
1890 struct cortex_m3_common
*cm3
)
1892 if (cm3
->common_magic
!= CORTEX_M3_COMMON_MAGIC
) {
1893 command_print(cmd_ctx
, "target is not a Cortex-M3");
1894 return ERROR_TARGET_INVALID
;
1900 * Only stuff below this line should need to verify that its target
1901 * is a Cortex-M3. Everything else should have indirected through the
1902 * cortexm3_target structure, which is only used with CM3 targets.
1905 static const struct {
1909 { "hard_err", VC_HARDERR
, },
1910 { "int_err", VC_INTERR
, },
1911 { "bus_err", VC_BUSERR
, },
1912 { "state_err", VC_STATERR
, },
1913 { "chk_err", VC_CHKERR
, },
1914 { "nocp_err", VC_NOCPERR
, },
1915 { "mm_err", VC_MMERR
, },
1916 { "reset", VC_CORERESET
, },
1919 COMMAND_HANDLER(handle_cortex_m3_vector_catch_command
)
1921 struct target
*target
= get_current_target(CMD_CTX
);
1922 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1923 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
1924 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1928 retval
= cortex_m3_verify_pointer(CMD_CTX
, cortex_m3
);
1929 if (retval
!= ERROR_OK
)
1932 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &demcr
);
1937 if (CMD_ARGC
== 1) {
1938 if (strcmp(CMD_ARGV
[0], "all") == 0) {
1939 catch = VC_HARDERR
| VC_INTERR
| VC_BUSERR
1940 | VC_STATERR
| VC_CHKERR
| VC_NOCPERR
1941 | VC_MMERR
| VC_CORERESET
;
1943 } else if (strcmp(CMD_ARGV
[0], "none") == 0) {
1947 while (CMD_ARGC
-- > 0) {
1949 for (i
= 0; i
< ARRAY_SIZE(vec_ids
); i
++) {
1950 if (strcmp(CMD_ARGV
[CMD_ARGC
], vec_ids
[i
].name
) != 0)
1952 catch |= vec_ids
[i
].mask
;
1955 if (i
== ARRAY_SIZE(vec_ids
)) {
1956 LOG_ERROR("No CM3 vector '%s'", CMD_ARGV
[CMD_ARGC
]);
1957 return ERROR_INVALID_ARGUMENTS
;
1961 /* For now, armv7m->demcr only stores vector catch flags. */
1962 armv7m
->demcr
= catch;
1967 /* write, but don't assume it stuck (why not??) */
1968 mem_ap_write_u32(swjdp
, DCB_DEMCR
, demcr
);
1969 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &demcr
);
1971 /* FIXME be sure to clear DEMCR on clean server shutdown.
1972 * Otherwise the vector catch hardware could fire when there's
1973 * no debugger hooked up, causing much confusion...
1977 for (unsigned i
= 0; i
< ARRAY_SIZE(vec_ids
); i
++)
1979 command_print(CMD_CTX
, "%9s: %s", vec_ids
[i
].name
,
1980 (demcr
& vec_ids
[i
].mask
) ? "catch" : "ignore");
1986 COMMAND_HANDLER(handle_cortex_m3_mask_interrupts_command
)
1988 struct target
*target
= get_current_target(CMD_CTX
);
1989 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1992 retval
= cortex_m3_verify_pointer(CMD_CTX
, cortex_m3
);
1993 if (retval
!= ERROR_OK
)
1996 if (target
->state
!= TARGET_HALTED
)
1998 command_print(CMD_CTX
, "target must be stopped for \"%s\" command", CMD_NAME
);
2005 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], enable
);
2006 uint32_t mask_on
= C_HALT
| (enable
? C_MASKINTS
: 0);
2007 uint32_t mask_off
= enable
? 0 : C_MASKINTS
;
2008 cortex_m3_write_debug_halt_mask(target
, mask_on
, mask_off
);
2011 command_print(CMD_CTX
, "cortex_m3 interrupt mask %s",
2012 (cortex_m3
->dcb_dhcsr
& C_MASKINTS
) ? "on" : "off");
2017 static const struct command_registration cortex_m3_exec_command_handlers
[] = {
2020 .handler
= handle_cortex_m3_mask_interrupts_command
,
2021 .mode
= COMMAND_EXEC
,
2022 .help
= "mask cortex_m3 interrupts",
2023 .usage
= "['on'|'off']",
2026 .name
= "vector_catch",
2027 .handler
= handle_cortex_m3_vector_catch_command
,
2028 .mode
= COMMAND_EXEC
,
2029 .help
= "configure hardware vectors to trigger debug entry",
2030 .usage
= "['all'|'none'|('bus_err'|'chk_err'|...)*]",
2032 COMMAND_REGISTRATION_DONE
2034 static const struct command_registration cortex_m3_command_handlers
[] = {
2036 .chain
= armv7m_command_handlers
,
2039 .name
= "cortex_m3",
2040 .mode
= COMMAND_EXEC
,
2041 .help
= "Cortex-M3 command group",
2042 .chain
= cortex_m3_exec_command_handlers
,
2044 COMMAND_REGISTRATION_DONE
2047 struct target_type cortexm3_target
=
2049 .name
= "cortex_m3",
2051 .poll
= cortex_m3_poll
,
2052 .arch_state
= armv7m_arch_state
,
2054 .target_request_data
= cortex_m3_target_request_data
,
2056 .halt
= cortex_m3_halt
,
2057 .resume
= cortex_m3_resume
,
2058 .step
= cortex_m3_step
,
2060 .assert_reset
= cortex_m3_assert_reset
,
2061 .deassert_reset
= cortex_m3_deassert_reset
,
2062 .soft_reset_halt
= cortex_m3_soft_reset_halt
,
2064 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
2066 .read_memory
= cortex_m3_read_memory
,
2067 .write_memory
= cortex_m3_write_memory
,
2068 .bulk_write_memory
= cortex_m3_bulk_write_memory
,
2069 .checksum_memory
= armv7m_checksum_memory
,
2070 .blank_check_memory
= armv7m_blank_check_memory
,
2072 .run_algorithm
= armv7m_run_algorithm
,
2074 .add_breakpoint
= cortex_m3_add_breakpoint
,
2075 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
2076 .add_watchpoint
= cortex_m3_add_watchpoint
,
2077 .remove_watchpoint
= cortex_m3_remove_watchpoint
,
2079 .commands
= cortex_m3_command_handlers
,
2080 .target_create
= cortex_m3_target_create
,
2081 .init_target
= cortex_m3_init_target
,
2082 .examine
= cortex_m3_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)