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 swjdp
->trans_mode
= TRANS_MODE_COMPOSITE
;
75 /* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */
76 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRSR
& 0xFFFFFFF0);
77 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRSR
& 0xC), regnum
);
79 /* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */
80 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRDR
& 0xFFFFFFF0);
81 dap_ap_read_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRDR
& 0xC), value
);
83 retval
= swjdp_transaction_endcheck(swjdp
);
85 /* restore DCB_DCRDR - this needs to be in a seperate
86 * transaction otherwise the emulated DCC channel breaks */
87 if (retval
== ERROR_OK
)
88 retval
= mem_ap_write_atomic_u32(swjdp
, DCB_DCRDR
, dcrdr
);
93 static int cortexm3_dap_write_coreregister_u32(struct swjdp_common
*swjdp
,
94 uint32_t value
, int regnum
)
99 /* because the DCB_DCRDR is used for the emulated dcc channel
100 * we have to save/restore the DCB_DCRDR when used */
102 mem_ap_read_u32(swjdp
, DCB_DCRDR
, &dcrdr
);
104 swjdp
->trans_mode
= TRANS_MODE_COMPOSITE
;
106 /* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */
107 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRDR
& 0xFFFFFFF0);
108 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRDR
& 0xC), value
);
110 /* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */
111 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRSR
& 0xFFFFFFF0);
112 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRSR
& 0xC), regnum
| DCRSR_WnR
);
114 retval
= swjdp_transaction_endcheck(swjdp
);
116 /* restore DCB_DCRDR - this needs to be in a seperate
117 * transaction otherwise the emulated DCC channel breaks */
118 if (retval
== ERROR_OK
)
119 retval
= mem_ap_write_atomic_u32(swjdp
, DCB_DCRDR
, dcrdr
);
124 static int cortex_m3_write_debug_halt_mask(struct target
*target
,
125 uint32_t mask_on
, uint32_t mask_off
)
127 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
128 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
130 /* mask off status bits */
131 cortex_m3
->dcb_dhcsr
&= ~((0xFFFF << 16) | mask_off
);
132 /* create new register mask */
133 cortex_m3
->dcb_dhcsr
|= DBGKEY
| C_DEBUGEN
| mask_on
;
135 return mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
, cortex_m3
->dcb_dhcsr
);
138 static int cortex_m3_clear_halt(struct target
*target
)
140 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
141 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
143 /* clear step if any */
144 cortex_m3_write_debug_halt_mask(target
, C_HALT
, C_STEP
);
146 /* Read Debug Fault Status Register */
147 mem_ap_read_atomic_u32(swjdp
, NVIC_DFSR
, &cortex_m3
->nvic_dfsr
);
149 /* Clear Debug Fault Status */
150 mem_ap_write_atomic_u32(swjdp
, NVIC_DFSR
, cortex_m3
->nvic_dfsr
);
151 LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32
"", cortex_m3
->nvic_dfsr
);
156 static int cortex_m3_single_step_core(struct target
*target
)
158 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
159 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
162 /* backup dhcsr reg */
163 dhcsr_save
= cortex_m3
->dcb_dhcsr
;
165 /* Mask interrupts before clearing halt, if done already. This avoids
166 * Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
167 * HALT can put the core into an unknown state.
169 if (!(cortex_m3
->dcb_dhcsr
& C_MASKINTS
))
170 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
,
171 DBGKEY
| C_MASKINTS
| C_HALT
| C_DEBUGEN
);
172 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
,
173 DBGKEY
| C_MASKINTS
| C_STEP
| C_DEBUGEN
);
176 /* restore dhcsr reg */
177 cortex_m3
->dcb_dhcsr
= dhcsr_save
;
178 cortex_m3_clear_halt(target
);
183 static int cortex_m3_endreset_event(struct target
*target
)
187 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
188 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
189 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
190 struct cortex_m3_fp_comparator
*fp_list
= cortex_m3
->fp_comparator_list
;
191 struct cortex_m3_dwt_comparator
*dwt_list
= cortex_m3
->dwt_comparator_list
;
193 /* REVISIT The four debug monitor bits are currently ignored... */
194 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &dcb_demcr
);
195 LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32
"",dcb_demcr
);
197 /* this register is used for emulated dcc channel */
198 mem_ap_write_u32(swjdp
, DCB_DCRDR
, 0);
200 /* Enable debug requests */
201 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
202 if (!(cortex_m3
->dcb_dhcsr
& C_DEBUGEN
))
203 mem_ap_write_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_DEBUGEN
);
205 /* clear any interrupt masking */
206 cortex_m3_write_debug_halt_mask(target
, 0, C_MASKINTS
);
208 /* Enable features controlled by ITM and DWT blocks, and catch only
209 * the vectors we were told to pay attention to.
211 * Target firmware is responsible for all fault handling policy
212 * choices *EXCEPT* explicitly scripted overrides like "vector_catch"
213 * or manual updates to the NVIC SHCSR and CCR registers.
215 mem_ap_write_u32(swjdp
, DCB_DEMCR
, TRCENA
| armv7m
->demcr
);
217 /* Paranoia: evidently some (early?) chips don't preserve all the
218 * debug state (including FBP, DWT, etc) across reset...
222 target_write_u32(target
, FP_CTRL
, 3);
223 cortex_m3
->fpb_enabled
= 1;
225 /* Restore FPB registers */
226 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++)
228 target_write_u32(target
, fp_list
[i
].fpcr_address
, fp_list
[i
].fpcr_value
);
231 /* Restore DWT registers */
232 for (i
= 0; i
< cortex_m3
->dwt_num_comp
; i
++)
234 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 0,
236 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 4,
238 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 8,
239 dwt_list
[i
].function
);
241 swjdp_transaction_endcheck(swjdp
);
243 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
245 /* make sure we have latest dhcsr flags */
246 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
251 static int cortex_m3_examine_debug_reason(struct target
*target
)
253 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
255 /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
256 /* only check the debug reason if we don't know it already */
258 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
259 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
))
261 if (cortex_m3
->nvic_dfsr
& DFSR_BKPT
)
263 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
264 if (cortex_m3
->nvic_dfsr
& DFSR_DWTTRAP
)
265 target
->debug_reason
= DBG_REASON_WPTANDBKPT
;
267 else if (cortex_m3
->nvic_dfsr
& DFSR_DWTTRAP
)
268 target
->debug_reason
= DBG_REASON_WATCHPOINT
;
269 else if (cortex_m3
->nvic_dfsr
& DFSR_VCATCH
)
270 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
271 else /* EXTERNAL, HALTED */
272 target
->debug_reason
= DBG_REASON_UNDEFINED
;
278 static int cortex_m3_examine_exception_reason(struct target
*target
)
280 uint32_t shcsr
, except_sr
, cfsr
= -1, except_ar
= -1;
281 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
282 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
284 mem_ap_read_u32(swjdp
, NVIC_SHCSR
, &shcsr
);
285 switch (armv7m
->exception_number
)
289 case 3: /* Hard Fault */
290 mem_ap_read_atomic_u32(swjdp
, NVIC_HFSR
, &except_sr
);
291 if (except_sr
& 0x40000000)
293 mem_ap_read_u32(swjdp
, NVIC_CFSR
, &cfsr
);
296 case 4: /* Memory Management */
297 mem_ap_read_u32(swjdp
, NVIC_CFSR
, &except_sr
);
298 mem_ap_read_u32(swjdp
, NVIC_MMFAR
, &except_ar
);
300 case 5: /* Bus Fault */
301 mem_ap_read_u32(swjdp
, NVIC_CFSR
, &except_sr
);
302 mem_ap_read_u32(swjdp
, NVIC_BFAR
, &except_ar
);
304 case 6: /* Usage Fault */
305 mem_ap_read_u32(swjdp
, NVIC_CFSR
, &except_sr
);
307 case 11: /* SVCall */
309 case 12: /* Debug Monitor */
310 mem_ap_read_u32(swjdp
, NVIC_DFSR
, &except_sr
);
312 case 14: /* PendSV */
314 case 15: /* SysTick */
320 swjdp_transaction_endcheck(swjdp
);
321 LOG_DEBUG("%s SHCSR 0x%" PRIx32
", SR 0x%" PRIx32
", CFSR 0x%" PRIx32
", AR 0x%" PRIx32
"", armv7m_exception_string(armv7m
->exception_number
), \
322 shcsr
, except_sr
, cfsr
, except_ar
);
326 static int cortex_m3_debug_entry(struct target
*target
)
331 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
332 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
333 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
338 cortex_m3_clear_halt(target
);
339 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
341 if ((retval
= armv7m
->examine_debug_reason(target
)) != ERROR_OK
)
344 /* Examine target state and mode */
345 /* First load register acessible through core debug port*/
346 int num_regs
= armv7m
->core_cache
->num_regs
;
348 for (i
= 0; i
< num_regs
; i
++)
350 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
351 armv7m
->read_core_reg(target
, i
);
354 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
355 xPSR
= buf_get_u32(r
->value
, 0, 32);
357 #ifdef ARMV7_GDB_HACKS
358 /* FIXME this breaks on scan chains with more than one Cortex-M3.
359 * Instead, each CM3 should have its own dummy value...
361 /* copy real xpsr reg for gdb, setting thumb bit */
362 buf_set_u32(armv7m_gdb_dummy_cpsr_value
, 0, 32, xPSR
);
363 buf_set_u32(armv7m_gdb_dummy_cpsr_value
, 5, 1, 1);
364 armv7m_gdb_dummy_cpsr_reg
.valid
= r
->valid
;
365 armv7m_gdb_dummy_cpsr_reg
.dirty
= r
->dirty
;
368 /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
372 cortex_m3_store_core_reg_u32(target
, ARMV7M_REGISTER_CORE_GP
, 16, xPSR
&~ 0xff);
375 /* Are we in an exception handler */
378 armv7m
->core_mode
= ARMV7M_MODE_HANDLER
;
379 armv7m
->exception_number
= (xPSR
& 0x1FF);
383 armv7m
->core_mode
= buf_get_u32(armv7m
->core_cache
384 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 1);
385 armv7m
->exception_number
= 0;
388 if (armv7m
->exception_number
)
390 cortex_m3_examine_exception_reason(target
);
393 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32
", target->state: %s",
394 armv7m_mode_strings
[armv7m
->core_mode
],
395 *(uint32_t*)(armv7m
->core_cache
->reg_list
[15].value
),
396 target_state_name(target
));
398 if (armv7m
->post_debug_entry
)
399 armv7m
->post_debug_entry(target
);
404 static int cortex_m3_poll(struct target
*target
)
407 enum target_state prev_target_state
= target
->state
;
408 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
409 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
411 /* Read from Debug Halting Control and Status Register */
412 retval
= mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
413 if (retval
!= ERROR_OK
)
415 target
->state
= TARGET_UNKNOWN
;
419 if (cortex_m3
->dcb_dhcsr
& S_RESET_ST
)
421 /* check if still in reset */
422 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
424 if (cortex_m3
->dcb_dhcsr
& S_RESET_ST
)
426 target
->state
= TARGET_RESET
;
431 if (target
->state
== TARGET_RESET
)
433 /* Cannot switch context while running so endreset is
434 * called with target->state == TARGET_RESET
436 LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32
,
437 cortex_m3
->dcb_dhcsr
);
438 cortex_m3_endreset_event(target
);
439 target
->state
= TARGET_RUNNING
;
440 prev_target_state
= TARGET_RUNNING
;
443 if (cortex_m3
->dcb_dhcsr
& S_HALT
)
445 target
->state
= TARGET_HALTED
;
447 if ((prev_target_state
== TARGET_RUNNING
) || (prev_target_state
== TARGET_RESET
))
449 if ((retval
= cortex_m3_debug_entry(target
)) != ERROR_OK
)
452 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
454 if (prev_target_state
== TARGET_DEBUG_RUNNING
)
457 if ((retval
= cortex_m3_debug_entry(target
)) != ERROR_OK
)
460 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
464 /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
465 * How best to model low power modes?
468 if (target
->state
== TARGET_UNKNOWN
)
470 /* check if processor is retiring instructions */
471 if (cortex_m3
->dcb_dhcsr
& S_RETIRE_ST
)
473 target
->state
= TARGET_RUNNING
;
481 static int cortex_m3_halt(struct target
*target
)
483 LOG_DEBUG("target->state: %s",
484 target_state_name(target
));
486 if (target
->state
== TARGET_HALTED
)
488 LOG_DEBUG("target was already halted");
492 if (target
->state
== TARGET_UNKNOWN
)
494 LOG_WARNING("target was in unknown state when halt was requested");
497 if (target
->state
== TARGET_RESET
)
499 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST
) && jtag_get_srst())
501 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
502 return ERROR_TARGET_FAILURE
;
506 /* we came here in a reset_halt or reset_init sequence
507 * debug entry was already prepared in cortex_m3_prepare_reset_halt()
509 target
->debug_reason
= DBG_REASON_DBGRQ
;
515 /* Write to Debug Halting Control and Status Register */
516 cortex_m3_write_debug_halt_mask(target
, C_HALT
, 0);
518 target
->debug_reason
= DBG_REASON_DBGRQ
;
523 static int cortex_m3_soft_reset_halt(struct target
*target
)
525 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
526 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
527 uint32_t dcb_dhcsr
= 0;
528 int retval
, timeout
= 0;
530 /* Enter debug state on reset; restore DEMCR in endreset_event() */
531 mem_ap_write_u32(swjdp
, DCB_DEMCR
,
532 TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
534 /* Request a core-only reset */
535 mem_ap_write_atomic_u32(swjdp
, NVIC_AIRCR
,
536 AIRCR_VECTKEY
| AIRCR_VECTRESET
);
537 target
->state
= TARGET_RESET
;
539 /* registers are now invalid */
540 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
542 while (timeout
< 100)
544 retval
= mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &dcb_dhcsr
);
545 if (retval
== ERROR_OK
)
547 mem_ap_read_atomic_u32(swjdp
, NVIC_DFSR
,
548 &cortex_m3
->nvic_dfsr
);
549 if ((dcb_dhcsr
& S_HALT
)
550 && (cortex_m3
->nvic_dfsr
& DFSR_VCATCH
))
552 LOG_DEBUG("system reset-halted, DHCSR 0x%08x, "
554 (unsigned) dcb_dhcsr
,
555 (unsigned) cortex_m3
->nvic_dfsr
);
556 cortex_m3_poll(target
);
557 /* FIXME restore user's vector catch config */
561 LOG_DEBUG("waiting for system reset-halt, "
562 "DHCSR 0x%08x, %d ms",
563 (unsigned) dcb_dhcsr
, timeout
);
572 static void cortex_m3_enable_breakpoints(struct target
*target
)
574 struct breakpoint
*breakpoint
= target
->breakpoints
;
576 /* set any pending breakpoints */
579 if (!breakpoint
->set
)
580 cortex_m3_set_breakpoint(target
, breakpoint
);
581 breakpoint
= breakpoint
->next
;
585 static int cortex_m3_resume(struct target
*target
, int current
,
586 uint32_t address
, int handle_breakpoints
, int debug_execution
)
588 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
589 struct breakpoint
*breakpoint
= NULL
;
593 if (target
->state
!= TARGET_HALTED
)
595 LOG_WARNING("target not halted");
596 return ERROR_TARGET_NOT_HALTED
;
599 if (!debug_execution
)
601 target_free_all_working_areas(target
);
602 cortex_m3_enable_breakpoints(target
);
603 cortex_m3_enable_watchpoints(target
);
608 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_PRIMASK
;
610 /* Disable interrupts */
611 /* We disable interrupts in the PRIMASK register instead of
612 * masking with C_MASKINTS. This is probably the same issue
613 * as Cortex-M3 Erratum 377493 (fixed in r1p0): C_MASKINTS
614 * in parallel with disabled interrupts can cause local faults
617 * REVISIT this clearly breaks non-debug execution, since the
618 * PRIMASK register state isn't saved/restored... workaround
619 * by never resuming app code after debug execution.
621 buf_set_u32(r
->value
, 0, 1, 1);
625 /* Make sure we are in Thumb mode */
626 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
627 buf_set_u32(r
->value
, 24, 1, 1);
632 /* current = 1: continue on current pc, otherwise continue at <address> */
633 r
= armv7m
->core_cache
->reg_list
+ 15;
636 buf_set_u32(r
->value
, 0, 32, address
);
641 /* if we halted last time due to a bkpt instruction
642 * then we have to manually step over it, otherwise
643 * the core will break again */
645 if (!breakpoint_find(target
, buf_get_u32(r
->value
, 0, 32))
648 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
651 resume_pc
= buf_get_u32(r
->value
, 0, 32);
653 armv7m_restore_context(target
);
655 /* the front-end may request us not to handle breakpoints */
656 if (handle_breakpoints
)
658 /* Single step past breakpoint at current address */
659 if ((breakpoint
= breakpoint_find(target
, resume_pc
)))
661 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
663 breakpoint
->unique_id
);
664 cortex_m3_unset_breakpoint(target
, breakpoint
);
665 cortex_m3_single_step_core(target
);
666 cortex_m3_set_breakpoint(target
, breakpoint
);
671 cortex_m3_write_debug_halt_mask(target
, 0, C_HALT
);
673 target
->debug_reason
= DBG_REASON_NOTHALTED
;
675 /* registers are now invalid */
676 register_cache_invalidate(armv7m
->core_cache
);
678 if (!debug_execution
)
680 target
->state
= TARGET_RUNNING
;
681 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
682 LOG_DEBUG("target resumed at 0x%" PRIx32
"", resume_pc
);
686 target
->state
= TARGET_DEBUG_RUNNING
;
687 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
688 LOG_DEBUG("target debug resumed at 0x%" PRIx32
"", resume_pc
);
694 /* int irqstepcount = 0; */
695 static int cortex_m3_step(struct target
*target
, int current
,
696 uint32_t address
, int handle_breakpoints
)
698 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
699 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
700 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
701 struct breakpoint
*breakpoint
= NULL
;
702 struct reg
*pc
= armv7m
->core_cache
->reg_list
+ 15;
703 bool bkpt_inst_found
= false;
705 if (target
->state
!= TARGET_HALTED
)
707 LOG_WARNING("target not halted");
708 return ERROR_TARGET_NOT_HALTED
;
711 /* current = 1: continue on current pc, otherwise continue at <address> */
713 buf_set_u32(pc
->value
, 0, 32, address
);
715 /* the front-end may request us not to handle breakpoints */
716 if (handle_breakpoints
) {
717 breakpoint
= breakpoint_find(target
,
718 buf_get_u32(pc
->value
, 0, 32));
720 cortex_m3_unset_breakpoint(target
, breakpoint
);
723 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
725 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
727 armv7m_restore_context(target
);
729 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
731 /* if no bkpt instruction is found at pc then we can perform
732 * a normal step, otherwise we have to manually step over the bkpt
733 * instruction - as such simulate a step */
734 if (bkpt_inst_found
== false)
736 /* set step and clear halt */
737 cortex_m3_write_debug_halt_mask(target
, C_STEP
, C_HALT
);
740 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
742 /* registers are now invalid */
743 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
746 cortex_m3_set_breakpoint(target
, breakpoint
);
748 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
749 " nvic_icsr = 0x%" PRIx32
,
750 cortex_m3
->dcb_dhcsr
, cortex_m3
->nvic_icsr
);
752 cortex_m3_debug_entry(target
);
753 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
755 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
756 " nvic_icsr = 0x%" PRIx32
,
757 cortex_m3
->dcb_dhcsr
, cortex_m3
->nvic_icsr
);
762 static int cortex_m3_assert_reset(struct target
*target
)
764 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
765 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
768 LOG_DEBUG("target->state: %s",
769 target_state_name(target
));
771 enum reset_types jtag_reset_config
= jtag_get_reset_config();
774 * We can reset Cortex-M3 targets using just the NVIC without
775 * requiring SRST, getting a SoC reset (or a core-only reset)
776 * instead of a system reset.
778 if (!(jtag_reset_config
& RESET_HAS_SRST
))
781 /* Enable debug requests */
782 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
783 if (!(cortex_m3
->dcb_dhcsr
& C_DEBUGEN
))
784 mem_ap_write_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_DEBUGEN
);
786 mem_ap_write_u32(swjdp
, DCB_DCRDR
, 0);
788 if (!target
->reset_halt
)
790 /* Set/Clear C_MASKINTS in a separate operation */
791 if (cortex_m3
->dcb_dhcsr
& C_MASKINTS
)
792 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
,
793 DBGKEY
| C_DEBUGEN
| C_HALT
);
795 /* clear any debug flags before resuming */
796 cortex_m3_clear_halt(target
);
798 /* clear C_HALT in dhcsr reg */
799 cortex_m3_write_debug_halt_mask(target
, 0, C_HALT
);
803 /* Halt in debug on reset; endreset_event() restores DEMCR.
805 * REVISIT catching BUSERR presumably helps to defend against
806 * bad vector table entries. Should this include MMERR or
809 mem_ap_write_atomic_u32(swjdp
, DCB_DEMCR
,
810 TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
814 * When nRST is asserted on most Stellaris devices, it clears some of
815 * the debug state. The ARMv7M and Cortex-M3 TRMs say that's wrong;
816 * and OpenOCD depends on those TRMs. So we won't use SRST on those
817 * chips. (Only power-on reset should affect debug state, beyond a
818 * few specified bits; not the chip's nRST input, wired to SRST.)
820 * REVISIT current errata specs don't seem to cover this issue.
821 * Do we have more details than this email?
822 * https://lists.berlios.de/pipermail
823 * /openocd-development/2008-August/003065.html
825 if (strcmp(target
->variant
, "lm3s") == 0)
827 /* Check for silicon revisions with the issue. */
830 if (target_read_u32(target
, 0x400fe000, &did0
) == ERROR_OK
)
832 switch ((did0
>> 16) & 0xff)
835 /* all Sandstorm suffer issue */
841 /* Fury and DustDevil rev A have
842 * this nRST problem. It should
843 * be fixed in rev B silicon.
845 if (((did0
>> 8) & 0xff) == 0)
849 /* Tempest should be fine. */
857 /* default to asserting srst */
858 if (jtag_reset_config
& RESET_SRST_PULLS_TRST
)
860 jtag_add_reset(1, 1);
864 jtag_add_reset(0, 1);
869 /* Use a standard Cortex-M3 software reset mechanism.
870 * SYSRESETREQ will reset SoC peripherals outside the
871 * core, like watchdog timers, if the SoC wires it up
872 * correctly. Else VECRESET can reset just the core.
874 mem_ap_write_atomic_u32(swjdp
, NVIC_AIRCR
,
875 AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
876 LOG_DEBUG("Using Cortex-M3 SYSRESETREQ");
879 /* I do not know why this is necessary, but it
880 * fixes strange effects (step/resume cause NMI
881 * after reset) on LM3S6918 -- Michael Schwingen
884 mem_ap_read_atomic_u32(swjdp
, NVIC_AIRCR
, &tmp
);
888 target
->state
= TARGET_RESET
;
889 jtag_add_sleep(50000);
891 register_cache_invalidate(cortex_m3
->armv7m
.core_cache
);
893 if (target
->reset_halt
)
896 if ((retval
= target_halt(target
)) != ERROR_OK
)
903 static int cortex_m3_deassert_reset(struct target
*target
)
905 LOG_DEBUG("target->state: %s",
906 target_state_name(target
));
908 /* deassert reset lines */
909 jtag_add_reset(0, 0);
915 cortex_m3_set_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
920 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
921 struct cortex_m3_fp_comparator
*comparator_list
= cortex_m3
->fp_comparator_list
;
925 LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint
->unique_id
);
929 if (cortex_m3
->auto_bp_type
)
931 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
934 if (breakpoint
->type
== BKPT_HARD
)
936 while (comparator_list
[fp_num
].used
&& (fp_num
< cortex_m3
->fp_num_code
))
938 if (fp_num
>= cortex_m3
->fp_num_code
)
940 LOG_ERROR("Can not find free FPB Comparator!");
943 breakpoint
->set
= fp_num
+ 1;
944 hilo
= (breakpoint
->address
& 0x2) ? FPCR_REPLACE_BKPT_HIGH
: FPCR_REPLACE_BKPT_LOW
;
945 comparator_list
[fp_num
].used
= 1;
946 comparator_list
[fp_num
].fpcr_value
= (breakpoint
->address
& 0x1FFFFFFC) | hilo
| 1;
947 target_write_u32(target
, comparator_list
[fp_num
].fpcr_address
, comparator_list
[fp_num
].fpcr_value
);
948 LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32
"", fp_num
, comparator_list
[fp_num
].fpcr_value
);
949 if (!cortex_m3
->fpb_enabled
)
951 LOG_DEBUG("FPB wasn't enabled, do it now");
952 target_write_u32(target
, FP_CTRL
, 3);
955 else if (breakpoint
->type
== BKPT_SOFT
)
959 /* NOTE: on ARMv6-M and ARMv7-M, BKPT(0xab) is used for
960 * semihosting; don't use that. Otherwise the BKPT
961 * parameter is arbitrary.
963 buf_set_u32(code
, 0, 32, ARMV5_T_BKPT(0x11));
964 retval
= target_read_memory(target
,
965 breakpoint
->address
& 0xFFFFFFFE,
966 breakpoint
->length
, 1,
967 breakpoint
->orig_instr
);
968 if (retval
!= ERROR_OK
)
970 retval
= target_write_memory(target
,
971 breakpoint
->address
& 0xFFFFFFFE,
972 breakpoint
->length
, 1,
974 if (retval
!= ERROR_OK
)
976 breakpoint
->set
= true;
979 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32
" Length: %d (set=%d)",
980 breakpoint
->unique_id
,
981 (int)(breakpoint
->type
),
990 cortex_m3_unset_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
993 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
994 struct cortex_m3_fp_comparator
* comparator_list
= cortex_m3
->fp_comparator_list
;
996 if (!breakpoint
->set
)
998 LOG_WARNING("breakpoint not set");
1002 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32
" Length: %d (set=%d)",
1003 breakpoint
->unique_id
,
1004 (int)(breakpoint
->type
),
1005 breakpoint
->address
,
1009 if (breakpoint
->type
== BKPT_HARD
)
1011 int fp_num
= breakpoint
->set
- 1;
1012 if ((fp_num
< 0) || (fp_num
>= cortex_m3
->fp_num_code
))
1014 LOG_DEBUG("Invalid FP Comparator number in breakpoint");
1017 comparator_list
[fp_num
].used
= 0;
1018 comparator_list
[fp_num
].fpcr_value
= 0;
1019 target_write_u32(target
, comparator_list
[fp_num
].fpcr_address
, comparator_list
[fp_num
].fpcr_value
);
1023 /* restore original instruction (kept in target endianness) */
1024 if (breakpoint
->length
== 4)
1026 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, 4, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
1033 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, 2, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
1039 breakpoint
->set
= false;
1045 cortex_m3_add_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1047 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1049 if (cortex_m3
->auto_bp_type
)
1051 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
1052 #ifdef ARMV7_GDB_HACKS
1053 if (breakpoint
->length
!= 2) {
1054 /* XXX Hack: Replace all breakpoints with length != 2 with
1055 * a hardware breakpoint. */
1056 breakpoint
->type
= BKPT_HARD
;
1057 breakpoint
->length
= 2;
1062 if ((breakpoint
->type
== BKPT_HARD
) && (breakpoint
->address
>= 0x20000000))
1064 LOG_INFO("flash patch comparator requested outside code memory region");
1065 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1068 if ((breakpoint
->type
== BKPT_SOFT
) && (breakpoint
->address
< 0x20000000))
1070 LOG_INFO("soft breakpoint requested in code (flash) memory region");
1071 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1074 if ((breakpoint
->type
== BKPT_HARD
) && (cortex_m3
->fp_code_available
< 1))
1076 LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
1077 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1080 if ((breakpoint
->length
!= 2))
1082 LOG_INFO("only breakpoints of two bytes length supported");
1083 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1086 if (breakpoint
->type
== BKPT_HARD
)
1087 cortex_m3
->fp_code_available
--;
1088 cortex_m3_set_breakpoint(target
, breakpoint
);
1094 cortex_m3_remove_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1096 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1098 /* REVISIT why check? FBP can be updated with core running ... */
1099 if (target
->state
!= TARGET_HALTED
)
1101 LOG_WARNING("target not halted");
1102 return ERROR_TARGET_NOT_HALTED
;
1105 if (cortex_m3
->auto_bp_type
)
1107 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
1110 if (breakpoint
->set
)
1112 cortex_m3_unset_breakpoint(target
, breakpoint
);
1115 if (breakpoint
->type
== BKPT_HARD
)
1116 cortex_m3
->fp_code_available
++;
1122 cortex_m3_set_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1125 uint32_t mask
, temp
;
1126 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1128 /* watchpoint params were validated earlier */
1130 temp
= watchpoint
->length
;
1137 /* REVISIT Don't fully trust these "not used" records ... users
1138 * may set up breakpoints by hand, e.g. dual-address data value
1139 * watchpoint using comparator #1; comparator #0 matching cycle
1140 * count; send data trace info through ITM and TPIU; etc
1142 struct cortex_m3_dwt_comparator
*comparator
;
1144 for (comparator
= cortex_m3
->dwt_comparator_list
;
1145 comparator
->used
&& dwt_num
< cortex_m3
->dwt_num_comp
;
1146 comparator
++, dwt_num
++)
1148 if (dwt_num
>= cortex_m3
->dwt_num_comp
)
1150 LOG_ERROR("Can not find free DWT Comparator");
1153 comparator
->used
= 1;
1154 watchpoint
->set
= dwt_num
+ 1;
1156 comparator
->comp
= watchpoint
->address
;
1157 target_write_u32(target
, comparator
->dwt_comparator_address
+ 0,
1160 comparator
->mask
= mask
;
1161 target_write_u32(target
, comparator
->dwt_comparator_address
+ 4,
1164 switch (watchpoint
->rw
) {
1166 comparator
->function
= 5;
1169 comparator
->function
= 6;
1172 comparator
->function
= 7;
1175 target_write_u32(target
, comparator
->dwt_comparator_address
+ 8,
1176 comparator
->function
);
1178 LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x",
1179 watchpoint
->unique_id
, dwt_num
,
1180 (unsigned) comparator
->comp
,
1181 (unsigned) comparator
->mask
,
1182 (unsigned) comparator
->function
);
1187 cortex_m3_unset_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1189 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1190 struct cortex_m3_dwt_comparator
*comparator
;
1193 if (!watchpoint
->set
)
1195 LOG_WARNING("watchpoint (wpid: %d) not set",
1196 watchpoint
->unique_id
);
1200 dwt_num
= watchpoint
->set
- 1;
1202 LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
1203 watchpoint
->unique_id
, dwt_num
,
1204 (unsigned) watchpoint
->address
);
1206 if ((dwt_num
< 0) || (dwt_num
>= cortex_m3
->dwt_num_comp
))
1208 LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
1212 comparator
= cortex_m3
->dwt_comparator_list
+ dwt_num
;
1213 comparator
->used
= 0;
1214 comparator
->function
= 0;
1215 target_write_u32(target
, comparator
->dwt_comparator_address
+ 8,
1216 comparator
->function
);
1218 watchpoint
->set
= false;
1224 cortex_m3_add_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1226 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1228 if (cortex_m3
->dwt_comp_available
< 1)
1230 LOG_DEBUG("no comparators?");
1231 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1234 /* hardware doesn't support data value masking */
1235 if (watchpoint
->mask
!= ~(uint32_t)0) {
1236 LOG_DEBUG("watchpoint value masks not supported");
1237 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1240 /* hardware allows address masks of up to 32K */
1243 for (mask
= 0; mask
< 16; mask
++) {
1244 if ((1u << mask
) == watchpoint
->length
)
1248 LOG_DEBUG("unsupported watchpoint length");
1249 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1251 if (watchpoint
->address
& ((1 << mask
) - 1)) {
1252 LOG_DEBUG("watchpoint address is unaligned");
1253 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1256 /* Caller doesn't seem to be able to describe watching for data
1257 * values of zero; that flags "no value".
1259 * REVISIT This DWT may well be able to watch for specific data
1260 * values. Requires comparator #1 to set DATAVMATCH and match
1261 * the data, and another comparator (DATAVADDR0) matching addr.
1263 if (watchpoint
->value
) {
1264 LOG_DEBUG("data value watchpoint not YET supported");
1265 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1268 cortex_m3
->dwt_comp_available
--;
1269 LOG_DEBUG("dwt_comp_available: %d", cortex_m3
->dwt_comp_available
);
1275 cortex_m3_remove_watchpoint(struct target
*target
, struct watchpoint
*watchpoint
)
1277 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1279 /* REVISIT why check? DWT can be updated with core running ... */
1280 if (target
->state
!= TARGET_HALTED
)
1282 LOG_WARNING("target not halted");
1283 return ERROR_TARGET_NOT_HALTED
;
1286 if (watchpoint
->set
)
1288 cortex_m3_unset_watchpoint(target
, watchpoint
);
1291 cortex_m3
->dwt_comp_available
++;
1292 LOG_DEBUG("dwt_comp_available: %d", cortex_m3
->dwt_comp_available
);
1297 static void cortex_m3_enable_watchpoints(struct target
*target
)
1299 struct watchpoint
*watchpoint
= target
->watchpoints
;
1301 /* set any pending watchpoints */
1304 if (!watchpoint
->set
)
1305 cortex_m3_set_watchpoint(target
, watchpoint
);
1306 watchpoint
= watchpoint
->next
;
1310 static int cortex_m3_load_core_reg_u32(struct target
*target
,
1311 enum armv7m_regtype type
, uint32_t num
, uint32_t * value
)
1314 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1315 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1317 /* NOTE: we "know" here that the register identifiers used
1318 * in the v7m header match the Cortex-M3 Debug Core Register
1319 * Selector values for R0..R15, xPSR, MSP, and PSP.
1323 /* read a normal core register */
1324 retval
= cortexm3_dap_read_coreregister_u32(swjdp
, value
, num
);
1326 if (retval
!= ERROR_OK
)
1328 LOG_ERROR("JTAG failure %i",retval
);
1329 return ERROR_JTAG_DEVICE_ERROR
;
1331 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"",(int)num
,*value
);
1334 case ARMV7M_PRIMASK
:
1335 case ARMV7M_BASEPRI
:
1336 case ARMV7M_FAULTMASK
:
1337 case ARMV7M_CONTROL
:
1338 /* Cortex-M3 packages these four registers as bitfields
1339 * in one Debug Core register. So say r0 and r2 docs;
1340 * it was removed from r1 docs, but still works.
1342 cortexm3_dap_read_coreregister_u32(swjdp
, value
, 20);
1346 case ARMV7M_PRIMASK
:
1347 *value
= buf_get_u32((uint8_t*)value
, 0, 1);
1350 case ARMV7M_BASEPRI
:
1351 *value
= buf_get_u32((uint8_t*)value
, 8, 8);
1354 case ARMV7M_FAULTMASK
:
1355 *value
= buf_get_u32((uint8_t*)value
, 16, 1);
1358 case ARMV7M_CONTROL
:
1359 *value
= buf_get_u32((uint8_t*)value
, 24, 2);
1363 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"", (int)num
, *value
);
1367 return ERROR_INVALID_ARGUMENTS
;
1373 static int cortex_m3_store_core_reg_u32(struct target
*target
,
1374 enum armv7m_regtype type
, uint32_t num
, uint32_t value
)
1378 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1379 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1381 #ifdef ARMV7_GDB_HACKS
1382 /* If the LR register is being modified, make sure it will put us
1383 * in "thumb" mode, or an INVSTATE exception will occur. This is a
1384 * hack to deal with the fact that gdb will sometimes "forge"
1385 * return addresses, and doesn't set the LSB correctly (i.e., when
1386 * printing expressions containing function calls, it sets LR = 0.)
1387 * Valid exception return codes have bit 0 set too.
1389 if (num
== ARMV7M_R14
)
1393 /* NOTE: we "know" here that the register identifiers used
1394 * in the v7m header match the Cortex-M3 Debug Core Register
1395 * Selector values for R0..R15, xPSR, MSP, and PSP.
1399 retval
= cortexm3_dap_write_coreregister_u32(swjdp
, value
, num
);
1400 if (retval
!= ERROR_OK
)
1404 LOG_ERROR("JTAG failure %i", retval
);
1405 r
= armv7m
->core_cache
->reg_list
+ num
;
1406 r
->dirty
= r
->valid
;
1407 return ERROR_JTAG_DEVICE_ERROR
;
1409 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
1412 case ARMV7M_PRIMASK
:
1413 case ARMV7M_BASEPRI
:
1414 case ARMV7M_FAULTMASK
:
1415 case ARMV7M_CONTROL
:
1416 /* Cortex-M3 packages these four registers as bitfields
1417 * in one Debug Core register. So say r0 and r2 docs;
1418 * it was removed from r1 docs, but still works.
1420 cortexm3_dap_read_coreregister_u32(swjdp
, ®
, 20);
1424 case ARMV7M_PRIMASK
:
1425 buf_set_u32((uint8_t*)®
, 0, 1, value
);
1428 case ARMV7M_BASEPRI
:
1429 buf_set_u32((uint8_t*)®
, 8, 8, value
);
1432 case ARMV7M_FAULTMASK
:
1433 buf_set_u32((uint8_t*)®
, 16, 1, value
);
1436 case ARMV7M_CONTROL
:
1437 buf_set_u32((uint8_t*)®
, 24, 2, value
);
1441 cortexm3_dap_write_coreregister_u32(swjdp
, reg
, 20);
1443 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
1447 return ERROR_INVALID_ARGUMENTS
;
1453 static int cortex_m3_read_memory(struct target
*target
, uint32_t address
,
1454 uint32_t size
, uint32_t count
, uint8_t *buffer
)
1456 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1457 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1458 int retval
= ERROR_INVALID_ARGUMENTS
;
1460 /* cortex_m3 handles unaligned memory access */
1461 if (count
&& buffer
) {
1464 retval
= mem_ap_read_buf_u32(swjdp
, buffer
, 4 * count
, address
);
1467 retval
= mem_ap_read_buf_u16(swjdp
, buffer
, 2 * count
, address
);
1470 retval
= mem_ap_read_buf_u8(swjdp
, buffer
, count
, address
);
1478 static int cortex_m3_write_memory(struct target
*target
, uint32_t address
,
1479 uint32_t size
, uint32_t count
, uint8_t *buffer
)
1481 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1482 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1483 int retval
= ERROR_INVALID_ARGUMENTS
;
1485 if (count
&& buffer
) {
1488 retval
= mem_ap_write_buf_u32(swjdp
, buffer
, 4 * count
, address
);
1491 retval
= mem_ap_write_buf_u16(swjdp
, buffer
, 2 * count
, address
);
1494 retval
= mem_ap_write_buf_u8(swjdp
, buffer
, count
, address
);
1502 static int cortex_m3_bulk_write_memory(struct target
*target
, uint32_t address
,
1503 uint32_t count
, uint8_t *buffer
)
1505 return cortex_m3_write_memory(target
, address
, 4, count
, buffer
);
1508 static int cortex_m3_init_target(struct command_context
*cmd_ctx
,
1509 struct target
*target
)
1511 armv7m_build_reg_cache(target
);
1515 /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid"
1516 * on r/w if the core is not running, and clear on resume or reset ... or
1517 * at least, in a post_restore_context() method.
1520 struct dwt_reg_state
{
1521 struct target
*target
;
1523 uint32_t value
; /* scratch/cache */
1526 static int cortex_m3_dwt_get_reg(struct reg
*reg
)
1528 struct dwt_reg_state
*state
= reg
->arch_info
;
1530 return target_read_u32(state
->target
, state
->addr
, &state
->value
);
1533 static int cortex_m3_dwt_set_reg(struct reg
*reg
, uint8_t *buf
)
1535 struct dwt_reg_state
*state
= reg
->arch_info
;
1537 return target_write_u32(state
->target
, state
->addr
,
1538 buf_get_u32(buf
, 0, reg
->size
));
1547 static struct dwt_reg dwt_base_regs
[] = {
1548 { DWT_CTRL
, "dwt_ctrl", 32, },
1549 /* NOTE that Erratum 532314 (fixed r2p0) affects CYCCNT: it wrongly
1550 * increments while the core is asleep.
1552 { DWT_CYCCNT
, "dwt_cyccnt", 32, },
1553 /* plus some 8 bit counters, useful for profiling with TPIU */
1556 static struct dwt_reg dwt_comp
[] = {
1557 #define DWT_COMPARATOR(i) \
1558 { DWT_COMP0 + 0x10 * (i), "dwt_" #i "_comp", 32, }, \
1559 { DWT_MASK0 + 0x10 * (i), "dwt_" #i "_mask", 4, }, \
1560 { DWT_FUNCTION0 + 0x10 * (i), "dwt_" #i "_function", 32, }
1565 #undef DWT_COMPARATOR
1568 static const struct reg_arch_type dwt_reg_type
= {
1569 .get
= cortex_m3_dwt_get_reg
,
1570 .set
= cortex_m3_dwt_set_reg
,
1574 cortex_m3_dwt_addreg(struct target
*t
, struct reg
*r
, struct dwt_reg
*d
)
1576 struct dwt_reg_state
*state
;
1578 state
= calloc(1, sizeof *state
);
1581 state
->addr
= d
->addr
;
1586 r
->value
= &state
->value
;
1587 r
->arch_info
= state
;
1588 r
->type
= &dwt_reg_type
;
1592 cortex_m3_dwt_setup(struct cortex_m3_common
*cm3
, struct target
*target
)
1595 struct reg_cache
*cache
;
1596 struct cortex_m3_dwt_comparator
*comparator
;
1599 target_read_u32(target
, DWT_CTRL
, &dwtcr
);
1601 LOG_DEBUG("no DWT");
1605 cm3
->dwt_num_comp
= (dwtcr
>> 28) & 0xF;
1606 cm3
->dwt_comp_available
= cm3
->dwt_num_comp
;
1607 cm3
->dwt_comparator_list
= calloc(cm3
->dwt_num_comp
,
1608 sizeof(struct cortex_m3_dwt_comparator
));
1609 if (!cm3
->dwt_comparator_list
) {
1611 cm3
->dwt_num_comp
= 0;
1612 LOG_ERROR("out of mem");
1616 cache
= calloc(1, sizeof *cache
);
1619 free(cm3
->dwt_comparator_list
);
1622 cache
->name
= "cortex-m3 dwt registers";
1623 cache
->num_regs
= 2 + cm3
->dwt_num_comp
* 3;
1624 cache
->reg_list
= calloc(cache
->num_regs
, sizeof *cache
->reg_list
);
1625 if (!cache
->reg_list
) {
1630 for (reg
= 0; reg
< 2; reg
++)
1631 cortex_m3_dwt_addreg(target
, cache
->reg_list
+ reg
,
1632 dwt_base_regs
+ reg
);
1634 comparator
= cm3
->dwt_comparator_list
;
1635 for (i
= 0; i
< cm3
->dwt_num_comp
; i
++, comparator
++) {
1638 comparator
->dwt_comparator_address
= DWT_COMP0
+ 0x10 * i
;
1639 for (j
= 0; j
< 3; j
++, reg
++)
1640 cortex_m3_dwt_addreg(target
, cache
->reg_list
+ reg
,
1641 dwt_comp
+ 3 * i
+ j
);
1644 *register_get_last_cache_p(&target
->reg_cache
) = cache
;
1645 cm3
->dwt_cache
= cache
;
1647 LOG_DEBUG("DWT dwtcr 0x%" PRIx32
", comp %d, watch%s",
1648 dwtcr
, cm3
->dwt_num_comp
,
1649 (dwtcr
& (0xf << 24)) ? " only" : "/trigger");
1651 /* REVISIT: if num_comp > 1, check whether comparator #1 can
1652 * implement single-address data value watchpoints ... so we
1653 * won't need to check it later, when asked to set one up.
1657 static int cortex_m3_examine(struct target
*target
)
1660 uint32_t cpuid
, fpcr
;
1662 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1663 struct swjdp_common
*swjdp
= &cortex_m3
->armv7m
.swjdp_info
;
1665 if ((retval
= ahbap_debugport_init(swjdp
)) != ERROR_OK
)
1668 if (!target_was_examined(target
))
1670 target_set_examined(target
);
1672 /* Read from Device Identification Registers */
1673 retval
= target_read_u32(target
, CPUID
, &cpuid
);
1674 if (retval
!= ERROR_OK
)
1677 if (((cpuid
>> 4) & 0xc3f) == 0xc23)
1678 LOG_DEBUG("Cortex-M3 r%" PRId8
"p%" PRId8
" processor detected",
1679 (uint8_t)((cpuid
>> 20) & 0xf), (uint8_t)((cpuid
>> 0) & 0xf));
1680 LOG_DEBUG("cpuid: 0x%8.8" PRIx32
"", cpuid
);
1682 /* NOTE: FPB and DWT are both optional. */
1685 target_read_u32(target
, FP_CTRL
, &fpcr
);
1686 cortex_m3
->auto_bp_type
= 1;
1687 cortex_m3
->fp_num_code
= ((fpcr
>> 8) & 0x70) | ((fpcr
>> 4) & 0xF); /* bits [14:12] and [7:4] */
1688 cortex_m3
->fp_num_lit
= (fpcr
>> 8) & 0xF;
1689 cortex_m3
->fp_code_available
= cortex_m3
->fp_num_code
;
1690 cortex_m3
->fp_comparator_list
= calloc(cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
, sizeof(struct cortex_m3_fp_comparator
));
1691 cortex_m3
->fpb_enabled
= fpcr
& 1;
1692 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++)
1694 cortex_m3
->fp_comparator_list
[i
].type
= (i
< cortex_m3
->fp_num_code
) ? FPCR_CODE
: FPCR_LITERAL
;
1695 cortex_m3
->fp_comparator_list
[i
].fpcr_address
= FP_COMP0
+ 4 * i
;
1697 LOG_DEBUG("FPB fpcr 0x%" PRIx32
", numcode %i, numlit %i", fpcr
, cortex_m3
->fp_num_code
, cortex_m3
->fp_num_lit
);
1700 cortex_m3_dwt_setup(cortex_m3
, target
);
1702 /* These hardware breakpoints only work for code in flash! */
1703 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
1704 target_name(target
),
1705 cortex_m3
->fp_num_code
,
1706 cortex_m3
->dwt_num_comp
);
1712 static int cortex_m3_dcc_read(struct swjdp_common
*swjdp
, uint8_t *value
, uint8_t *ctrl
)
1716 mem_ap_read_buf_u16(swjdp
, (uint8_t*)&dcrdr
, 1, DCB_DCRDR
);
1717 *ctrl
= (uint8_t)dcrdr
;
1718 *value
= (uint8_t)(dcrdr
>> 8);
1720 LOG_DEBUG("data 0x%x ctrl 0x%x", *value
, *ctrl
);
1722 /* write ack back to software dcc register
1723 * signify we have read data */
1724 if (dcrdr
& (1 << 0))
1727 mem_ap_write_buf_u16(swjdp
, (uint8_t*)&dcrdr
, 1, DCB_DCRDR
);
1733 static int cortex_m3_target_request_data(struct target
*target
,
1734 uint32_t size
, uint8_t *buffer
)
1736 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1737 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1742 for (i
= 0; i
< (size
* 4); i
++)
1744 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1751 static int cortex_m3_handle_target_request(void *priv
)
1753 struct target
*target
= priv
;
1754 if (!target_was_examined(target
))
1756 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
1757 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1759 if (!target
->dbg_msg_enabled
)
1762 if (target
->state
== TARGET_RUNNING
)
1767 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1769 /* check if we have data */
1770 if (ctrl
& (1 << 0))
1774 /* we assume target is quick enough */
1776 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1777 request
|= (data
<< 8);
1778 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1779 request
|= (data
<< 16);
1780 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1781 request
|= (data
<< 24);
1782 target_request(target
, request
);
1789 static int cortex_m3_init_arch_info(struct target
*target
,
1790 struct cortex_m3_common
*cortex_m3
, struct jtag_tap
*tap
)
1793 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
1795 armv7m_init_arch_info(target
, armv7m
);
1797 /* prepare JTAG information for the new target */
1798 cortex_m3
->jtag_info
.tap
= tap
;
1799 cortex_m3
->jtag_info
.scann_size
= 4;
1801 armv7m
->swjdp_info
.dp_select_value
= -1;
1802 armv7m
->swjdp_info
.ap_csw_value
= -1;
1803 armv7m
->swjdp_info
.ap_tar_value
= -1;
1804 armv7m
->swjdp_info
.jtag_info
= &cortex_m3
->jtag_info
;
1805 armv7m
->swjdp_info
.memaccess_tck
= 8;
1806 armv7m
->swjdp_info
.tar_autoincr_block
= (1 << 12); /* Cortex-M3 has 4096 bytes autoincrement range */
1808 /* register arch-specific functions */
1809 armv7m
->examine_debug_reason
= cortex_m3_examine_debug_reason
;
1811 armv7m
->post_debug_entry
= NULL
;
1813 armv7m
->pre_restore_context
= NULL
;
1814 armv7m
->post_restore_context
= NULL
;
1816 armv7m
->load_core_reg_u32
= cortex_m3_load_core_reg_u32
;
1817 armv7m
->store_core_reg_u32
= cortex_m3_store_core_reg_u32
;
1819 target_register_timer_callback(cortex_m3_handle_target_request
, 1, 1, target
);
1821 if ((retval
= arm_jtag_setup_connection(&cortex_m3
->jtag_info
)) != ERROR_OK
)
1829 static int cortex_m3_target_create(struct target
*target
, Jim_Interp
*interp
)
1831 struct cortex_m3_common
*cortex_m3
= calloc(1,sizeof(struct cortex_m3_common
));
1833 cortex_m3
->common_magic
= CORTEX_M3_COMMON_MAGIC
;
1834 cortex_m3_init_arch_info(target
, cortex_m3
, target
->tap
);
1839 /*--------------------------------------------------------------------------*/
1841 static int cortex_m3_verify_pointer(struct command_context
*cmd_ctx
,
1842 struct cortex_m3_common
*cm3
)
1844 if (cm3
->common_magic
!= CORTEX_M3_COMMON_MAGIC
) {
1845 command_print(cmd_ctx
, "target is not a Cortex-M3");
1846 return ERROR_TARGET_INVALID
;
1852 * Only stuff below this line should need to verify that its target
1853 * is a Cortex-M3. Everything else should have indirected through the
1854 * cortexm3_target structure, which is only used with CM3 targets.
1858 * REVISIT Thumb2 disassembly should work for all ARMv7 cores, as well
1859 * as at least ARM-1156T2. The interesting thing about Cortex-M is
1860 * that *only* Thumb2 disassembly matters. There are also some small
1861 * additions to Thumb2 that are specific to ARMv7-M.
1863 COMMAND_HANDLER(handle_cortex_m3_disassemble_command
)
1866 struct target
*target
= get_current_target(CMD_CTX
);
1867 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1869 unsigned long count
= 1;
1870 struct arm_instruction cur_instruction
;
1872 retval
= cortex_m3_verify_pointer(CMD_CTX
, cortex_m3
);
1873 if (retval
!= ERROR_OK
)
1879 COMMAND_PARSE_NUMBER(ulong
, CMD_ARGV
[1], count
);
1882 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
1885 command_print(CMD_CTX
,
1886 "usage: cortex_m3 disassemble <address> [<count>]");
1891 retval
= thumb2_opcode(target
, address
, &cur_instruction
);
1892 if (retval
!= ERROR_OK
)
1894 command_print(CMD_CTX
, "%s", cur_instruction
.text
);
1895 address
+= cur_instruction
.instruction_size
;
1901 static const struct {
1905 { "hard_err", VC_HARDERR
, },
1906 { "int_err", VC_INTERR
, },
1907 { "bus_err", VC_BUSERR
, },
1908 { "state_err", VC_STATERR
, },
1909 { "chk_err", VC_CHKERR
, },
1910 { "nocp_err", VC_NOCPERR
, },
1911 { "mm_err", VC_MMERR
, },
1912 { "reset", VC_CORERESET
, },
1915 COMMAND_HANDLER(handle_cortex_m3_vector_catch_command
)
1917 struct target
*target
= get_current_target(CMD_CTX
);
1918 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1919 struct armv7m_common
*armv7m
= &cortex_m3
->armv7m
;
1920 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
1924 retval
= cortex_m3_verify_pointer(CMD_CTX
, cortex_m3
);
1925 if (retval
!= ERROR_OK
)
1928 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &demcr
);
1933 if (CMD_ARGC
== 1) {
1934 if (strcmp(CMD_ARGV
[0], "all") == 0) {
1935 catch = VC_HARDERR
| VC_INTERR
| VC_BUSERR
1936 | VC_STATERR
| VC_CHKERR
| VC_NOCPERR
1937 | VC_MMERR
| VC_CORERESET
;
1939 } else if (strcmp(CMD_ARGV
[0], "none") == 0) {
1943 while (CMD_ARGC
-- > 0) {
1945 for (i
= 0; i
< ARRAY_SIZE(vec_ids
); i
++) {
1946 if (strcmp(CMD_ARGV
[CMD_ARGC
], vec_ids
[i
].name
) != 0)
1948 catch |= vec_ids
[i
].mask
;
1951 if (i
== ARRAY_SIZE(vec_ids
)) {
1952 LOG_ERROR("No CM3 vector '%s'", CMD_ARGV
[CMD_ARGC
]);
1953 return ERROR_INVALID_ARGUMENTS
;
1957 /* For now, armv7m->demcr only stores vector catch flags. */
1958 armv7m
->demcr
= catch;
1963 /* write, but don't assume it stuck (why not??) */
1964 mem_ap_write_u32(swjdp
, DCB_DEMCR
, demcr
);
1965 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &demcr
);
1967 /* FIXME be sure to clear DEMCR on clean server shutdown.
1968 * Otherwise the vector catch hardware could fire when there's
1969 * no debugger hooked up, causing much confusion...
1973 for (unsigned i
= 0; i
< ARRAY_SIZE(vec_ids
); i
++)
1975 command_print(CMD_CTX
, "%9s: %s", vec_ids
[i
].name
,
1976 (demcr
& vec_ids
[i
].mask
) ? "catch" : "ignore");
1982 COMMAND_HANDLER(handle_cortex_m3_mask_interrupts_command
)
1984 struct target
*target
= get_current_target(CMD_CTX
);
1985 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
1988 retval
= cortex_m3_verify_pointer(CMD_CTX
, cortex_m3
);
1989 if (retval
!= ERROR_OK
)
1992 if (target
->state
!= TARGET_HALTED
)
1994 command_print(CMD_CTX
, "target must be stopped for \"%s\" command", CMD_NAME
);
2001 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], enable
);
2002 uint32_t mask_on
= C_HALT
| (enable
? C_MASKINTS
: 0);
2003 uint32_t mask_off
= enable
? 0 : C_MASKINTS
;
2004 cortex_m3_write_debug_halt_mask(target
, mask_on
, mask_off
);
2007 command_print(CMD_CTX
, "cortex_m3 interrupt mask %s",
2008 (cortex_m3
->dcb_dhcsr
& C_MASKINTS
) ? "on" : "off");
2013 static const struct command_registration cortex_m3_exec_command_handlers
[] = {
2015 .name
= "disassemble",
2016 .handler
= handle_cortex_m3_disassemble_command
,
2017 .mode
= COMMAND_EXEC
,
2018 .help
= "disassemble Thumb2 instructions",
2019 .usage
= "address [count]",
2023 .handler
= handle_cortex_m3_mask_interrupts_command
,
2024 .mode
= COMMAND_EXEC
,
2025 .help
= "mask cortex_m3 interrupts",
2026 .usage
= "['on'|'off']",
2029 .name
= "vector_catch",
2030 .handler
= handle_cortex_m3_vector_catch_command
,
2031 .mode
= COMMAND_EXEC
,
2032 .help
= "configure hardware vectors to trigger debug entry",
2033 .usage
= "['all'|'none'|('bus_err'|'chk_err'|...)*]",
2035 COMMAND_REGISTRATION_DONE
2037 static const struct command_registration cortex_m3_command_handlers
[] = {
2039 .chain
= armv7m_command_handlers
,
2042 .name
= "cortex_m3",
2043 .mode
= COMMAND_EXEC
,
2044 .help
= "Cortex-M3 command group",
2045 .chain
= cortex_m3_exec_command_handlers
,
2047 COMMAND_REGISTRATION_DONE
2050 struct target_type cortexm3_target
=
2052 .name
= "cortex_m3",
2054 .poll
= cortex_m3_poll
,
2055 .arch_state
= armv7m_arch_state
,
2057 .target_request_data
= cortex_m3_target_request_data
,
2059 .halt
= cortex_m3_halt
,
2060 .resume
= cortex_m3_resume
,
2061 .step
= cortex_m3_step
,
2063 .assert_reset
= cortex_m3_assert_reset
,
2064 .deassert_reset
= cortex_m3_deassert_reset
,
2065 .soft_reset_halt
= cortex_m3_soft_reset_halt
,
2067 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
2069 .read_memory
= cortex_m3_read_memory
,
2070 .write_memory
= cortex_m3_write_memory
,
2071 .bulk_write_memory
= cortex_m3_bulk_write_memory
,
2072 .checksum_memory
= armv7m_checksum_memory
,
2073 .blank_check_memory
= armv7m_blank_check_memory
,
2075 .run_algorithm
= armv7m_run_algorithm
,
2077 .add_breakpoint
= cortex_m3_add_breakpoint
,
2078 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
2079 .add_watchpoint
= cortex_m3_add_watchpoint
,
2080 .remove_watchpoint
= cortex_m3_remove_watchpoint
,
2082 .commands
= cortex_m3_command_handlers
,
2083 .target_create
= cortex_m3_target_create
,
2084 .init_target
= cortex_m3_init_target
,
2085 .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)