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 "cortex_m3.h"
35 #include "target_request.h"
36 #include "target_type.h"
37 #include "arm_disassembler.h"
40 #define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0])))
43 /* forward declarations */
44 static int cortex_m3_set_breakpoint(struct target_s
*target
, breakpoint_t
*breakpoint
);
45 static int cortex_m3_unset_breakpoint(struct target_s
*target
, breakpoint_t
*breakpoint
);
46 static void cortex_m3_enable_watchpoints(struct target_s
*target
);
47 static int cortex_m3_store_core_reg_u32(target_t
*target
,
48 enum armv7m_regtype type
, uint32_t num
, uint32_t value
);
50 #ifdef ARMV7_GDB_HACKS
51 extern uint8_t armv7m_gdb_dummy_cpsr_value
[];
52 extern reg_t armv7m_gdb_dummy_cpsr_reg
;
55 static int cortex_m3_has_mmu(struct target_s
*target
, bool *has_mmu
)
61 static int cortexm3_dap_read_coreregister_u32(swjdp_common_t
*swjdp
,
62 uint32_t *value
, int regnum
)
67 /* because the DCB_DCRDR is used for the emulated dcc channel
68 * we have to save/restore the DCB_DCRDR when used */
70 mem_ap_read_u32(swjdp
, DCB_DCRDR
, &dcrdr
);
72 swjdp
->trans_mode
= TRANS_MODE_COMPOSITE
;
74 /* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */
75 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRSR
& 0xFFFFFFF0);
76 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRSR
& 0xC), regnum
);
78 /* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */
79 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRDR
& 0xFFFFFFF0);
80 dap_ap_read_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRDR
& 0xC), value
);
82 retval
= swjdp_transaction_endcheck(swjdp
);
84 /* restore DCB_DCRDR - this needs to be in a seperate
85 * transaction otherwise the emulated DCC channel breaks */
86 if (retval
== ERROR_OK
)
87 retval
= mem_ap_write_atomic_u32(swjdp
, DCB_DCRDR
, dcrdr
);
92 static int cortexm3_dap_write_coreregister_u32(swjdp_common_t
*swjdp
,
93 uint32_t value
, int regnum
)
98 /* because the DCB_DCRDR is used for the emulated dcc channel
99 * we have to save/restore the DCB_DCRDR when used */
101 mem_ap_read_u32(swjdp
, DCB_DCRDR
, &dcrdr
);
103 swjdp
->trans_mode
= TRANS_MODE_COMPOSITE
;
105 /* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */
106 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRDR
& 0xFFFFFFF0);
107 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRDR
& 0xC), value
);
109 /* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */
110 dap_setup_accessport(swjdp
, CSW_32BIT
| CSW_ADDRINC_OFF
, DCB_DCRSR
& 0xFFFFFFF0);
111 dap_ap_write_reg_u32(swjdp
, AP_REG_BD0
| (DCB_DCRSR
& 0xC), regnum
| DCRSR_WnR
);
113 retval
= swjdp_transaction_endcheck(swjdp
);
115 /* restore DCB_DCRDR - this needs to be in a seperate
116 * transaction otherwise the emulated DCC channel breaks */
117 if (retval
== ERROR_OK
)
118 retval
= mem_ap_write_atomic_u32(swjdp
, DCB_DCRDR
, dcrdr
);
123 static int cortex_m3_write_debug_halt_mask(target_t
*target
,
124 uint32_t mask_on
, uint32_t mask_off
)
126 /* get pointers to arch-specific information */
127 armv7m_common_t
*armv7m
= target
->arch_info
;
128 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
129 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
131 /* mask off status bits */
132 cortex_m3
->dcb_dhcsr
&= ~((0xFFFF << 16) | mask_off
);
133 /* create new register mask */
134 cortex_m3
->dcb_dhcsr
|= DBGKEY
| C_DEBUGEN
| mask_on
;
136 return mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
, cortex_m3
->dcb_dhcsr
);
139 static int cortex_m3_clear_halt(target_t
*target
)
141 /* get pointers to arch-specific information */
142 armv7m_common_t
*armv7m
= target
->arch_info
;
143 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
144 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
146 /* clear step if any */
147 cortex_m3_write_debug_halt_mask(target
, C_HALT
, C_STEP
);
149 /* Read Debug Fault Status Register */
150 mem_ap_read_atomic_u32(swjdp
, NVIC_DFSR
, &cortex_m3
->nvic_dfsr
);
151 /* Clear Debug Fault Status */
152 mem_ap_write_atomic_u32(swjdp
, NVIC_DFSR
, cortex_m3
->nvic_dfsr
);
153 LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32
"", cortex_m3
->nvic_dfsr
);
158 static int cortex_m3_single_step_core(target_t
*target
)
160 /* get pointers to arch-specific information */
161 armv7m_common_t
*armv7m
= target
->arch_info
;
162 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
163 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
166 /* backup dhcsr reg */
167 dhcsr_save
= cortex_m3
->dcb_dhcsr
;
169 /* mask interrupts if not done already */
170 if (!(cortex_m3
->dcb_dhcsr
& C_MASKINTS
))
171 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_MASKINTS
| C_HALT
| C_DEBUGEN
);
172 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_MASKINTS
| C_STEP
| C_DEBUGEN
);
175 /* restore dhcsr reg */
176 cortex_m3
->dcb_dhcsr
= dhcsr_save
;
177 cortex_m3_clear_halt(target
);
182 static int cortex_m3_endreset_event(target_t
*target
)
187 /* get pointers to arch-specific information */
188 armv7m_common_t
*armv7m
= target
->arch_info
;
189 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
190 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
191 cortex_m3_fp_comparator_t
*fp_list
= cortex_m3
->fp_comparator_list
;
192 cortex_m3_dwt_comparator_t
*dwt_list
= cortex_m3
->dwt_comparator_list
;
194 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &dcb_demcr
);
195 LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32
"",dcb_demcr
);
197 /* this regsiter 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 trace and dwt */
209 mem_ap_write_u32(swjdp
, DCB_DEMCR
, TRCENA
| VC_HARDERR
| VC_BUSERR
);
210 /* Monitor bus faults */
211 mem_ap_write_u32(swjdp
, NVIC_SHCSR
, SHCSR_BUSFAULTENA
);
214 target_write_u32(target
, FP_CTRL
, 3);
215 cortex_m3
->fpb_enabled
= 1;
217 /* Restore FPB registers */
218 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++)
220 target_write_u32(target
, fp_list
[i
].fpcr_address
, fp_list
[i
].fpcr_value
);
223 /* Restore DWT registers */
224 for (i
= 0; i
< cortex_m3
->dwt_num_comp
; i
++)
226 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 0,
228 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 4,
230 target_write_u32(target
, dwt_list
[i
].dwt_comparator_address
+ 8,
231 dwt_list
[i
].function
);
233 swjdp_transaction_endcheck(swjdp
);
235 armv7m_invalidate_core_regs(target
);
237 /* make sure we have latest dhcsr flags */
238 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
243 static int cortex_m3_examine_debug_reason(target_t
*target
)
245 /* get pointers to arch-specific information */
246 armv7m_common_t
*armv7m
= target
->arch_info
;
247 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
249 /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
250 /* only check the debug reason if we don't know it already */
252 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
253 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
))
255 if (cortex_m3
->nvic_dfsr
& DFSR_BKPT
)
257 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
258 if (cortex_m3
->nvic_dfsr
& DFSR_DWTTRAP
)
259 target
->debug_reason
= DBG_REASON_WPTANDBKPT
;
261 else if (cortex_m3
->nvic_dfsr
& DFSR_DWTTRAP
)
262 target
->debug_reason
= DBG_REASON_WATCHPOINT
;
263 else if (cortex_m3
->nvic_dfsr
& DFSR_VCATCH
)
264 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
265 else /* EXTERNAL, HALTED */
266 target
->debug_reason
= DBG_REASON_UNDEFINED
;
272 static int cortex_m3_examine_exception_reason(target_t
*target
)
274 uint32_t shcsr
, except_sr
, cfsr
= -1, except_ar
= -1;
276 /* get pointers to arch-specific information */
277 armv7m_common_t
*armv7m
= target
->arch_info
;
278 swjdp_common_t
*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 swjdp_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 static int cortex_m3_debug_entry(target_t
*target
)
328 /* get pointers to arch-specific information */
329 armv7m_common_t
*armv7m
= target
->arch_info
;
330 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
331 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
335 cortex_m3_clear_halt(target
);
336 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
338 if ((retval
= armv7m
->examine_debug_reason(target
)) != ERROR_OK
)
341 /* Examine target state and mode */
342 /* First load register acessible through core debug port*/
343 int num_regs
= armv7m
->core_cache
->num_regs
;
345 for (i
= 0; i
< num_regs
; i
++)
347 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
348 armv7m
->read_core_reg(target
, i
);
351 xPSR
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].value
, 0, 32);
353 #ifdef ARMV7_GDB_HACKS
354 /* copy real xpsr reg for gdb, setting thumb bit */
355 buf_set_u32(armv7m_gdb_dummy_cpsr_value
, 0, 32, xPSR
);
356 buf_set_u32(armv7m_gdb_dummy_cpsr_value
, 5, 1, 1);
357 armv7m_gdb_dummy_cpsr_reg
.valid
= armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].valid
;
358 armv7m_gdb_dummy_cpsr_reg
.dirty
= armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].dirty
;
361 /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
364 armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].dirty
= armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].valid
;
365 cortex_m3_store_core_reg_u32(target
, ARMV7M_REGISTER_CORE_GP
, 16, xPSR
&~ 0xff);
368 /* Are we in an exception handler */
371 armv7m
->core_mode
= ARMV7M_MODE_HANDLER
;
372 armv7m
->exception_number
= (xPSR
& 0x1FF);
376 armv7m
->core_mode
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
, 0, 1);
377 armv7m
->exception_number
= 0;
380 if (armv7m
->exception_number
)
382 cortex_m3_examine_exception_reason(target
);
385 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32
", target->state: %s",
386 armv7m_mode_strings
[armv7m
->core_mode
],
387 *(uint32_t*)(armv7m
->core_cache
->reg_list
[15].value
),
388 target_state_name(target
));
390 if (armv7m
->post_debug_entry
)
391 armv7m
->post_debug_entry(target
);
396 static int cortex_m3_poll(target_t
*target
)
399 enum target_state prev_target_state
= target
->state
;
401 /* get pointers to arch-specific information */
402 armv7m_common_t
*armv7m
= target
->arch_info
;
403 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
404 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
406 /* Read from Debug Halting Control and Status Register */
407 retval
= mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
408 if (retval
!= ERROR_OK
)
410 target
->state
= TARGET_UNKNOWN
;
414 if (cortex_m3
->dcb_dhcsr
& S_RESET_ST
)
416 /* check if still in reset */
417 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
419 if (cortex_m3
->dcb_dhcsr
& S_RESET_ST
)
421 target
->state
= TARGET_RESET
;
426 if (target
->state
== TARGET_RESET
)
428 /* Cannot switch context while running so endreset is called with target->state == TARGET_RESET */
429 LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32
"", cortex_m3
->dcb_dhcsr
);
430 cortex_m3_endreset_event(target
);
431 target
->state
= TARGET_RUNNING
;
432 prev_target_state
= TARGET_RUNNING
;
435 if (cortex_m3
->dcb_dhcsr
& S_HALT
)
437 target
->state
= TARGET_HALTED
;
439 if ((prev_target_state
== TARGET_RUNNING
) || (prev_target_state
== TARGET_RESET
))
441 if ((retval
= cortex_m3_debug_entry(target
)) != ERROR_OK
)
444 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
446 if (prev_target_state
== TARGET_DEBUG_RUNNING
)
449 if ((retval
= cortex_m3_debug_entry(target
)) != ERROR_OK
)
452 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
456 /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
457 * How best to model low power modes?
460 if (target
->state
== TARGET_UNKNOWN
)
462 /* check if processor is retiring instructions */
463 if (cortex_m3
->dcb_dhcsr
& S_RETIRE_ST
)
465 target
->state
= TARGET_RUNNING
;
473 static int cortex_m3_halt(target_t
*target
)
475 LOG_DEBUG("target->state: %s",
476 target_state_name(target
));
478 if (target
->state
== TARGET_HALTED
)
480 LOG_DEBUG("target was already halted");
484 if (target
->state
== TARGET_UNKNOWN
)
486 LOG_WARNING("target was in unknown state when halt was requested");
489 if (target
->state
== TARGET_RESET
)
491 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST
) && jtag_get_srst())
493 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
494 return ERROR_TARGET_FAILURE
;
498 /* we came here in a reset_halt or reset_init sequence
499 * debug entry was already prepared in cortex_m3_prepare_reset_halt()
501 target
->debug_reason
= DBG_REASON_DBGRQ
;
507 /* Write to Debug Halting Control and Status Register */
508 cortex_m3_write_debug_halt_mask(target
, C_HALT
, 0);
510 target
->debug_reason
= DBG_REASON_DBGRQ
;
515 static int cortex_m3_soft_reset_halt(struct target_s
*target
)
517 /* get pointers to arch-specific information */
518 armv7m_common_t
*armv7m
= target
->arch_info
;
519 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
520 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
521 uint32_t dcb_dhcsr
= 0;
522 int retval
, timeout
= 0;
524 /* Enter debug state on reset, cf. end_reset_event() */
525 mem_ap_write_u32(swjdp
, DCB_DEMCR
, TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
527 /* Request a reset */
528 mem_ap_write_atomic_u32(swjdp
, NVIC_AIRCR
, AIRCR_VECTKEY
| AIRCR_VECTRESET
);
529 target
->state
= TARGET_RESET
;
531 /* registers are now invalid */
532 armv7m_invalidate_core_regs(target
);
534 while (timeout
< 100)
536 retval
= mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &dcb_dhcsr
);
537 if (retval
== ERROR_OK
)
539 mem_ap_read_atomic_u32(swjdp
, NVIC_DFSR
, &cortex_m3
->nvic_dfsr
);
540 if ((dcb_dhcsr
& S_HALT
) && (cortex_m3
->nvic_dfsr
& DFSR_VCATCH
))
542 LOG_DEBUG("system reset-halted, dcb_dhcsr 0x%" PRIx32
", nvic_dfsr 0x%" PRIx32
"", dcb_dhcsr
, cortex_m3
->nvic_dfsr
);
543 cortex_m3_poll(target
);
547 LOG_DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%" PRIx32
", %i ms", dcb_dhcsr
, timeout
);
556 static void cortex_m3_enable_breakpoints(struct target_s
*target
)
558 breakpoint_t
*breakpoint
= target
->breakpoints
;
560 /* set any pending breakpoints */
563 if (breakpoint
->set
== 0)
564 cortex_m3_set_breakpoint(target
, breakpoint
);
565 breakpoint
= breakpoint
->next
;
569 static int cortex_m3_resume(struct target_s
*target
, int current
,
570 uint32_t address
, int handle_breakpoints
, int debug_execution
)
572 /* get pointers to arch-specific information */
573 armv7m_common_t
*armv7m
= target
->arch_info
;
574 breakpoint_t
*breakpoint
= NULL
;
577 if (target
->state
!= TARGET_HALTED
)
579 LOG_WARNING("target not halted");
580 return ERROR_TARGET_NOT_HALTED
;
583 if (!debug_execution
)
585 target_free_all_working_areas(target
);
586 cortex_m3_enable_breakpoints(target
);
587 cortex_m3_enable_watchpoints(target
);
592 /* Disable interrupts */
593 /* We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
594 * This is probably the same issue as Cortex-M3 Errata 377493:
595 * C_MASKINTS in parallel with disabled interrupts can cause local faults to not be taken. */
596 buf_set_u32(armv7m
->core_cache
->reg_list
[ARMV7M_PRIMASK
].value
, 0, 32, 1);
597 armv7m
->core_cache
->reg_list
[ARMV7M_PRIMASK
].dirty
= 1;
598 armv7m
->core_cache
->reg_list
[ARMV7M_PRIMASK
].valid
= 1;
600 /* Make sure we are in Thumb mode */
601 buf_set_u32(armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].value
, 0, 32,
602 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].value
, 0, 32) | (1 << 24));
603 armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].dirty
= 1;
604 armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].valid
= 1;
607 /* current = 1: continue on current pc, otherwise continue at <address> */
610 buf_set_u32(armv7m
->core_cache
->reg_list
[15].value
, 0, 32, address
);
611 armv7m
->core_cache
->reg_list
[15].dirty
= 1;
612 armv7m
->core_cache
->reg_list
[15].valid
= 1;
615 resume_pc
= buf_get_u32(armv7m
->core_cache
->reg_list
[15].value
, 0, 32);
617 armv7m_restore_context(target
);
619 /* the front-end may request us not to handle breakpoints */
620 if (handle_breakpoints
)
622 /* Single step past breakpoint at current address */
623 if ((breakpoint
= breakpoint_find(target
, resume_pc
)))
625 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
627 breakpoint
->unique_id
);
628 cortex_m3_unset_breakpoint(target
, breakpoint
);
629 cortex_m3_single_step_core(target
);
630 cortex_m3_set_breakpoint(target
, breakpoint
);
635 cortex_m3_write_debug_halt_mask(target
, 0, C_HALT
);
637 target
->debug_reason
= DBG_REASON_NOTHALTED
;
639 /* registers are now invalid */
640 armv7m_invalidate_core_regs(target
);
641 if (!debug_execution
)
643 target
->state
= TARGET_RUNNING
;
644 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
645 LOG_DEBUG("target resumed at 0x%" PRIx32
"", resume_pc
);
649 target
->state
= TARGET_DEBUG_RUNNING
;
650 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
651 LOG_DEBUG("target debug resumed at 0x%" PRIx32
"", resume_pc
);
657 /* int irqstepcount = 0; */
658 static int cortex_m3_step(struct target_s
*target
, int current
,
659 uint32_t address
, int handle_breakpoints
)
661 /* get pointers to arch-specific information */
662 armv7m_common_t
*armv7m
= target
->arch_info
;
663 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
664 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
665 breakpoint_t
*breakpoint
= NULL
;
667 if (target
->state
!= TARGET_HALTED
)
669 LOG_WARNING("target not halted");
670 return ERROR_TARGET_NOT_HALTED
;
673 /* current = 1: continue on current pc, otherwise continue at <address> */
675 buf_set_u32(armv7m
->core_cache
->reg_list
[15].value
, 0, 32, address
);
677 /* the front-end may request us not to handle breakpoints */
678 if (handle_breakpoints
)
679 if ((breakpoint
= breakpoint_find(target
, buf_get_u32(armv7m
->core_cache
->reg_list
[15].value
, 0, 32))))
680 cortex_m3_unset_breakpoint(target
, breakpoint
);
682 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
684 armv7m_restore_context(target
);
686 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
688 /* set step and clear halt */
689 cortex_m3_write_debug_halt_mask(target
, C_STEP
, C_HALT
);
690 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
692 /* registers are now invalid */
693 armv7m_invalidate_core_regs(target
);
696 cortex_m3_set_breakpoint(target
, breakpoint
);
698 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
" nvic_icsr = 0x%" PRIx32
"", cortex_m3
->dcb_dhcsr
, cortex_m3
->nvic_icsr
);
700 cortex_m3_debug_entry(target
);
701 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
703 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
" nvic_icsr = 0x%" PRIx32
"", cortex_m3
->dcb_dhcsr
, cortex_m3
->nvic_icsr
);
707 static int cortex_m3_assert_reset(target_t
*target
)
709 armv7m_common_t
*armv7m
= target
->arch_info
;
710 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
711 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
714 LOG_DEBUG("target->state: %s",
715 target_state_name(target
));
717 enum reset_types jtag_reset_config
= jtag_get_reset_config();
720 * We can reset Cortex-M3 targets using just the NVIC without
721 * requiring SRST, getting a SoC reset (or a core-only reset)
722 * instead of a system reset.
724 if (!(jtag_reset_config
& RESET_HAS_SRST
))
727 /* Enable debug requests */
728 mem_ap_read_atomic_u32(swjdp
, DCB_DHCSR
, &cortex_m3
->dcb_dhcsr
);
729 if (!(cortex_m3
->dcb_dhcsr
& C_DEBUGEN
))
730 mem_ap_write_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_DEBUGEN
);
732 mem_ap_write_u32(swjdp
, DCB_DCRDR
, 0);
734 if (!target
->reset_halt
)
736 /* Set/Clear C_MASKINTS in a separate operation */
737 if (cortex_m3
->dcb_dhcsr
& C_MASKINTS
)
738 mem_ap_write_atomic_u32(swjdp
, DCB_DHCSR
, DBGKEY
| C_DEBUGEN
| C_HALT
);
740 /* clear any debug flags before resuming */
741 cortex_m3_clear_halt(target
);
743 /* clear C_HALT in dhcsr reg */
744 cortex_m3_write_debug_halt_mask(target
, 0, C_HALT
);
746 /* Enter debug state on reset, cf. end_reset_event() */
747 mem_ap_write_u32(swjdp
, DCB_DEMCR
, TRCENA
| VC_HARDERR
| VC_BUSERR
);
751 /* Enter debug state on reset, cf. end_reset_event() */
752 mem_ap_write_atomic_u32(swjdp
, DCB_DEMCR
, TRCENA
| VC_HARDERR
| VC_BUSERR
| VC_CORERESET
);
756 * When nRST is asserted on most Stellaris devices, it clears some of
757 * the debug state. The ARMv7M and Cortex-M3 TRMs say that's wrong;
758 * and OpenOCD depends on those TRMs. So we won't use SRST on those
759 * chips. (Only power-on reset should affect debug state, beyond a
760 * few specified bits; not the chip's nRST input, wired to SRST.)
762 * REVISIT current errata specs don't seem to cover this issue.
763 * Do we have more details than this email?
764 * https://lists.berlios.de/pipermail
765 * /openocd-development/2008-August/003065.html
767 if (strcmp(target
->variant
, "lm3s") == 0)
769 /* Check for silicon revisions with the issue. */
772 if (target_read_u32(target
, 0x400fe000, &did0
) == ERROR_OK
)
774 switch ((did0
>> 16) & 0xff)
777 /* all Sandstorm suffer issue */
783 /* Fury and DustDevil rev A have
784 * this nRST problem. It should
785 * be fixed in rev B silicon.
787 if (((did0
>> 8) & 0xff) == 0)
791 /* Tempest should be fine. */
799 /* default to asserting srst */
800 if (jtag_reset_config
& RESET_SRST_PULLS_TRST
)
802 jtag_add_reset(1, 1);
806 jtag_add_reset(0, 1);
811 /* Use a standard Cortex-M3 software reset mechanism.
812 * SYSRESETREQ will reset SoC peripherals outside the
813 * core, like watchdog timers, if the SoC wires it up
814 * correctly. Else VECRESET can reset just the core.
816 mem_ap_write_atomic_u32(swjdp
, NVIC_AIRCR
,
817 AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
818 LOG_DEBUG("Using Cortex-M3 SYSRESETREQ");
821 /* I do not know why this is necessary, but it
822 * fixes strange effects (step/resume cause NMI
823 * after reset) on LM3S6918 -- Michael Schwingen
826 mem_ap_read_atomic_u32(swjdp
, NVIC_AIRCR
, &tmp
);
830 target
->state
= TARGET_RESET
;
831 jtag_add_sleep(50000);
833 armv7m_invalidate_core_regs(target
);
835 if (target
->reset_halt
)
838 if ((retval
= target_halt(target
)) != ERROR_OK
)
845 static int cortex_m3_deassert_reset(target_t
*target
)
847 LOG_DEBUG("target->state: %s",
848 target_state_name(target
));
850 /* deassert reset lines */
851 jtag_add_reset(0, 0);
857 cortex_m3_set_breakpoint(struct target_s
*target
, breakpoint_t
*breakpoint
)
863 /* get pointers to arch-specific information */
864 armv7m_common_t
*armv7m
= target
->arch_info
;
865 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
867 cortex_m3_fp_comparator_t
* comparator_list
= cortex_m3
->fp_comparator_list
;
871 LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint
->unique_id
);
875 if (cortex_m3
->auto_bp_type
)
877 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
880 if (breakpoint
->type
== BKPT_HARD
)
882 while (comparator_list
[fp_num
].used
&& (fp_num
< cortex_m3
->fp_num_code
))
884 if (fp_num
>= cortex_m3
->fp_num_code
)
886 LOG_DEBUG("ERROR Can not find free FP Comparator");
887 LOG_WARNING("ERROR Can not find free FP Comparator");
890 breakpoint
->set
= fp_num
+ 1;
891 hilo
= (breakpoint
->address
& 0x2) ? FPCR_REPLACE_BKPT_HIGH
: FPCR_REPLACE_BKPT_LOW
;
892 comparator_list
[fp_num
].used
= 1;
893 comparator_list
[fp_num
].fpcr_value
= (breakpoint
->address
& 0x1FFFFFFC) | hilo
| 1;
894 target_write_u32(target
, comparator_list
[fp_num
].fpcr_address
, comparator_list
[fp_num
].fpcr_value
);
895 LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32
"", fp_num
, comparator_list
[fp_num
].fpcr_value
);
896 if (!cortex_m3
->fpb_enabled
)
898 LOG_DEBUG("FPB wasn't enabled, do it now");
899 target_write_u32(target
, FP_CTRL
, 3);
902 else if (breakpoint
->type
== BKPT_SOFT
)
905 buf_set_u32(code
, 0, 32, ARMV7M_T_BKPT(0x11));
906 if ((retval
= target_read_memory(target
, breakpoint
->address
& 0xFFFFFFFE, breakpoint
->length
, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
910 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, breakpoint
->length
, 1, code
)) != ERROR_OK
)
914 breakpoint
->set
= 0x11; /* Any nice value but 0 */
917 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32
" Length: %d (set=%d)",
918 breakpoint
->unique_id
,
919 (int)(breakpoint
->type
),
928 cortex_m3_unset_breakpoint(struct target_s
*target
, breakpoint_t
*breakpoint
)
931 /* get pointers to arch-specific information */
932 armv7m_common_t
*armv7m
= target
->arch_info
;
933 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
934 cortex_m3_fp_comparator_t
* comparator_list
= cortex_m3
->fp_comparator_list
;
936 if (!breakpoint
->set
)
938 LOG_WARNING("breakpoint not set");
942 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32
" Length: %d (set=%d)",
943 breakpoint
->unique_id
,
944 (int)(breakpoint
->type
),
949 if (breakpoint
->type
== BKPT_HARD
)
951 int fp_num
= breakpoint
->set
- 1;
952 if ((fp_num
< 0) || (fp_num
>= cortex_m3
->fp_num_code
))
954 LOG_DEBUG("Invalid FP Comparator number in breakpoint");
957 comparator_list
[fp_num
].used
= 0;
958 comparator_list
[fp_num
].fpcr_value
= 0;
959 target_write_u32(target
, comparator_list
[fp_num
].fpcr_address
, comparator_list
[fp_num
].fpcr_value
);
963 /* restore original instruction (kept in target endianness) */
964 if (breakpoint
->length
== 4)
966 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, 4, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
973 if ((retval
= target_write_memory(target
, breakpoint
->address
& 0xFFFFFFFE, 2, 1, breakpoint
->orig_instr
)) != ERROR_OK
)
985 cortex_m3_add_breakpoint(struct target_s
*target
, breakpoint_t
*breakpoint
)
987 /* get pointers to arch-specific information */
988 armv7m_common_t
*armv7m
= target
->arch_info
;
989 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
991 if (cortex_m3
->auto_bp_type
)
993 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
994 #ifdef ARMV7_GDB_HACKS
995 if (breakpoint
->length
!= 2) {
996 /* XXX Hack: Replace all breakpoints with length != 2 with
997 * a hardware breakpoint. */
998 breakpoint
->type
= BKPT_HARD
;
999 breakpoint
->length
= 2;
1004 if ((breakpoint
->type
== BKPT_HARD
) && (breakpoint
->address
>= 0x20000000))
1006 LOG_INFO("flash patch comparator requested outside code memory region");
1007 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1010 if ((breakpoint
->type
== BKPT_SOFT
) && (breakpoint
->address
< 0x20000000))
1012 LOG_INFO("soft breakpoint requested in code (flash) memory region");
1013 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1016 if ((breakpoint
->type
== BKPT_HARD
) && (cortex_m3
->fp_code_available
< 1))
1018 LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
1019 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1022 if ((breakpoint
->length
!= 2))
1024 LOG_INFO("only breakpoints of two bytes length supported");
1025 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1028 if (breakpoint
->type
== BKPT_HARD
)
1029 cortex_m3
->fp_code_available
--;
1030 cortex_m3_set_breakpoint(target
, breakpoint
);
1036 cortex_m3_remove_breakpoint(struct target_s
*target
, breakpoint_t
*breakpoint
)
1038 /* get pointers to arch-specific information */
1039 armv7m_common_t
*armv7m
= target
->arch_info
;
1040 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
1042 /* REVISIT why check? FBP can be updated with core running ... */
1043 if (target
->state
!= TARGET_HALTED
)
1045 LOG_WARNING("target not halted");
1046 return ERROR_TARGET_NOT_HALTED
;
1049 if (cortex_m3
->auto_bp_type
)
1051 breakpoint
->type
= (breakpoint
->address
< 0x20000000) ? BKPT_HARD
: BKPT_SOFT
;
1054 if (breakpoint
->set
)
1056 cortex_m3_unset_breakpoint(target
, breakpoint
);
1059 if (breakpoint
->type
== BKPT_HARD
)
1060 cortex_m3
->fp_code_available
++;
1066 cortex_m3_set_watchpoint(struct target_s
*target
, watchpoint_t
*watchpoint
)
1069 uint32_t mask
, temp
;
1071 /* get pointers to arch-specific information */
1072 armv7m_common_t
*armv7m
= target
->arch_info
;
1073 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
1075 /* watchpoint params were validated earlier */
1077 temp
= watchpoint
->length
;
1084 /* REVISIT Don't fully trust these "not used" records ... users
1085 * may set up breakpoints by hand, e.g. dual-address data value
1086 * watchpoint using comparator #1; comparator #0 matching cycle
1087 * count; send data trace info through ITM and TPIU; etc
1089 cortex_m3_dwt_comparator_t
*comparator
;
1091 for (comparator
= cortex_m3
->dwt_comparator_list
;
1092 comparator
->used
&& dwt_num
< cortex_m3
->dwt_num_comp
;
1093 comparator
++, dwt_num
++)
1095 if (dwt_num
>= cortex_m3
->dwt_num_comp
)
1097 LOG_ERROR("Can not find free DWT Comparator");
1100 comparator
->used
= 1;
1101 watchpoint
->set
= dwt_num
+ 1;
1103 comparator
->comp
= watchpoint
->address
;
1104 target_write_u32(target
, comparator
->dwt_comparator_address
+ 0,
1107 comparator
->mask
= mask
;
1108 target_write_u32(target
, comparator
->dwt_comparator_address
+ 4,
1111 switch (watchpoint
->rw
) {
1113 comparator
->function
= 5;
1116 comparator
->function
= 6;
1119 comparator
->function
= 7;
1122 target_write_u32(target
, comparator
->dwt_comparator_address
+ 8,
1123 comparator
->function
);
1125 LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x",
1126 watchpoint
->unique_id
, dwt_num
,
1127 (unsigned) comparator
->comp
,
1128 (unsigned) comparator
->mask
,
1129 (unsigned) comparator
->function
);
1134 cortex_m3_unset_watchpoint(struct target_s
*target
, watchpoint_t
*watchpoint
)
1136 /* get pointers to arch-specific information */
1137 armv7m_common_t
*armv7m
= target
->arch_info
;
1138 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
1139 cortex_m3_dwt_comparator_t
*comparator
;
1142 if (!watchpoint
->set
)
1144 LOG_WARNING("watchpoint (wpid: %d) not set",
1145 watchpoint
->unique_id
);
1149 dwt_num
= watchpoint
->set
- 1;
1151 LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
1152 watchpoint
->unique_id
, dwt_num
,
1153 (unsigned) watchpoint
->address
);
1155 if ((dwt_num
< 0) || (dwt_num
>= cortex_m3
->dwt_num_comp
))
1157 LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
1161 comparator
= cortex_m3
->dwt_comparator_list
+ dwt_num
;
1162 comparator
->used
= 0;
1163 comparator
->function
= 0;
1164 target_write_u32(target
, comparator
->dwt_comparator_address
+ 8,
1165 comparator
->function
);
1167 watchpoint
->set
= 0;
1173 cortex_m3_add_watchpoint(struct target_s
*target
, watchpoint_t
*watchpoint
)
1175 /* get pointers to arch-specific information */
1176 armv7m_common_t
*armv7m
= target
->arch_info
;
1177 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
1179 /* REVISIT why check? DWT can be updated with core running ... */
1180 if (target
->state
!= TARGET_HALTED
)
1182 LOG_WARNING("target not halted");
1183 return ERROR_TARGET_NOT_HALTED
;
1186 if (cortex_m3
->dwt_comp_available
< 1)
1188 LOG_DEBUG("no comparators?");
1189 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1192 /* hardware doesn't support data value masking */
1193 if (watchpoint
->mask
!= ~(uint32_t)0) {
1194 LOG_DEBUG("watchpoint value masks not supported");
1195 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1198 /* hardware allows address masks of up to 32K */
1201 for (mask
= 0; mask
< 16; mask
++) {
1202 if ((1u << mask
) == watchpoint
->length
)
1206 LOG_DEBUG("unsupported watchpoint length");
1207 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1209 if (watchpoint
->address
& ((1 << mask
) - 1)) {
1210 LOG_DEBUG("watchpoint address is unaligned");
1211 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1214 /* Caller doesn't seem to be able to describe watching for data
1215 * values of zero; that flags "no value".
1217 * REVISIT This DWT may well be able to watch for specific data
1218 * values. Requires comparator #1 to set DATAVMATCH and match
1219 * the data, and another comparator (DATAVADDR0) matching addr.
1221 if (watchpoint
->value
) {
1222 LOG_DEBUG("data value watchpoint not YET supported");
1223 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1226 cortex_m3
->dwt_comp_available
--;
1227 LOG_DEBUG("dwt_comp_available: %d", cortex_m3
->dwt_comp_available
);
1233 cortex_m3_remove_watchpoint(struct target_s
*target
, watchpoint_t
*watchpoint
)
1235 /* get pointers to arch-specific information */
1236 armv7m_common_t
*armv7m
= target
->arch_info
;
1237 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
1239 /* REVISIT why check? DWT can be updated with core running ... */
1240 if (target
->state
!= TARGET_HALTED
)
1242 LOG_WARNING("target not halted");
1243 return ERROR_TARGET_NOT_HALTED
;
1246 if (watchpoint
->set
)
1248 cortex_m3_unset_watchpoint(target
, watchpoint
);
1251 cortex_m3
->dwt_comp_available
++;
1252 LOG_DEBUG("dwt_comp_available: %d", cortex_m3
->dwt_comp_available
);
1257 static void cortex_m3_enable_watchpoints(struct target_s
*target
)
1259 watchpoint_t
*watchpoint
= target
->watchpoints
;
1261 /* set any pending watchpoints */
1264 if (watchpoint
->set
== 0)
1265 cortex_m3_set_watchpoint(target
, watchpoint
);
1266 watchpoint
= watchpoint
->next
;
1270 static int cortex_m3_load_core_reg_u32(struct target_s
*target
,
1271 enum armv7m_regtype type
, uint32_t num
, uint32_t * value
)
1274 /* get pointers to arch-specific information */
1275 armv7m_common_t
*armv7m
= target
->arch_info
;
1276 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
1278 /* NOTE: we "know" here that the register identifiers used
1279 * in the v7m header match the Cortex-M3 Debug Core Register
1280 * Selector values for R0..R15, xPSR, MSP, and PSP.
1284 /* read a normal core register */
1285 retval
= cortexm3_dap_read_coreregister_u32(swjdp
, value
, num
);
1287 if (retval
!= ERROR_OK
)
1289 LOG_ERROR("JTAG failure %i",retval
);
1290 return ERROR_JTAG_DEVICE_ERROR
;
1292 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"",(int)num
,*value
);
1295 case ARMV7M_PRIMASK
:
1296 case ARMV7M_BASEPRI
:
1297 case ARMV7M_FAULTMASK
:
1298 case ARMV7M_CONTROL
:
1299 /* Cortex-M3 packages these four registers as bitfields
1300 * in one Debug Core register. So say r0 and r2 docs;
1301 * it was removed from r1 docs, but still works.
1303 cortexm3_dap_read_coreregister_u32(swjdp
, value
, 20);
1307 case ARMV7M_PRIMASK
:
1308 *value
= buf_get_u32((uint8_t*)value
, 0, 1);
1311 case ARMV7M_BASEPRI
:
1312 *value
= buf_get_u32((uint8_t*)value
, 8, 8);
1315 case ARMV7M_FAULTMASK
:
1316 *value
= buf_get_u32((uint8_t*)value
, 16, 1);
1319 case ARMV7M_CONTROL
:
1320 *value
= buf_get_u32((uint8_t*)value
, 24, 2);
1324 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"", (int)num
, *value
);
1328 return ERROR_INVALID_ARGUMENTS
;
1334 static int cortex_m3_store_core_reg_u32(struct target_s
*target
,
1335 enum armv7m_regtype type
, uint32_t num
, uint32_t value
)
1340 /* get pointers to arch-specific information */
1341 armv7m_common_t
*armv7m
= target
->arch_info
;
1342 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
1344 #ifdef ARMV7_GDB_HACKS
1345 /* If the LR register is being modified, make sure it will put us
1346 * in "thumb" mode, or an INVSTATE exception will occur. This is a
1347 * hack to deal with the fact that gdb will sometimes "forge"
1348 * return addresses, and doesn't set the LSB correctly (i.e., when
1349 * printing expressions containing function calls, it sets LR = 0.)
1350 * Valid exception return codes have bit 0 set too.
1352 if (num
== ARMV7M_R14
)
1356 /* NOTE: we "know" here that the register identifiers used
1357 * in the v7m header match the Cortex-M3 Debug Core Register
1358 * Selector values for R0..R15, xPSR, MSP, and PSP.
1362 retval
= cortexm3_dap_write_coreregister_u32(swjdp
, value
, num
);
1363 if (retval
!= ERROR_OK
)
1365 LOG_ERROR("JTAG failure %i", retval
);
1366 armv7m
->core_cache
->reg_list
[num
].dirty
= armv7m
->core_cache
->reg_list
[num
].valid
;
1367 return ERROR_JTAG_DEVICE_ERROR
;
1369 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
1372 case ARMV7M_PRIMASK
:
1373 case ARMV7M_BASEPRI
:
1374 case ARMV7M_FAULTMASK
:
1375 case ARMV7M_CONTROL
:
1376 /* Cortex-M3 packages these four registers as bitfields
1377 * in one Debug Core register. So say r0 and r2 docs;
1378 * it was removed from r1 docs, but still works.
1380 cortexm3_dap_read_coreregister_u32(swjdp
, ®
, 20);
1384 case ARMV7M_PRIMASK
:
1385 buf_set_u32((uint8_t*)®
, 0, 1, value
);
1388 case ARMV7M_BASEPRI
:
1389 buf_set_u32((uint8_t*)®
, 8, 8, value
);
1392 case ARMV7M_FAULTMASK
:
1393 buf_set_u32((uint8_t*)®
, 16, 1, value
);
1396 case ARMV7M_CONTROL
:
1397 buf_set_u32((uint8_t*)®
, 24, 2, value
);
1401 cortexm3_dap_write_coreregister_u32(swjdp
, reg
, 20);
1403 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
1407 return ERROR_INVALID_ARGUMENTS
;
1413 static int cortex_m3_read_memory(struct target_s
*target
, uint32_t address
,
1414 uint32_t size
, uint32_t count
, uint8_t *buffer
)
1416 /* get pointers to arch-specific information */
1417 armv7m_common_t
*armv7m
= target
->arch_info
;
1418 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
1421 /* sanitize arguments */
1422 if (((size
!= 4) && (size
!= 2) && (size
!= 1)) || (count
== 0) || !(buffer
))
1423 return ERROR_INVALID_ARGUMENTS
;
1425 /* cortex_m3 handles unaligned memory access */
1430 retval
= mem_ap_read_buf_u32(swjdp
, buffer
, 4 * count
, address
);
1433 retval
= mem_ap_read_buf_u16(swjdp
, buffer
, 2 * count
, address
);
1436 retval
= mem_ap_read_buf_u8(swjdp
, buffer
, count
, address
);
1439 LOG_ERROR("BUG: we shouldn't get here");
1446 static int cortex_m3_write_memory(struct target_s
*target
, uint32_t address
,
1447 uint32_t size
, uint32_t count
, uint8_t *buffer
)
1449 /* get pointers to arch-specific information */
1450 armv7m_common_t
*armv7m
= target
->arch_info
;
1451 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
1454 /* sanitize arguments */
1455 if (((size
!= 4) && (size
!= 2) && (size
!= 1)) || (count
== 0) || !(buffer
))
1456 return ERROR_INVALID_ARGUMENTS
;
1461 retval
= mem_ap_write_buf_u32(swjdp
, buffer
, 4 * count
, address
);
1464 retval
= mem_ap_write_buf_u16(swjdp
, buffer
, 2 * count
, address
);
1467 retval
= mem_ap_write_buf_u8(swjdp
, buffer
, count
, address
);
1470 LOG_ERROR("BUG: we shouldn't get here");
1477 static int cortex_m3_bulk_write_memory(target_t
*target
, uint32_t address
,
1478 uint32_t count
, uint8_t *buffer
)
1480 return cortex_m3_write_memory(target
, address
, 4, count
, buffer
);
1483 static int cortex_m3_init_target(struct command_context_s
*cmd_ctx
,
1484 struct target_s
*target
)
1486 armv7m_build_reg_cache(target
);
1490 /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid"
1491 * on r/w if the core is not running, and clear on resume or reset ... or
1492 * at least, in a post_restore_context() method.
1495 struct dwt_reg_state
{
1496 struct target_s
*target
;
1498 uint32_t value
; /* scratch/cache */
1501 static int cortex_m3_dwt_get_reg(struct reg_s
*reg
)
1503 struct dwt_reg_state
*state
= reg
->arch_info
;
1505 return target_read_u32(state
->target
, state
->addr
, &state
->value
);
1508 static int cortex_m3_dwt_set_reg(struct reg_s
*reg
, uint8_t *buf
)
1510 struct dwt_reg_state
*state
= reg
->arch_info
;
1512 return target_write_u32(state
->target
, state
->addr
,
1513 buf_get_u32(buf
, 0, reg
->size
));
1522 static struct dwt_reg dwt_base_regs
[] = {
1523 { DWT_CTRL
, "dwt_ctrl", 32, },
1524 { DWT_CYCCNT
, "dwt_cyccnt", 32, },
1525 /* plus some 8 bit counters, useful for profiling with TPIU */
1528 static struct dwt_reg dwt_comp
[] = {
1529 #define DWT_COMPARATOR(i) \
1530 { DWT_COMP0 + 0x10 * (i), "dwt_" #i "_comp", 32, }, \
1531 { DWT_MASK0 + 0x10 * (i), "dwt_" #i "_mask", 4, }, \
1532 { DWT_FUNCTION0 + 0x10 * (i), "dwt_" #i "_function", 32, }
1537 #undef DWT_COMPARATOR
1540 static int dwt_reg_type
= -1;
1543 cortex_m3_dwt_addreg(struct target_s
*t
, struct reg_s
*r
, struct dwt_reg
*d
)
1545 struct dwt_reg_state
*state
;
1547 state
= calloc(1, sizeof *state
);
1550 state
->addr
= d
->addr
;
1555 r
->value
= &state
->value
;
1556 r
->arch_info
= state
;
1557 r
->arch_type
= dwt_reg_type
;
1561 cortex_m3_dwt_setup(cortex_m3_common_t
*cm3
, struct target_s
*target
)
1564 struct reg_cache_s
*cache
;
1565 cortex_m3_dwt_comparator_t
*comparator
;
1568 target_read_u32(target
, DWT_CTRL
, &dwtcr
);
1570 LOG_DEBUG("no DWT");
1574 if (dwt_reg_type
< 0)
1575 dwt_reg_type
= register_reg_arch_type(cortex_m3_dwt_get_reg
,
1576 cortex_m3_dwt_set_reg
);
1578 cm3
->dwt_num_comp
= (dwtcr
>> 28) & 0xF;
1579 cm3
->dwt_comp_available
= cm3
->dwt_num_comp
;
1580 cm3
->dwt_comparator_list
= calloc(cm3
->dwt_num_comp
,
1581 sizeof(cortex_m3_dwt_comparator_t
));
1582 if (!cm3
->dwt_comparator_list
) {
1584 cm3
->dwt_num_comp
= 0;
1585 LOG_ERROR("out of mem");
1589 cache
= calloc(1, sizeof *cache
);
1592 free(cm3
->dwt_comparator_list
);
1595 cache
->name
= "cortex-m3 dwt registers";
1596 cache
->num_regs
= 2 + cm3
->dwt_num_comp
* 3;
1597 cache
->reg_list
= calloc(cache
->num_regs
, sizeof *cache
->reg_list
);
1598 if (!cache
->reg_list
) {
1603 for (reg
= 0; reg
< 2; reg
++)
1604 cortex_m3_dwt_addreg(target
, cache
->reg_list
+ reg
,
1605 dwt_base_regs
+ reg
);
1607 comparator
= cm3
->dwt_comparator_list
;
1608 for (i
= 0; i
< cm3
->dwt_num_comp
; i
++, comparator
++) {
1611 comparator
->dwt_comparator_address
= DWT_COMP0
+ 0x10 * i
;
1612 for (j
= 0; j
< 3; j
++, reg
++)
1613 cortex_m3_dwt_addreg(target
, cache
->reg_list
+ reg
,
1614 dwt_comp
+ 3 * i
+ j
);
1617 *register_get_last_cache_p(&target
->reg_cache
) = cache
;
1618 cm3
->dwt_cache
= cache
;
1620 LOG_INFO("DWT dwtcr 0x%" PRIx32
", comp %d, watch%s",
1621 dwtcr
, cm3
->dwt_num_comp
,
1622 (dwtcr
& (0xf << 24)) ? " only" : "/trigger");
1624 /* REVISIT: if num_comp > 1, check whether comparator #1 can
1625 * implement single-address data value watchpoints ... so we
1626 * won't need to check it later, when asked to set one up.
1630 static int cortex_m3_examine(struct target_s
*target
)
1633 uint32_t cpuid
, fpcr
;
1636 /* get pointers to arch-specific information */
1637 armv7m_common_t
*armv7m
= target
->arch_info
;
1638 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
1639 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
1641 if ((retval
= ahbap_debugport_init(swjdp
)) != ERROR_OK
)
1644 if (!target_was_examined(target
))
1646 target_set_examined(target
);
1648 /* Read from Device Identification Registers */
1649 retval
= target_read_u32(target
, CPUID
, &cpuid
);
1650 if (retval
!= ERROR_OK
)
1653 if (((cpuid
>> 4) & 0xc3f) == 0xc23)
1654 LOG_DEBUG("CORTEX-M3 processor detected");
1655 LOG_DEBUG("cpuid: 0x%8.8" PRIx32
"", cpuid
);
1657 /* NOTE: FPB and DWT are both optional. */
1660 target_read_u32(target
, FP_CTRL
, &fpcr
);
1661 cortex_m3
->auto_bp_type
= 1;
1662 cortex_m3
->fp_num_code
= ((fpcr
>> 8) & 0x70) | ((fpcr
>> 4) & 0xF); /* bits [14:12] and [7:4] */
1663 cortex_m3
->fp_num_lit
= (fpcr
>> 8) & 0xF;
1664 cortex_m3
->fp_code_available
= cortex_m3
->fp_num_code
;
1665 cortex_m3
->fp_comparator_list
= calloc(cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
, sizeof(cortex_m3_fp_comparator_t
));
1666 cortex_m3
->fpb_enabled
= fpcr
& 1;
1667 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++)
1669 cortex_m3
->fp_comparator_list
[i
].type
= (i
< cortex_m3
->fp_num_code
) ? FPCR_CODE
: FPCR_LITERAL
;
1670 cortex_m3
->fp_comparator_list
[i
].fpcr_address
= FP_COMP0
+ 4 * i
;
1672 LOG_DEBUG("FPB fpcr 0x%" PRIx32
", numcode %i, numlit %i", fpcr
, cortex_m3
->fp_num_code
, cortex_m3
->fp_num_lit
);
1675 cortex_m3_dwt_setup(cortex_m3
, target
);
1681 static int cortex_m3_dcc_read(swjdp_common_t
*swjdp
, uint8_t *value
, uint8_t *ctrl
)
1685 mem_ap_read_buf_u16(swjdp
, (uint8_t*)&dcrdr
, 1, DCB_DCRDR
);
1686 *ctrl
= (uint8_t)dcrdr
;
1687 *value
= (uint8_t)(dcrdr
>> 8);
1689 LOG_DEBUG("data 0x%x ctrl 0x%x", *value
, *ctrl
);
1691 /* write ack back to software dcc register
1692 * signify we have read data */
1693 if (dcrdr
& (1 << 0))
1696 mem_ap_write_buf_u16(swjdp
, (uint8_t*)&dcrdr
, 1, DCB_DCRDR
);
1702 static int cortex_m3_target_request_data(target_t
*target
,
1703 uint32_t size
, uint8_t *buffer
)
1705 armv7m_common_t
*armv7m
= target
->arch_info
;
1706 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
1711 for (i
= 0; i
< (size
* 4); i
++)
1713 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1720 static int cortex_m3_handle_target_request(void *priv
)
1722 target_t
*target
= priv
;
1723 if (!target_was_examined(target
))
1725 armv7m_common_t
*armv7m
= target
->arch_info
;
1726 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
1728 if (!target
->dbg_msg_enabled
)
1731 if (target
->state
== TARGET_RUNNING
)
1736 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1738 /* check if we have data */
1739 if (ctrl
& (1 << 0))
1743 /* we assume target is quick enough */
1745 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1746 request
|= (data
<< 8);
1747 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1748 request
|= (data
<< 16);
1749 cortex_m3_dcc_read(swjdp
, &data
, &ctrl
);
1750 request
|= (data
<< 24);
1751 target_request(target
, request
);
1758 static int cortex_m3_init_arch_info(target_t
*target
,
1759 cortex_m3_common_t
*cortex_m3
, jtag_tap_t
*tap
)
1762 armv7m_common_t
*armv7m
;
1763 armv7m
= &cortex_m3
->armv7m
;
1765 armv7m_init_arch_info(target
, armv7m
);
1767 /* prepare JTAG information for the new target */
1768 cortex_m3
->jtag_info
.tap
= tap
;
1769 cortex_m3
->jtag_info
.scann_size
= 4;
1771 armv7m
->swjdp_info
.dp_select_value
= -1;
1772 armv7m
->swjdp_info
.ap_csw_value
= -1;
1773 armv7m
->swjdp_info
.ap_tar_value
= -1;
1774 armv7m
->swjdp_info
.jtag_info
= &cortex_m3
->jtag_info
;
1775 armv7m
->swjdp_info
.memaccess_tck
= 8;
1776 armv7m
->swjdp_info
.tar_autoincr_block
= (1 << 12); /* Cortex-M3 has 4096 bytes autoincrement range */
1778 /* initialize arch-specific breakpoint handling */
1780 cortex_m3
->common_magic
= CORTEX_M3_COMMON_MAGIC
;
1781 cortex_m3
->arch_info
= NULL
;
1783 /* register arch-specific functions */
1784 armv7m
->examine_debug_reason
= cortex_m3_examine_debug_reason
;
1786 armv7m
->post_debug_entry
= NULL
;
1788 armv7m
->pre_restore_context
= NULL
;
1789 armv7m
->post_restore_context
= NULL
;
1791 armv7m
->arch_info
= cortex_m3
;
1792 armv7m
->load_core_reg_u32
= cortex_m3_load_core_reg_u32
;
1793 armv7m
->store_core_reg_u32
= cortex_m3_store_core_reg_u32
;
1795 target_register_timer_callback(cortex_m3_handle_target_request
, 1, 1, target
);
1797 if ((retval
= arm_jtag_setup_connection(&cortex_m3
->jtag_info
)) != ERROR_OK
)
1805 static int cortex_m3_target_create(struct target_s
*target
, Jim_Interp
*interp
)
1807 cortex_m3_common_t
*cortex_m3
= calloc(1,sizeof(cortex_m3_common_t
));
1809 cortex_m3_init_arch_info(target
, cortex_m3
, target
->tap
);
1815 * REVISIT Thumb2 disassembly should work for all ARMv7 cores, as well
1816 * as at least ARM-1156T2. The interesting thing about Cortex-M is
1817 * that *only* Thumb2 disassembly matters. There are also some small
1818 * additions to Thumb2 that are specific to ARMv7-M.
1821 handle_cortex_m3_disassemble_command(struct command_context_s
*cmd_ctx
,
1822 char *cmd
, char **args
, int argc
)
1824 int retval
= ERROR_OK
;
1825 target_t
*target
= get_current_target(cmd_ctx
);
1827 unsigned long count
= 1;
1828 arm_instruction_t cur_instruction
;
1833 count
= strtoul(args
[1], NULL
, 0);
1838 address
= strtoul(args
[0], NULL
, 0);
1843 command_print(cmd_ctx
,
1844 "usage: cortex_m3 disassemble <address> [<count>]");
1849 retval
= thumb2_opcode(target
, address
, &cur_instruction
);
1850 if (retval
!= ERROR_OK
)
1852 command_print(cmd_ctx
, "%s", cur_instruction
.text
);
1853 address
+= cur_instruction
.instruction_size
;
1859 static const struct {
1863 { "hard_err", VC_HARDERR
, },
1864 { "int_err", VC_INTERR
, },
1865 { "bus_err", VC_BUSERR
, },
1866 { "state_err", VC_STATERR
, },
1867 { "chk_err", VC_CHKERR
, },
1868 { "nocp_err", VC_NOCPERR
, },
1869 { "mm_err", VC_MMERR
, },
1870 { "reset", VC_CORERESET
, },
1874 handle_cortex_m3_vector_catch_command(struct command_context_s
*cmd_ctx
,
1875 char *cmd
, char **argv
, int argc
)
1877 target_t
*target
= get_current_target(cmd_ctx
);
1878 armv7m_common_t
*armv7m
= target
->arch_info
;
1879 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
1883 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &demcr
);
1889 if (strcmp(argv
[0], "all") == 0) {
1890 catch = VC_HARDERR
| VC_INTERR
| VC_BUSERR
1891 | VC_STATERR
| VC_CHKERR
| VC_NOCPERR
1892 | VC_MMERR
| VC_CORERESET
;
1894 } else if (strcmp(argv
[0], "none") == 0) {
1898 while (argc
-- > 0) {
1899 for (i
= 0; i
< ARRAY_SIZE(vec_ids
); i
++) {
1900 if (strcmp(argv
[argc
], vec_ids
[i
].name
) != 0)
1902 catch |= vec_ids
[i
].mask
;
1905 if (i
== ARRAY_SIZE(vec_ids
)) {
1906 LOG_ERROR("No CM3 vector '%s'", argv
[argc
]);
1907 return ERROR_INVALID_ARGUMENTS
;
1914 /* write, but don't assume it stuck */
1915 mem_ap_write_u32(swjdp
, DCB_DEMCR
, demcr
);
1916 mem_ap_read_atomic_u32(swjdp
, DCB_DEMCR
, &demcr
);
1919 for (i
= 0; i
< ARRAY_SIZE(vec_ids
); i
++)
1920 command_print(cmd_ctx
, "%9s: %s", vec_ids
[i
].name
,
1921 (demcr
& vec_ids
[i
].mask
) ? "catch" : "ignore");
1927 handle_cortex_m3_mask_interrupts_command(struct command_context_s
*cmd_ctx
,
1928 char *cmd
, char **args
, int argc
)
1930 target_t
*target
= get_current_target(cmd_ctx
);
1931 armv7m_common_t
*armv7m
= target
->arch_info
;
1932 cortex_m3_common_t
*cortex_m3
= armv7m
->arch_info
;
1934 if (target
->state
!= TARGET_HALTED
)
1936 command_print(cmd_ctx
, "target must be stopped for \"%s\" command", cmd
);
1942 if (!strcmp(args
[0], "on"))
1944 cortex_m3_write_debug_halt_mask(target
, C_HALT
| C_MASKINTS
, 0);
1946 else if (!strcmp(args
[0], "off"))
1948 cortex_m3_write_debug_halt_mask(target
, C_HALT
, C_MASKINTS
);
1952 command_print(cmd_ctx
, "usage: cortex_m3 maskisr ['on'|'off']");
1956 command_print(cmd_ctx
, "cortex_m3 interrupt mask %s",
1957 (cortex_m3
->dcb_dhcsr
& C_MASKINTS
) ? "on" : "off");
1962 static int cortex_m3_register_commands(struct command_context_s
*cmd_ctx
)
1965 command_t
*cortex_m3_cmd
;
1967 retval
= armv7m_register_commands(cmd_ctx
);
1969 cortex_m3_cmd
= register_command(cmd_ctx
, NULL
, "cortex_m3",
1970 NULL
, COMMAND_ANY
, "cortex_m3 specific commands");
1972 register_command(cmd_ctx
, cortex_m3_cmd
, "disassemble",
1973 handle_cortex_m3_disassemble_command
, COMMAND_EXEC
,
1974 "disassemble Thumb2 instructions <address> [<count>]");
1975 register_command(cmd_ctx
, cortex_m3_cmd
, "maskisr",
1976 handle_cortex_m3_mask_interrupts_command
, COMMAND_EXEC
,
1977 "mask cortex_m3 interrupts ['on'|'off']");
1978 register_command(cmd_ctx
, cortex_m3_cmd
, "vector_catch",
1979 handle_cortex_m3_vector_catch_command
, COMMAND_EXEC
,
1980 "catch hardware vectors ['all'|'none'|<list>]");
1985 target_type_t cortexm3_target
=
1987 .name
= "cortex_m3",
1989 .poll
= cortex_m3_poll
,
1990 .arch_state
= armv7m_arch_state
,
1992 .target_request_data
= cortex_m3_target_request_data
,
1994 .halt
= cortex_m3_halt
,
1995 .resume
= cortex_m3_resume
,
1996 .step
= cortex_m3_step
,
1998 .assert_reset
= cortex_m3_assert_reset
,
1999 .deassert_reset
= cortex_m3_deassert_reset
,
2000 .soft_reset_halt
= cortex_m3_soft_reset_halt
,
2002 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
2004 .read_memory
= cortex_m3_read_memory
,
2005 .write_memory
= cortex_m3_write_memory
,
2006 .bulk_write_memory
= cortex_m3_bulk_write_memory
,
2007 .checksum_memory
= armv7m_checksum_memory
,
2008 .blank_check_memory
= armv7m_blank_check_memory
,
2010 .run_algorithm
= armv7m_run_algorithm
,
2012 .add_breakpoint
= cortex_m3_add_breakpoint
,
2013 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
2014 .add_watchpoint
= cortex_m3_add_watchpoint
,
2015 .remove_watchpoint
= cortex_m3_remove_watchpoint
,
2017 .register_commands
= cortex_m3_register_commands
,
2018 .target_create
= cortex_m3_target_create
,
2019 .init_target
= cortex_m3_init_target
,
2020 .has_mmu
= cortex_m3_has_mmu
,
2021 .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)