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"
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 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
500 if (prev_target_state
== TARGET_DEBUG_RUNNING
)
503 if ((retval
= cortex_m3_debug_entry(target
)) != ERROR_OK
)
506 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
510 /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
511 * How best to model low power modes?
514 if (target
->state
== TARGET_UNKNOWN
)
516 /* check if processor is retiring instructions */
517 if (cortex_m3
->dcb_dhcsr
& S_RETIRE_ST
)
519 target
->state
= TARGET_RUNNING
;
527 static int cortex_m3_halt(struct target
*target
)
529 LOG_DEBUG("target->state: %s",
530 target_state_name(target
));
532 if (target
->state
== TARGET_HALTED
)
534 LOG_DEBUG("target was already halted");
538 if (target
->state
== TARGET_UNKNOWN
)
540 LOG_WARNING("target was in unknown state when halt was requested");
543 if (target
->state
== TARGET_RESET
)
545 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST
) && jtag_get_srst())
547 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
548 return ERROR_TARGET_FAILURE
;
552 /* we came here in a reset_halt or reset_init sequence
553 * debug entry was already prepared in cortex_m3_prepare_reset_halt()
555 target
->debug_reason
= DBG_REASON_DBGRQ
;
561 /* Write to Debug Halting Control and Status Register */
562 cortex_m3_write_debug_halt_mask(target
, C_HALT
, 0);
564 target
->debug_reason
= DBG_REASON_DBGRQ
;
569 static int cortex_m3_soft_reset_halt(struct target
*target
)
571 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
572 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
573 uint32_t dcb_dhcsr
= 0;
574 int retval
, timeout
= 0;
576 /* Enter debug state on reset; restore DEMCR in endreset_event() */
577 mem_ap_write_u32(swjdp
, DCB_DEMCR
,
578 TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
580 /* Request a core-only reset */
581 mem_ap_write_atomic_u32(swjdp
, NVIC_AIRCR
,
582 AIRCR_VECTKEY
| AIRCR_VECTRESET
);
583 target
->state
= TARGET_RESET
;
585 /* registers are now invalid */
586 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
588 while (timeout
< 100)
590 retval
= mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &dcb_dhcsr
);
591 if (retval
== ERROR_OK
)
593 mem_ap_read_atomic_u32(swjdp
, NVIC_DFSR
,
594 &cortex_m3
->nvic_dfsr
);
595 if ((dcb_dhcsr
& S_HALT
)
596 && (cortex_m3
->nvic_dfsr
& DFSR_VCATCH
))
598 LOG_DEBUG("system reset-halted, DHCSR 0x%08x, "
600 (unsigned) dcb_dhcsr
,
601 (unsigned) cortex_m3
->nvic_dfsr
);
602 cortex_m3_poll(target
);
603 /* FIXME restore user's vector catch config */
607 LOG_DEBUG("waiting for system reset-halt, "
608 "DHCSR 0x%08x, %d ms",
609 (unsigned) dcb_dhcsr
, timeout
);
618 static void cortex_m3_enable_breakpoints(struct target
*target
)
620 struct breakpoint
*breakpoint
= target
->breakpoints
;
622 /* set any pending breakpoints */
625 if (!breakpoint
->set
)
626 cortex_m3_set_breakpoint(target
, breakpoint
);
627 breakpoint
= breakpoint
->next
;
631 static int cortex_m3_resume(struct target
*target
, int current
,
632 uint32_t address
, int handle_breakpoints
, int debug_execution
)
634 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
635 struct breakpoint
*breakpoint
= NULL
;
639 if (target
->state
!= TARGET_HALTED
)
641 LOG_WARNING("target not halted");
642 return ERROR_TARGET_NOT_HALTED
;
645 if (!debug_execution
)
647 target_free_all_working_areas(target
);
648 cortex_m3_enable_breakpoints(target
);
649 cortex_m3_enable_watchpoints(target
);
654 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_PRIMASK
;
656 /* Disable interrupts */
657 /* We disable interrupts in the PRIMASK register instead of
658 * masking with C_MASKINTS. This is probably the same issue
659 * as Cortex-M3 Erratum 377493 (fixed in r1p0): C_MASKINTS
660 * in parallel with disabled interrupts can cause local faults
663 * REVISIT this clearly breaks non-debug execution, since the
664 * PRIMASK register state isn't saved/restored... workaround
665 * by never resuming app code after debug execution.
667 buf_set_u32(r
->value
, 0, 1, 1);
671 /* Make sure we are in Thumb mode */
672 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
673 buf_set_u32(r
->value
, 24, 1, 1);
678 /* current = 1: continue on current pc, otherwise continue at <address> */
682 buf_set_u32(r
->value
, 0, 32, address
);
687 /* if we halted last time due to a bkpt instruction
688 * then we have to manually step over it, otherwise
689 * the core will break again */
691 if (!breakpoint_find(target
, buf_get_u32(r
->value
, 0, 32))
694 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
697 resume_pc
= buf_get_u32(r
->value
, 0, 32);
699 armv7m_restore_context(target
);
701 /* the front-end may request us not to handle breakpoints */
702 if (handle_breakpoints
)
704 /* Single step past breakpoint at current address */
705 if ((breakpoint
= breakpoint_find(target
, resume_pc
)))
707 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
709 breakpoint
->unique_id
);
710 cortex_m3_unset_breakpoint(target
, breakpoint
);
711 cortex_m3_single_step_core(target
);
712 cortex_m3_set_breakpoint(target
, breakpoint
);
717 cortex_m3_write_debug_halt_mask(target
, 0, C_HALT
);
719 target
->debug_reason
= DBG_REASON_NOTHALTED
;
721 /* registers are now invalid */
722 register_cache_invalidate(armv7m
->core_cache
);
724 if (!debug_execution
)
726 target
->state
= TARGET_RUNNING
;
727 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
728 LOG_DEBUG("target resumed at 0x%" PRIx32
"", resume_pc
);
732 target
->state
= TARGET_DEBUG_RUNNING
;
733 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
734 LOG_DEBUG("target debug resumed at 0x%" PRIx32
"", resume_pc
);
740 /* int irqstepcount = 0; */
741 static int cortex_m3_step(struct target
*target
, int current
,
742 uint32_t address
, int handle_breakpoints
)
744 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
745 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
746 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
747 struct breakpoint
*breakpoint
= NULL
;
748 struct reg
*pc
= armv7m
->arm
.pc
;
749 bool bkpt_inst_found
= false;
751 if (target
->state
!= TARGET_HALTED
)
753 LOG_WARNING("target not halted");
754 return ERROR_TARGET_NOT_HALTED
;
757 /* current = 1: continue on current pc, otherwise continue at <address> */
759 buf_set_u32(pc
->value
, 0, 32, address
);
761 /* the front-end may request us not to handle breakpoints */
762 if (handle_breakpoints
) {
763 breakpoint
= breakpoint_find(target
,
764 buf_get_u32(pc
->value
, 0, 32));
766 cortex_m3_unset_breakpoint(target
, breakpoint
);
769 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
771 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
773 armv7m_restore_context(target
);
775 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
777 /* if no bkpt instruction is found at pc then we can perform
778 * a normal step, otherwise we have to manually step over the bkpt
779 * instruction - as such simulate a step */
780 if (bkpt_inst_found
== false)
782 /* set step and clear halt */
783 cortex_m3_write_debug_halt_mask(target
, C_STEP
, C_HALT
);
786 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
788 /* registers are now invalid */
789 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
792 cortex_m3_set_breakpoint(target
, breakpoint
);
794 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
795 " nvic_icsr = 0x%" PRIx32
,
796 cortex_m3
->dcb_dhcsr
, cortex_m3
->nvic_icsr
);
798 cortex_m3_debug_entry(target
);
799 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
801 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
802 " nvic_icsr = 0x%" PRIx32
,
803 cortex_m3
->dcb_dhcsr
, cortex_m3
->nvic_icsr
);
808 static int cortex_m3_assert_reset(struct target
*target
)
810 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
811 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
814 LOG_DEBUG("target->state: %s",
815 target_state_name(target
));
817 enum reset_types jtag_reset_config
= jtag_get_reset_config();
820 * We can reset Cortex-M3 targets using just the NVIC without
821 * requiring SRST, getting a SoC reset (or a core-only reset)
822 * instead of a system reset.
824 if (!(jtag_reset_config
& RESET_HAS_SRST
))
827 /* Enable debug requests */
828 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
829 if (!(cortex_m3
->dcb_dhcsr
& C_DEBUGEN
))
830 mem_ap_write_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_DEBUGEN
);
832 mem_ap_write_u32(swjdp
, DCB_DCRDR
, 0);
834 if (!target
->reset_halt
)
836 /* Set/Clear C_MASKINTS in a separate operation */
837 if (cortex_m3
->dcb_dhcsr
& C_MASKINTS
)
838 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
,
839 DBGKEY
| C_DEBUGEN
| C_HALT
);
841 /* clear any debug flags before resuming */
842 cortex_m3_clear_halt(target
);
844 /* clear C_HALT in dhcsr reg */
845 cortex_m3_write_debug_halt_mask(target
, 0, C_HALT
);
849 /* Halt in debug on reset; endreset_event() restores DEMCR.
851 * REVISIT catching BUSERR presumably helps to defend against
852 * bad vector table entries. Should this include MMERR or
855 mem_ap_write_atomic_u32(swjdp
, DCB_DEMCR
,
856 TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
860 * When nRST is asserted on most Stellaris devices, it clears some of
861 * the debug state. The ARMv7M and Cortex-M3 TRMs say that's wrong;
862 * and OpenOCD depends on those TRMs. So we won't use SRST on those
863 * chips. (Only power-on reset should affect debug state, beyond a
864 * few specified bits; not the chip's nRST input, wired to SRST.)
866 * REVISIT current errata specs don't seem to cover this issue.
867 * Do we have more details than this email?
868 * https://lists.berlios.de/pipermail
869 * /openocd-development/2008-August/003065.html
871 if (strcmp(target
->variant
, "lm3s") == 0)
873 /* Check for silicon revisions with the issue. */
876 if (target_read_u32(target
, 0x400fe000, &did0
) == ERROR_OK
)
878 switch ((did0
>> 16) & 0xff)
881 /* all Sandstorm suffer issue */
887 /* Fury and DustDevil rev A have
888 * this nRST problem. It should
889 * be fixed in rev B silicon.
891 if (((did0
>> 8) & 0xff) == 0)
895 /* Tempest should be fine. */
903 /* default to asserting srst */
904 if (jtag_reset_config
& RESET_SRST_PULLS_TRST
)
906 jtag_add_reset(1, 1);
910 jtag_add_reset(0, 1);
915 /* Use a standard Cortex-M3 software reset mechanism.
916 * SYSRESETREQ will reset SoC peripherals outside the
917 * core, like watchdog timers, if the SoC wires it up
918 * correctly. Else VECRESET can reset just the core.
920 mem_ap_write_atomic_u32(swjdp
, NVIC_AIRCR
,
921 AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
922 LOG_DEBUG("Using Cortex-M3 SYSRESETREQ");
925 /* I do not know why this is necessary, but it
926 * fixes strange effects (step/resume cause NMI
927 * after reset) on LM3S6918 -- Michael Schwingen
930 mem_ap_read_atomic_u32(swjdp
, NVIC_AIRCR
, &tmp
);
934 target
->state
= TARGET_RESET
;
935 jtag_add_sleep(50000);
937 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
939 if (target
->reset_halt
)
942 if ((retval
= target_halt(target
)) != ERROR_OK
)
949 static int cortex_m3_deassert_reset(struct target
*target
)
951 LOG_DEBUG("target->state: %s",
952 target_state_name(target
));
954 /* deassert reset lines */
955 jtag_add_reset(0, 0);
961 cortex_m3_set_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
966 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
967 struct cortex_m3_fp_comparator
*comparator_list
= cortex_m3
->fp_comparator_list
;
971 LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint
->unique_id
);
975 if (cortex_m3
->auto_bp_type
)
977 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
980 if (breakpoint
->type
== BKPT_HARD
)
982 while (comparator_list
[fp_num
].used
&& (fp_num
< cortex_m3
->fp_num_code
))
984 if (fp_num
>= cortex_m3
->fp_num_code
)
986 LOG_ERROR("Can not find free FPB Comparator!");
989 breakpoint
->set
= fp_num
+ 1;
990 hilo
= (breakpoint
->address
& 0x2) ? FPCR_REPLACE_BKPT_HIGH
: FPCR_REPLACE_BKPT_LOW
;
991 comparator_list
[fp_num
].used
= 1;
992 comparator_list
[fp_num
].fpcr_value
= (breakpoint
->address
& 0x1FFFFFFC) | hilo
| 1;
993 target_write_u32(target
, comparator_list
[fp_num
].fpcr_address
, comparator_list
[fp_num
].fpcr_value
);
994 LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32
"", fp_num
, comparator_list
[fp_num
].fpcr_value
);
995 if (!cortex_m3
->fpb_enabled
)
997 LOG_DEBUG("FPB wasn't enabled, do it now");
998 target_write_u32(target
, FP_CTRL
, 3);
1001 else if (breakpoint
->type
== BKPT_SOFT
)
1005 /* NOTE: on ARMv6-M and ARMv7-M, BKPT(0xab) is used for
1006 * semihosting; don't use that. Otherwise the BKPT
1007 * parameter is arbitrary.
1009 buf_set_u32(code
, 0, 32, ARMV5_T_BKPT(0x11));
1010 retval
= target_read_memory(target
,
1011 breakpoint
->address
& 0xFFFFFFFE,
1012 breakpoint
->length
, 1,
1013 breakpoint
->orig_instr
);
1014 if (retval
!= ERROR_OK
)
1016 retval
= target_write_memory(target
,
1017 breakpoint
->address
& 0xFFFFFFFE,
1018 breakpoint
->length
, 1,
1020 if (retval
!= ERROR_OK
)
1022 breakpoint
->set
= true;
1025 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32
" Length: %d (set=%d)",
1026 breakpoint
->unique_id
,
1027 (int)(breakpoint
->type
),
1028 breakpoint
->address
,
1036 cortex_m3_unset_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1039 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1040 struct cortex_m3_fp_comparator
* comparator_list
= cortex_m3
->fp_comparator_list
;
1042 if (!breakpoint
->set
)
1044 LOG_WARNING("breakpoint not set");
1048 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32
" Length: %d (set=%d)",
1049 breakpoint
->unique_id
,
1050 (int)(breakpoint
->type
),
1051 breakpoint
->address
,
1055 if (breakpoint
->type
== BKPT_HARD
)
1057 int fp_num
= breakpoint
->set
- 1;
1058 if ((fp_num
< 0) || (fp_num
>= cortex_m3
->fp_num_code
))
1060 LOG_DEBUG("Invalid FP Comparator number in breakpoint");
1063 comparator_list
[fp_num
].used
= 0;
1064 comparator_list
[fp_num
].fpcr_value
= 0;
1065 target_write_u32(target
, comparator_list
[fp_num
].fpcr_address
, comparator_list
[fp_num
].fpcr_value
);
1069 /* restore original instruction (kept in target endianness) */
1070 if (breakpoint
->length
== 4)
1072 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, 4, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
1079 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, 2, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
1085 breakpoint
->set
= false;
1091 cortex_m3_add_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1093 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1095 if (cortex_m3
->auto_bp_type
)
1097 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
1098 #ifdef ARMV7_GDB_HACKS
1099 if (breakpoint
->length
!= 2) {
1100 /* XXX Hack: Replace all breakpoints with length != 2 with
1101 * a hardware breakpoint. */
1102 breakpoint
->type
= BKPT_HARD
;
1103 breakpoint
->length
= 2;
1108 if ((breakpoint
->type
== BKPT_HARD
) && (breakpoint
->address
>= 0x20000000))
1110 LOG_INFO("flash patch comparator requested outside code memory region");
1111 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1114 if ((breakpoint
->type
== BKPT_SOFT
) && (breakpoint
->address
< 0x20000000))
1116 LOG_INFO("soft breakpoint requested in code (flash) memory region");
1117 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1120 if ((breakpoint
->type
== BKPT_HARD
) && (cortex_m3
->fp_code_available
< 1))
1122 LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
1123 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1126 if ((breakpoint
->length
!= 2))
1128 LOG_INFO("only breakpoints of two bytes length supported");
1129 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1132 if (breakpoint
->type
== BKPT_HARD
)
1133 cortex_m3
->fp_code_available
--;
1134 cortex_m3_set_breakpoint(target
, breakpoint
);
1140 cortex_m3_remove_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1142 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1144 /* REVISIT why check? FBP can be updated with core running ... */
1145 if (target
->state
!= TARGET_HALTED
)
1147 LOG_WARNING("target not halted");
1148 return ERROR_TARGET_NOT_HALTED
;
1151 if (cortex_m3
->auto_bp_type
)
1153 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
1156 if (breakpoint
->set
)
1158 cortex_m3_unset_breakpoint(target
, breakpoint
);
1161 if (breakpoint
->type
== BKPT_HARD
)
1162 cortex_m3
->fp_code_available
++;
1168 cortex_m3_set_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1171 uint32_t mask
, temp
;
1172 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1174 /* watchpoint params were validated earlier */
1176 temp
= watchpoint
->length
;
1183 /* REVISIT Don't fully trust these "not used" records ... users
1184 * may set up breakpoints by hand, e.g. dual-address data value
1185 * watchpoint using comparator #1; comparator #0 matching cycle
1186 * count; send data trace info through ITM and TPIU; etc
1188 struct cortex_m3_dwt_comparator
*comparator
;
1190 for (comparator
= cortex_m3
->dwt_comparator_list
;
1191 comparator
->used
&& dwt_num
< cortex_m3
->dwt_num_comp
;
1192 comparator
++, dwt_num
++)
1194 if (dwt_num
>= cortex_m3
->dwt_num_comp
)
1196 LOG_ERROR("Can not find free DWT Comparator");
1199 comparator
->used
= 1;
1200 watchpoint
->set
= dwt_num
+ 1;
1202 comparator
->comp
= watchpoint
->address
;
1203 target_write_u32(target
, comparator
->dwt_comparator_address
+ 0,
1206 comparator
->mask
= mask
;
1207 target_write_u32(target
, comparator
->dwt_comparator_address
+ 4,
1210 switch (watchpoint
->rw
) {
1212 comparator
->function
= 5;
1215 comparator
->function
= 6;
1218 comparator
->function
= 7;
1221 target_write_u32(target
, comparator
->dwt_comparator_address
+ 8,
1222 comparator
->function
);
1224 LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x",
1225 watchpoint
->unique_id
, dwt_num
,
1226 (unsigned) comparator
->comp
,
1227 (unsigned) comparator
->mask
,
1228 (unsigned) comparator
->function
);
1233 cortex_m3_unset_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1235 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1236 struct cortex_m3_dwt_comparator
*comparator
;
1239 if (!watchpoint
->set
)
1241 LOG_WARNING("watchpoint (wpid: %d) not set",
1242 watchpoint
->unique_id
);
1246 dwt_num
= watchpoint
->set
- 1;
1248 LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
1249 watchpoint
->unique_id
, dwt_num
,
1250 (unsigned) watchpoint
->address
);
1252 if ((dwt_num
< 0) || (dwt_num
>= cortex_m3
->dwt_num_comp
))
1254 LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
1258 comparator
= cortex_m3
->dwt_comparator_list
+ dwt_num
;
1259 comparator
->used
= 0;
1260 comparator
->function
= 0;
1261 target_write_u32(target
, comparator
->dwt_comparator_address
+ 8,
1262 comparator
->function
);
1264 watchpoint
->set
= false;
1270 cortex_m3_add_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1272 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1274 if (cortex_m3
->dwt_comp_available
< 1)
1276 LOG_DEBUG("no comparators?");
1277 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1280 /* hardware doesn't support data value masking */
1281 if (watchpoint
->mask
!= ~(uint32_t)0) {
1282 LOG_DEBUG("watchpoint value masks not supported");
1283 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1286 /* hardware allows address masks of up to 32K */
1289 for (mask
= 0; mask
< 16; mask
++) {
1290 if ((1u << mask
) == watchpoint
->length
)
1294 LOG_DEBUG("unsupported watchpoint length");
1295 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1297 if (watchpoint
->address
& ((1 << mask
) - 1)) {
1298 LOG_DEBUG("watchpoint address is unaligned");
1299 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1302 /* Caller doesn't seem to be able to describe watching for data
1303 * values of zero; that flags "no value".
1305 * REVISIT This DWT may well be able to watch for specific data
1306 * values. Requires comparator #1 to set DATAVMATCH and match
1307 * the data, and another comparator (DATAVADDR0) matching addr.
1309 if (watchpoint
->value
) {
1310 LOG_DEBUG("data value watchpoint not YET supported");
1311 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1314 cortex_m3
->dwt_comp_available
--;
1315 LOG_DEBUG("dwt_comp_available: %d", cortex_m3
->dwt_comp_available
);
1321 cortex_m3_remove_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1323 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1325 /* REVISIT why check? DWT can be updated with core running ... */
1326 if (target
->state
!= TARGET_HALTED
)
1328 LOG_WARNING("target not halted");
1329 return ERROR_TARGET_NOT_HALTED
;
1332 if (watchpoint
->set
)
1334 cortex_m3_unset_watchpoint(target
, watchpoint
);
1337 cortex_m3
->dwt_comp_available
++;
1338 LOG_DEBUG("dwt_comp_available: %d", cortex_m3
->dwt_comp_available
);
1343 static void cortex_m3_enable_watchpoints(struct target
*target
)
1345 struct watchpoint
*watchpoint
= target
->watchpoints
;
1347 /* set any pending watchpoints */
1350 if (!watchpoint
->set
)
1351 cortex_m3_set_watchpoint(target
, watchpoint
);
1352 watchpoint
= watchpoint
->next
;
1356 static int cortex_m3_load_core_reg_u32(struct target
*target
,
1357 enum armv7m_regtype type
, uint32_t num
, uint32_t * value
)
1360 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1361 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1363 /* NOTE: we "know" here that the register identifiers used
1364 * in the v7m header match the Cortex-M3 Debug Core Register
1365 * Selector values for R0..R15, xPSR, MSP, and PSP.
1369 /* read a normal core register */
1370 retval
= cortexm3_dap_read_coreregister_u32(swjdp
, value
, num
);
1372 if (retval
!= ERROR_OK
)
1374 LOG_ERROR("JTAG failure %i",retval
);
1375 return ERROR_JTAG_DEVICE_ERROR
;
1377 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"",(int)num
,*value
);
1380 case ARMV7M_PRIMASK
:
1381 case ARMV7M_BASEPRI
:
1382 case ARMV7M_FAULTMASK
:
1383 case ARMV7M_CONTROL
:
1384 /* Cortex-M3 packages these four registers as bitfields
1385 * in one Debug Core register. So say r0 and r2 docs;
1386 * it was removed from r1 docs, but still works.
1388 cortexm3_dap_read_coreregister_u32(swjdp
, value
, 20);
1392 case ARMV7M_PRIMASK
:
1393 *value
= buf_get_u32((uint8_t*)value
, 0, 1);
1396 case ARMV7M_BASEPRI
:
1397 *value
= buf_get_u32((uint8_t*)value
, 8, 8);
1400 case ARMV7M_FAULTMASK
:
1401 *value
= buf_get_u32((uint8_t*)value
, 16, 1);
1404 case ARMV7M_CONTROL
:
1405 *value
= buf_get_u32((uint8_t*)value
, 24, 2);
1409 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"", (int)num
, *value
);
1413 return ERROR_INVALID_ARGUMENTS
;
1419 static int cortex_m3_store_core_reg_u32(struct target
*target
,
1420 enum armv7m_regtype type
, uint32_t num
, uint32_t value
)
1424 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1425 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1427 #ifdef ARMV7_GDB_HACKS
1428 /* If the LR register is being modified, make sure it will put us
1429 * in "thumb" mode, or an INVSTATE exception will occur. This is a
1430 * hack to deal with the fact that gdb will sometimes "forge"
1431 * return addresses, and doesn't set the LSB correctly (i.e., when
1432 * printing expressions containing function calls, it sets LR = 0.)
1433 * Valid exception return codes have bit 0 set too.
1435 if (num
== ARMV7M_R14
)
1439 /* NOTE: we "know" here that the register identifiers used
1440 * in the v7m header match the Cortex-M3 Debug Core Register
1441 * Selector values for R0..R15, xPSR, MSP, and PSP.
1445 retval
= cortexm3_dap_write_coreregister_u32(swjdp
, value
, num
);
1446 if (retval
!= ERROR_OK
)
1450 LOG_ERROR("JTAG failure %i", retval
);
1451 r
= armv7m
->core_cache
->reg_list
+ num
;
1452 r
->dirty
= r
->valid
;
1453 return ERROR_JTAG_DEVICE_ERROR
;
1455 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
1458 case ARMV7M_PRIMASK
:
1459 case ARMV7M_BASEPRI
:
1460 case ARMV7M_FAULTMASK
:
1461 case ARMV7M_CONTROL
:
1462 /* Cortex-M3 packages these four registers as bitfields
1463 * in one Debug Core register. So say r0 and r2 docs;
1464 * it was removed from r1 docs, but still works.
1466 cortexm3_dap_read_coreregister_u32(swjdp
, ®
, 20);
1470 case ARMV7M_PRIMASK
:
1471 buf_set_u32((uint8_t*)®
, 0, 1, value
);
1474 case ARMV7M_BASEPRI
:
1475 buf_set_u32((uint8_t*)®
, 8, 8, value
);
1478 case ARMV7M_FAULTMASK
:
1479 buf_set_u32((uint8_t*)®
, 16, 1, value
);
1482 case ARMV7M_CONTROL
:
1483 buf_set_u32((uint8_t*)®
, 24, 2, value
);
1487 cortexm3_dap_write_coreregister_u32(swjdp
, reg
, 20);
1489 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
1493 return ERROR_INVALID_ARGUMENTS
;
1499 static int cortex_m3_read_memory(struct target
*target
, uint32_t address
,
1500 uint32_t size
, uint32_t count
, uint8_t *buffer
)
1502 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1503 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1504 int retval
= ERROR_INVALID_ARGUMENTS
;
1506 /* cortex_m3 handles unaligned memory access */
1507 if (count
&& buffer
) {
1510 retval
= mem_ap_read_buf_u32(swjdp
, buffer
, 4 * count
, address
);
1513 retval
= mem_ap_read_buf_u16(swjdp
, buffer
, 2 * count
, address
);
1516 retval
= mem_ap_read_buf_u8(swjdp
, buffer
, count
, address
);
1524 static int cortex_m3_write_memory(struct target
*target
, uint32_t address
,
1525 uint32_t size
, uint32_t count
, uint8_t *buffer
)
1527 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1528 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1529 int retval
= ERROR_INVALID_ARGUMENTS
;
1531 if (count
&& buffer
) {
1534 retval
= mem_ap_write_buf_u32(swjdp
, buffer
, 4 * count
, address
);
1537 retval
= mem_ap_write_buf_u16(swjdp
, buffer
, 2 * count
, address
);
1540 retval
= mem_ap_write_buf_u8(swjdp
, buffer
, count
, address
);
1548 static int cortex_m3_bulk_write_memory(struct target
*target
, uint32_t address
,
1549 uint32_t count
, uint8_t *buffer
)
1551 return cortex_m3_write_memory(target
, address
, 4, count
, buffer
);
1554 static int cortex_m3_init_target(struct command_context
*cmd_ctx
,
1555 struct target
*target
)
1557 armv7m_build_reg_cache(target
);
1561 /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid"
1562 * on r/w if the core is not running, and clear on resume or reset ... or
1563 * at least, in a post_restore_context() method.
1566 struct dwt_reg_state
{
1567 struct target
*target
;
1569 uint32_t value
; /* scratch/cache */
1572 static int cortex_m3_dwt_get_reg(struct reg
*reg
)
1574 struct dwt_reg_state
*state
= reg
->arch_info
;
1576 return target_read_u32(state
->target
, state
->addr
, &state
->value
);
1579 static int cortex_m3_dwt_set_reg(struct reg
*reg
, uint8_t *buf
)
1581 struct dwt_reg_state
*state
= reg
->arch_info
;
1583 return target_write_u32(state
->target
, state
->addr
,
1584 buf_get_u32(buf
, 0, reg
->size
));
1593 static struct dwt_reg dwt_base_regs
[] = {
1594 { DWT_CTRL
, "dwt_ctrl", 32, },
1595 /* NOTE that Erratum 532314 (fixed r2p0) affects CYCCNT: it wrongly
1596 * increments while the core is asleep.
1598 { DWT_CYCCNT
, "dwt_cyccnt", 32, },
1599 /* plus some 8 bit counters, useful for profiling with TPIU */
1602 static struct dwt_reg dwt_comp
[] = {
1603 #define DWT_COMPARATOR(i) \
1604 { DWT_COMP0 + 0x10 * (i), "dwt_" #i "_comp", 32, }, \
1605 { DWT_MASK0 + 0x10 * (i), "dwt_" #i "_mask", 4, }, \
1606 { DWT_FUNCTION0 + 0x10 * (i), "dwt_" #i "_function", 32, }
1611 #undef DWT_COMPARATOR
1614 static const struct reg_arch_type dwt_reg_type
= {
1615 .get
= cortex_m3_dwt_get_reg
,
1616 .set
= cortex_m3_dwt_set_reg
,
1620 cortex_m3_dwt_addreg(struct target
*t
, struct reg
*r
, struct dwt_reg
*d
)
1622 struct dwt_reg_state
*state
;
1624 state
= calloc(1, sizeof *state
);
1627 state
->addr
= d
->addr
;
1632 r
->value
= &state
->value
;
1633 r
->arch_info
= state
;
1634 r
->type
= &dwt_reg_type
;
1638 cortex_m3_dwt_setup(struct cortex_m3_common
*cm3
, struct target
*target
)
1641 struct reg_cache
*cache
;
1642 struct cortex_m3_dwt_comparator
*comparator
;
1645 target_read_u32(target
, DWT_CTRL
, &dwtcr
);
1647 LOG_DEBUG("no DWT");
1651 cm3
->dwt_num_comp
= (dwtcr
>> 28) & 0xF;
1652 cm3
->dwt_comp_available
= cm3
->dwt_num_comp
;
1653 cm3
->dwt_comparator_list
= calloc(cm3
->dwt_num_comp
,
1654 sizeof(struct cortex_m3_dwt_comparator
));
1655 if (!cm3
->dwt_comparator_list
) {
1657 cm3
->dwt_num_comp
= 0;
1658 LOG_ERROR("out of mem");
1662 cache
= calloc(1, sizeof *cache
);
1665 free(cm3
->dwt_comparator_list
);
1668 cache
->name
= "cortex-m3 dwt registers";
1669 cache
->num_regs
= 2 + cm3
->dwt_num_comp
* 3;
1670 cache
->reg_list
= calloc(cache
->num_regs
, sizeof *cache
->reg_list
);
1671 if (!cache
->reg_list
) {
1676 for (reg
= 0; reg
< 2; reg
++)
1677 cortex_m3_dwt_addreg(target
, cache
->reg_list
+ reg
,
1678 dwt_base_regs
+ reg
);
1680 comparator
= cm3
->dwt_comparator_list
;
1681 for (i
= 0; i
< cm3
->dwt_num_comp
; i
++, comparator
++) {
1684 comparator
->dwt_comparator_address
= DWT_COMP0
+ 0x10 * i
;
1685 for (j
= 0; j
< 3; j
++, reg
++)
1686 cortex_m3_dwt_addreg(target
, cache
->reg_list
+ reg
,
1687 dwt_comp
+ 3 * i
+ j
);
1690 *register_get_last_cache_p(&target
->reg_cache
) = cache
;
1691 cm3
->dwt_cache
= cache
;
1693 LOG_DEBUG("DWT dwtcr 0x%" PRIx32
", comp %d, watch%s",
1694 dwtcr
, cm3
->dwt_num_comp
,
1695 (dwtcr
& (0xf << 24)) ? " only" : "/trigger");
1697 /* REVISIT: if num_comp > 1, check whether comparator #1 can
1698 * implement single-address data value watchpoints ... so we
1699 * won't need to check it later, when asked to set one up.
1703 static int cortex_m3_examine(struct target
*target
)
1706 uint32_t cpuid
, fpcr
;
1708 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1709 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
1711 if ((retval
= ahbap_debugport_init(swjdp
)) != ERROR_OK
)
1714 if (!target_was_examined(target
))
1716 target_set_examined(target
);
1718 /* Read from Device Identification Registers */
1719 retval
= target_read_u32(target
, CPUID
, &cpuid
);
1720 if (retval
!= ERROR_OK
)
1723 if (((cpuid
>> 4) & 0xc3f) == 0xc23)
1724 LOG_DEBUG("Cortex-M3 r%" PRId8
"p%" PRId8
" processor detected",
1725 (uint8_t)((cpuid
>> 20) & 0xf), (uint8_t)((cpuid
>> 0) & 0xf));
1726 LOG_DEBUG("cpuid: 0x%8.8" PRIx32
"", cpuid
);
1728 /* NOTE: FPB and DWT are both optional. */
1731 target_read_u32(target
, FP_CTRL
, &fpcr
);
1732 cortex_m3
->auto_bp_type
= 1;
1733 cortex_m3
->fp_num_code
= ((fpcr
>> 8) & 0x70) | ((fpcr
>> 4) & 0xF); /* bits [14:12] and [7:4] */
1734 cortex_m3
->fp_num_lit
= (fpcr
>> 8) & 0xF;
1735 cortex_m3
->fp_code_available
= cortex_m3
->fp_num_code
;
1736 cortex_m3
->fp_comparator_list
= calloc(cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
, sizeof(struct cortex_m3_fp_comparator
));
1737 cortex_m3
->fpb_enabled
= fpcr
& 1;
1738 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++)
1740 cortex_m3
->fp_comparator_list
[i
].type
= (i
< cortex_m3
->fp_num_code
) ? FPCR_CODE
: FPCR_LITERAL
;
1741 cortex_m3
->fp_comparator_list
[i
].fpcr_address
= FP_COMP0
+ 4 * i
;
1743 LOG_DEBUG("FPB fpcr 0x%" PRIx32
", numcode %i, numlit %i", fpcr
, cortex_m3
->fp_num_code
, cortex_m3
->fp_num_lit
);
1746 cortex_m3_dwt_setup(cortex_m3
, target
);
1748 /* These hardware breakpoints only work for code in flash! */
1749 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
1750 target_name(target
),
1751 cortex_m3
->fp_num_code
,
1752 cortex_m3
->dwt_num_comp
);
1758 static int cortex_m3_dcc_read(struct swjdp_common
*swjdp
, uint8_t *value
, uint8_t *ctrl
)
1762 mem_ap_read_buf_u16(swjdp
, (uint8_t*)&dcrdr
, 1, DCB_DCRDR
);
1763 *ctrl
= (uint8_t)dcrdr
;
1764 *value
= (uint8_t)(dcrdr
>> 8);
1766 LOG_DEBUG("data 0x%x ctrl 0x%x", *value
, *ctrl
);
1768 /* write ack back to software dcc register
1769 * signify we have read data */
1770 if (dcrdr
& (1 << 0))
1773 mem_ap_write_buf_u16(swjdp
, (uint8_t*)&dcrdr
, 1, DCB_DCRDR
);
1779 static int cortex_m3_target_request_data(struct target
*target
,
1780 uint32_t size
, uint8_t *buffer
)
1782 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1783 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1788 for (i
= 0; i
< (size
* 4); i
++)
1790 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1797 static int cortex_m3_handle_target_request(void *priv
)
1799 struct target
*target
= priv
;
1800 if (!target_was_examined(target
))
1802 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1803 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1805 if (!target
->dbg_msg_enabled
)
1808 if (target
->state
== TARGET_RUNNING
)
1813 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1815 /* check if we have data */
1816 if (ctrl
& (1 << 0))
1820 /* we assume target is quick enough */
1822 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1823 request
|= (data
<< 8);
1824 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1825 request
|= (data
<< 16);
1826 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1827 request
|= (data
<< 24);
1828 target_request(target
, request
);
1835 static int cortex_m3_init_arch_info(struct target
*target
,
1836 struct cortex_m3_common
*cortex_m3
, struct jtag_tap
*tap
)
1839 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
1841 armv7m_init_arch_info(target
, armv7m
);
1843 /* prepare JTAG information for the new target */
1844 cortex_m3
->jtag_info
.tap
= tap
;
1845 cortex_m3
->jtag_info
.scann_size
= 4;
1847 /* Leave (only) generic DAP stuff for debugport_init(); */
1848 armv7m
->swjdp_info
.jtag_info
= &cortex_m3
->jtag_info
;
1849 armv7m
->swjdp_info
.memaccess_tck
= 8;
1850 /* Cortex-M3 has 4096 bytes autoincrement range */
1851 armv7m
->swjdp_info
.tar_autoincr_block
= (1 << 12);
1853 /* register arch-specific functions */
1854 armv7m
->examine_debug_reason
= cortex_m3_examine_debug_reason
;
1856 armv7m
->post_debug_entry
= NULL
;
1858 armv7m
->pre_restore_context
= NULL
;
1859 armv7m
->post_restore_context
= NULL
;
1861 armv7m
->load_core_reg_u32
= cortex_m3_load_core_reg_u32
;
1862 armv7m
->store_core_reg_u32
= cortex_m3_store_core_reg_u32
;
1864 target_register_timer_callback(cortex_m3_handle_target_request
, 1, 1, target
);
1866 if ((retval
= arm_jtag_setup_connection(&cortex_m3
->jtag_info
)) != ERROR_OK
)
1874 static int cortex_m3_target_create(struct target
*target
, Jim_Interp
*interp
)
1876 struct cortex_m3_common
*cortex_m3
= calloc(1,sizeof(struct cortex_m3_common
));
1878 cortex_m3
->common_magic
= CORTEX_M3_COMMON_MAGIC
;
1879 cortex_m3_init_arch_info(target
, cortex_m3
, target
->tap
);
1884 /*--------------------------------------------------------------------------*/
1886 static int cortex_m3_verify_pointer(struct command_context
*cmd_ctx
,
1887 struct cortex_m3_common
*cm3
)
1889 if (cm3
->common_magic
!= CORTEX_M3_COMMON_MAGIC
) {
1890 command_print(cmd_ctx
, "target is not a Cortex-M3");
1891 return ERROR_TARGET_INVALID
;
1897 * Only stuff below this line should need to verify that its target
1898 * is a Cortex-M3. Everything else should have indirected through the
1899 * cortexm3_target structure, which is only used with CM3 targets.
1902 static const struct {
1906 { "hard_err", VC_HARDERR
, },
1907 { "int_err", VC_INTERR
, },
1908 { "bus_err", VC_BUSERR
, },
1909 { "state_err", VC_STATERR
, },
1910 { "chk_err", VC_CHKERR
, },
1911 { "nocp_err", VC_NOCPERR
, },
1912 { "mm_err", VC_MMERR
, },
1913 { "reset", VC_CORERESET
, },
1916 COMMAND_HANDLER(handle_cortex_m3_vector_catch_command
)
1918 struct target
*target
= get_current_target(CMD_CTX
);
1919 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1920 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
1921 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1925 retval
= cortex_m3_verify_pointer(CMD_CTX
, cortex_m3
);
1926 if (retval
!= ERROR_OK
)
1929 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &demcr
);
1934 if (CMD_ARGC
== 1) {
1935 if (strcmp(CMD_ARGV
[0], "all") == 0) {
1936 catch = VC_HARDERR
| VC_INTERR
| VC_BUSERR
1937 | VC_STATERR
| VC_CHKERR
| VC_NOCPERR
1938 | VC_MMERR
| VC_CORERESET
;
1940 } else if (strcmp(CMD_ARGV
[0], "none") == 0) {
1944 while (CMD_ARGC
-- > 0) {
1946 for (i
= 0; i
< ARRAY_SIZE(vec_ids
); i
++) {
1947 if (strcmp(CMD_ARGV
[CMD_ARGC
], vec_ids
[i
].name
) != 0)
1949 catch |= vec_ids
[i
].mask
;
1952 if (i
== ARRAY_SIZE(vec_ids
)) {
1953 LOG_ERROR("No CM3 vector '%s'", CMD_ARGV
[CMD_ARGC
]);
1954 return ERROR_INVALID_ARGUMENTS
;
1958 /* For now, armv7m->demcr only stores vector catch flags. */
1959 armv7m
->demcr
= catch;
1964 /* write, but don't assume it stuck (why not??) */
1965 mem_ap_write_u32(swjdp
, DCB_DEMCR
, demcr
);
1966 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &demcr
);
1968 /* FIXME be sure to clear DEMCR on clean server shutdown.
1969 * Otherwise the vector catch hardware could fire when there's
1970 * no debugger hooked up, causing much confusion...
1974 for (unsigned i
= 0; i
< ARRAY_SIZE(vec_ids
); i
++)
1976 command_print(CMD_CTX
, "%9s: %s", vec_ids
[i
].name
,
1977 (demcr
& vec_ids
[i
].mask
) ? "catch" : "ignore");
1983 COMMAND_HANDLER(handle_cortex_m3_mask_interrupts_command
)
1985 struct target
*target
= get_current_target(CMD_CTX
);
1986 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1989 retval
= cortex_m3_verify_pointer(CMD_CTX
, cortex_m3
);
1990 if (retval
!= ERROR_OK
)
1993 if (target
->state
!= TARGET_HALTED
)
1995 command_print(CMD_CTX
, "target must be stopped for \"%s\" command", CMD_NAME
);
2002 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], enable
);
2003 uint32_t mask_on
= C_HALT
| (enable
? C_MASKINTS
: 0);
2004 uint32_t mask_off
= enable
? 0 : C_MASKINTS
;
2005 cortex_m3_write_debug_halt_mask(target
, mask_on
, mask_off
);
2008 command_print(CMD_CTX
, "cortex_m3 interrupt mask %s",
2009 (cortex_m3
->dcb_dhcsr
& C_MASKINTS
) ? "on" : "off");
2014 static const struct command_registration cortex_m3_exec_command_handlers
[] = {
2017 .handler
= handle_cortex_m3_mask_interrupts_command
,
2018 .mode
= COMMAND_EXEC
,
2019 .help
= "mask cortex_m3 interrupts",
2020 .usage
= "['on'|'off']",
2023 .name
= "vector_catch",
2024 .handler
= handle_cortex_m3_vector_catch_command
,
2025 .mode
= COMMAND_EXEC
,
2026 .help
= "configure hardware vectors to trigger debug entry",
2027 .usage
= "['all'|'none'|('bus_err'|'chk_err'|...)*]",
2029 COMMAND_REGISTRATION_DONE
2031 static const struct command_registration cortex_m3_command_handlers
[] = {
2033 .chain
= armv7m_command_handlers
,
2036 .name
= "cortex_m3",
2037 .mode
= COMMAND_EXEC
,
2038 .help
= "Cortex-M3 command group",
2039 .chain
= cortex_m3_exec_command_handlers
,
2041 COMMAND_REGISTRATION_DONE
2044 struct target_type cortexm3_target
=
2046 .name
= "cortex_m3",
2048 .poll
= cortex_m3_poll
,
2049 .arch_state
= armv7m_arch_state
,
2051 .target_request_data
= cortex_m3_target_request_data
,
2053 .halt
= cortex_m3_halt
,
2054 .resume
= cortex_m3_resume
,
2055 .step
= cortex_m3_step
,
2057 .assert_reset
= cortex_m3_assert_reset
,
2058 .deassert_reset
= cortex_m3_deassert_reset
,
2059 .soft_reset_halt
= cortex_m3_soft_reset_halt
,
2061 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
2063 .read_memory
= cortex_m3_read_memory
,
2064 .write_memory
= cortex_m3_write_memory
,
2065 .bulk_write_memory
= cortex_m3_bulk_write_memory
,
2066 .checksum_memory
= armv7m_checksum_memory
,
2067 .blank_check_memory
= armv7m_blank_check_memory
,
2069 .run_algorithm
= armv7m_run_algorithm
,
2071 .add_breakpoint
= cortex_m3_add_breakpoint
,
2072 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
2073 .add_watchpoint
= cortex_m3_add_watchpoint
,
2074 .remove_watchpoint
= cortex_m3_remove_watchpoint
,
2076 .commands
= cortex_m3_command_handlers
,
2077 .target_create
= cortex_m3_target_create
,
2078 .init_target
= cortex_m3_init_target
,
2079 .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)