David Brownell <david-b@pacbell.net>:
[openocd.git] / src / target / cortex_m3.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2006 by Magnus Lundin *
6 * lundin@mlu.mine.nu *
7 * *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
10 * *
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. *
15 * *
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. *
20 * *
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. *
25 * *
26 * *
27 * Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0) *
28 * *
29 ***************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "cortex_m3.h"
35 #include "target_request.h"
36 #include "target_type.h"
37 #include "arm_disassembler.h"
38
39
40 /* cli handling */
41 int cortex_m3_register_commands(struct command_context_s *cmd_ctx);
42 int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
43
44 /* forward declarations */
45 void cortex_m3_enable_breakpoints(struct target_s *target);
46 void cortex_m3_enable_watchpoints(struct target_s *target);
47 int cortex_m3_target_create(struct target_s *target, Jim_Interp *interp);
48 int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
49 int cortex_m3_quit(void);
50 int cortex_m3_load_core_reg_u32(target_t *target, enum armv7m_regtype type, uint32_t num, uint32_t *value);
51 int cortex_m3_store_core_reg_u32(target_t *target, enum armv7m_regtype type, uint32_t num, uint32_t value);
52 int cortex_m3_target_request_data(target_t *target, uint32_t size, uint8_t *buffer);
53 int cortex_m3_examine(struct target_s *target);
54
55 #ifdef ARMV7_GDB_HACKS
56 extern uint8_t armv7m_gdb_dummy_cpsr_value[];
57 extern reg_t armv7m_gdb_dummy_cpsr_reg;
58 #endif
59
60 target_type_t cortexm3_target =
61 {
62 .name = "cortex_m3",
63
64 .poll = cortex_m3_poll,
65 .arch_state = armv7m_arch_state,
66
67 .target_request_data = cortex_m3_target_request_data,
68
69 .halt = cortex_m3_halt,
70 .resume = cortex_m3_resume,
71 .step = cortex_m3_step,
72
73 .assert_reset = cortex_m3_assert_reset,
74 .deassert_reset = cortex_m3_deassert_reset,
75 .soft_reset_halt = cortex_m3_soft_reset_halt,
76
77 .get_gdb_reg_list = armv7m_get_gdb_reg_list,
78
79 .read_memory = cortex_m3_read_memory,
80 .write_memory = cortex_m3_write_memory,
81 .bulk_write_memory = cortex_m3_bulk_write_memory,
82 .checksum_memory = armv7m_checksum_memory,
83 .blank_check_memory = armv7m_blank_check_memory,
84
85 .run_algorithm = armv7m_run_algorithm,
86
87 .add_breakpoint = cortex_m3_add_breakpoint,
88 .remove_breakpoint = cortex_m3_remove_breakpoint,
89 .add_watchpoint = cortex_m3_add_watchpoint,
90 .remove_watchpoint = cortex_m3_remove_watchpoint,
91
92 .register_commands = cortex_m3_register_commands,
93 .target_create = cortex_m3_target_create,
94 .init_target = cortex_m3_init_target,
95 .examine = cortex_m3_examine,
96 .quit = cortex_m3_quit
97 };
98
99 int cortexm3_dap_read_coreregister_u32(swjdp_common_t *swjdp, uint32_t *value, int regnum)
100 {
101 int retval;
102 uint32_t dcrdr;
103
104 /* because the DCB_DCRDR is used for the emulated dcc channel
105 * we gave to save/restore the DCB_DCRDR when used */
106
107 mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);
108
109 swjdp->trans_mode = TRANS_MODE_COMPOSITE;
110
111 /* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */
112 dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
113 dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum);
114
115 /* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */
116 dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
117 dap_ap_read_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
118
119 mem_ap_write_u32(swjdp, DCB_DCRDR, dcrdr);
120 retval = swjdp_transaction_endcheck(swjdp);
121 return retval;
122 }
123
124 int cortexm3_dap_write_coreregister_u32(swjdp_common_t *swjdp, uint32_t value, int regnum)
125 {
126 int retval;
127 uint32_t dcrdr;
128
129 /* because the DCB_DCRDR is used for the emulated dcc channel
130 * we gave to save/restore the DCB_DCRDR when used */
131
132 mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);
133
134 swjdp->trans_mode = TRANS_MODE_COMPOSITE;
135
136 /* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */
137 dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
138 dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
139
140 /* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */
141 dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
142 dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR);
143
144 mem_ap_write_u32(swjdp, DCB_DCRDR, dcrdr);
145 retval = swjdp_transaction_endcheck(swjdp);
146 return retval;
147 }
148
149
150 int cortex_m3_write_debug_halt_mask(target_t *target, uint32_t mask_on, uint32_t mask_off)
151 {
152 /* get pointers to arch-specific information */
153 armv7m_common_t *armv7m = target->arch_info;
154 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
155 swjdp_common_t *swjdp = &armv7m->swjdp_info;
156
157 /* mask off status bits */
158 cortex_m3->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
159 /* create new register mask */
160 cortex_m3->dcb_dhcsr |= DBGKEY | C_DEBUGEN | mask_on;
161
162 return mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, cortex_m3->dcb_dhcsr);
163 }
164
165 int cortex_m3_clear_halt(target_t *target)
166 {
167 /* get pointers to arch-specific information */
168 armv7m_common_t *armv7m = target->arch_info;
169 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
170 swjdp_common_t *swjdp = &armv7m->swjdp_info;
171
172 /* clear step if any */
173 cortex_m3_write_debug_halt_mask(target, C_HALT, C_STEP);
174
175 /* Read Debug Fault Status Register */
176 mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
177 /* Write Debug Fault Status Register to enable processing to resume ?? Try with and without this !! */
178 mem_ap_write_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr);
179 LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m3->nvic_dfsr);
180
181 return ERROR_OK;
182 }
183
184 int cortex_m3_single_step_core(target_t *target)
185 {
186 /* get pointers to arch-specific information */
187 armv7m_common_t *armv7m = target->arch_info;
188 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
189 swjdp_common_t *swjdp = &armv7m->swjdp_info;
190 uint32_t dhcsr_save;
191
192 /* backup dhcsr reg */
193 dhcsr_save = cortex_m3->dcb_dhcsr;
194
195 /* mask interrupts if not done already */
196 if (!(cortex_m3->dcb_dhcsr & C_MASKINTS))
197 mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
198 mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN);
199 LOG_DEBUG(" ");
200
201 /* restore dhcsr reg */
202 cortex_m3->dcb_dhcsr = dhcsr_save;
203 cortex_m3_clear_halt(target);
204
205 return ERROR_OK;
206 }
207
208 int cortex_m3_exec_opcode(target_t *target,uint32_t opcode, int len /* MODE, r0_invalue, &r0_outvalue */)
209 {
210 /* get pointers to arch-specific information */
211 armv7m_common_t *armv7m = target->arch_info;
212 swjdp_common_t *swjdp = &armv7m->swjdp_info;
213 uint32_t savedram;
214 int retvalue;
215
216 mem_ap_read_u32(swjdp, 0x20000000, &savedram);
217 mem_ap_write_u32(swjdp, 0x20000000, opcode);
218 cortexm3_dap_write_coreregister_u32(swjdp, 0x20000000, 15);
219 cortex_m3_single_step_core(target);
220 armv7m->core_cache->reg_list[15].dirty = armv7m->core_cache->reg_list[15].valid;
221 retvalue = mem_ap_write_atomic_u32(swjdp, 0x20000000, savedram);
222
223 return retvalue;
224 }
225
226 #if 0
227 /* Enable interrupts */
228 int cortex_m3_cpsie(target_t *target, uint32_t IF)
229 {
230 return cortex_m3_exec_opcode(target, ARMV7M_T_CPSIE(IF), 2);
231 }
232
233 /* Disable interrupts */
234 int cortex_m3_cpsid(target_t *target, uint32_t IF)
235 {
236 return cortex_m3_exec_opcode(target, ARMV7M_T_CPSID(IF), 2);
237 }
238 #endif
239
240 int cortex_m3_endreset_event(target_t *target)
241 {
242 int i;
243 uint32_t dcb_demcr;
244
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;
248 swjdp_common_t *swjdp = &armv7m->swjdp_info;
249 cortex_m3_fp_comparator_t *fp_list = cortex_m3->fp_comparator_list;
250 cortex_m3_dwt_comparator_t *dwt_list = cortex_m3->dwt_comparator_list;
251
252 mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
253 LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "",dcb_demcr);
254
255 /* this regsiter is used for emulated dcc channel */
256 mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
257
258 /* Enable debug requests */
259 mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
260 if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
261 mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
262
263 /* clear any interrupt masking */
264 cortex_m3_write_debug_halt_mask(target, 0, C_MASKINTS);
265
266 /* Enable trace and dwt */
267 mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
268 /* Monitor bus faults */
269 mem_ap_write_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA);
270
271 /* Enable FPB */
272 target_write_u32(target, FP_CTRL, 3);
273 cortex_m3->fpb_enabled = 1;
274
275 /* Restore FPB registers */
276 for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++)
277 {
278 target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
279 }
280
281 /* Restore DWT registers */
282 for (i = 0; i < cortex_m3->dwt_num_comp; i++)
283 {
284 target_write_u32(target, dwt_list[i].dwt_comparator_address, dwt_list[i].comp);
285 target_write_u32(target, dwt_list[i].dwt_comparator_address | 0x4, dwt_list[i].mask);
286 target_write_u32(target, dwt_list[i].dwt_comparator_address | 0x8, dwt_list[i].function);
287 }
288 swjdp_transaction_endcheck(swjdp);
289
290 armv7m_invalidate_core_regs(target);
291
292 /* make sure we have latest dhcsr flags */
293 mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
294
295 return ERROR_OK;
296 }
297
298 int cortex_m3_examine_debug_reason(target_t *target)
299 {
300 /* get pointers to arch-specific information */
301 armv7m_common_t *armv7m = target->arch_info;
302 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
303
304 /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
305 /* only check the debug reason if we don't know it already */
306
307 if ((target->debug_reason != DBG_REASON_DBGRQ)
308 && (target->debug_reason != DBG_REASON_SINGLESTEP))
309 {
310 /* INCOMPLETE */
311
312 if (cortex_m3->nvic_dfsr & DFSR_BKPT)
313 {
314 target->debug_reason = DBG_REASON_BREAKPOINT;
315 if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
316 target->debug_reason = DBG_REASON_WPTANDBKPT;
317 }
318 else if (cortex_m3->nvic_dfsr & DFSR_DWTTRAP)
319 target->debug_reason = DBG_REASON_WATCHPOINT;
320 }
321
322 return ERROR_OK;
323 }
324
325 int cortex_m3_examine_exception_reason(target_t *target)
326 {
327 uint32_t shcsr, except_sr, cfsr = -1, except_ar = -1;
328
329 /* get pointers to arch-specific information */
330 armv7m_common_t *armv7m = target->arch_info;
331 swjdp_common_t *swjdp = &armv7m->swjdp_info;
332
333 mem_ap_read_u32(swjdp, NVIC_SHCSR, &shcsr);
334 switch (armv7m->exception_number)
335 {
336 case 2: /* NMI */
337 break;
338 case 3: /* Hard Fault */
339 mem_ap_read_atomic_u32(swjdp, NVIC_HFSR, &except_sr);
340 if (except_sr & 0x40000000)
341 {
342 mem_ap_read_u32(swjdp, NVIC_CFSR, &cfsr);
343 }
344 break;
345 case 4: /* Memory Management */
346 mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
347 mem_ap_read_u32(swjdp, NVIC_MMFAR, &except_ar);
348 break;
349 case 5: /* Bus Fault */
350 mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
351 mem_ap_read_u32(swjdp, NVIC_BFAR, &except_ar);
352 break;
353 case 6: /* Usage Fault */
354 mem_ap_read_u32(swjdp, NVIC_CFSR, &except_sr);
355 break;
356 case 11: /* SVCall */
357 break;
358 case 12: /* Debug Monitor */
359 mem_ap_read_u32(swjdp, NVIC_DFSR, &except_sr);
360 break;
361 case 14: /* PendSV */
362 break;
363 case 15: /* SysTick */
364 break;
365 default:
366 except_sr = 0;
367 break;
368 }
369 swjdp_transaction_endcheck(swjdp);
370 LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32 ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32 "", armv7m_exception_string(armv7m->exception_number), \
371 shcsr, except_sr, cfsr, except_ar);
372 return ERROR_OK;
373 }
374
375 int cortex_m3_debug_entry(target_t *target)
376 {
377 int i;
378 uint32_t xPSR;
379 int retval;
380
381 /* get pointers to arch-specific information */
382 armv7m_common_t *armv7m = target->arch_info;
383 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
384 swjdp_common_t *swjdp = &armv7m->swjdp_info;
385
386 LOG_DEBUG(" ");
387 if (armv7m->pre_debug_entry)
388 armv7m->pre_debug_entry(target);
389
390 cortex_m3_clear_halt(target);
391 mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
392
393 if ((retval = armv7m->examine_debug_reason(target)) != ERROR_OK)
394 return retval;
395
396 /* Examine target state and mode */
397 /* First load register acessible through core debug port*/
398 int num_regs = armv7m->core_cache->num_regs;
399
400 for (i = 0; i < num_regs; i++)
401 {
402 if (!armv7m->core_cache->reg_list[i].valid)
403 armv7m->read_core_reg(target, i);
404 }
405
406 xPSR = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32);
407
408 #ifdef ARMV7_GDB_HACKS
409 /* copy real xpsr reg for gdb, setting thumb bit */
410 buf_set_u32(armv7m_gdb_dummy_cpsr_value, 0, 32, xPSR);
411 buf_set_u32(armv7m_gdb_dummy_cpsr_value, 5, 1, 1);
412 armv7m_gdb_dummy_cpsr_reg.valid = armv7m->core_cache->reg_list[ARMV7M_xPSR].valid;
413 armv7m_gdb_dummy_cpsr_reg.dirty = armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty;
414 #endif
415
416 /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
417 if (xPSR & 0xf00)
418 {
419 armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = armv7m->core_cache->reg_list[ARMV7M_xPSR].valid;
420 cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
421 }
422
423 /* Are we in an exception handler */
424 if (xPSR & 0x1FF)
425 {
426 armv7m->core_mode = ARMV7M_MODE_HANDLER;
427 armv7m->exception_number = (xPSR & 0x1FF);
428 }
429 else
430 {
431 armv7m->core_mode = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1);
432 armv7m->exception_number = 0;
433 }
434
435 if (armv7m->exception_number)
436 {
437 cortex_m3_examine_exception_reason(target);
438 }
439
440 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
441 armv7m_mode_strings[armv7m->core_mode],
442 *(uint32_t*)(armv7m->core_cache->reg_list[15].value),
443 target_state_name(target));
444
445 if (armv7m->post_debug_entry)
446 armv7m->post_debug_entry(target);
447
448 return ERROR_OK;
449 }
450
451 int cortex_m3_poll(target_t *target)
452 {
453 int retval;
454 enum target_state prev_target_state = target->state;
455
456 /* get pointers to arch-specific information */
457 armv7m_common_t *armv7m = target->arch_info;
458 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
459 swjdp_common_t *swjdp = &armv7m->swjdp_info;
460
461 /* Read from Debug Halting Control and Status Register */
462 retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
463 if (retval != ERROR_OK)
464 {
465 target->state = TARGET_UNKNOWN;
466 return retval;
467 }
468
469 if (cortex_m3->dcb_dhcsr & S_RESET_ST)
470 {
471 /* check if still in reset */
472 mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
473
474 if (cortex_m3->dcb_dhcsr & S_RESET_ST)
475 {
476 target->state = TARGET_RESET;
477 return ERROR_OK;
478 }
479 }
480
481 if (target->state == TARGET_RESET)
482 {
483 /* Cannot switch context while running so endreset is called with target->state == TARGET_RESET */
484 LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32 "", cortex_m3->dcb_dhcsr);
485 cortex_m3_endreset_event(target);
486 target->state = TARGET_RUNNING;
487 prev_target_state = TARGET_RUNNING;
488 }
489
490 if (cortex_m3->dcb_dhcsr & S_HALT)
491 {
492 target->state = TARGET_HALTED;
493
494 if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET))
495 {
496 if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
497 return retval;
498
499 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
500 }
501 if (prev_target_state == TARGET_DEBUG_RUNNING)
502 {
503 LOG_DEBUG(" ");
504 if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
505 return retval;
506
507 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
508 }
509 }
510
511 /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
512 * How best to model low power modes?
513 */
514
515 if (target->state == TARGET_UNKNOWN)
516 {
517 /* check if processor is retiring instructions */
518 if (cortex_m3->dcb_dhcsr & S_RETIRE_ST)
519 {
520 target->state = TARGET_RUNNING;
521 return ERROR_OK;
522 }
523 }
524
525 return ERROR_OK;
526 }
527
528 int cortex_m3_halt(target_t *target)
529 {
530 LOG_DEBUG("target->state: %s",
531 target_state_name(target));
532
533 if (target->state == TARGET_HALTED)
534 {
535 LOG_DEBUG("target was already halted");
536 return ERROR_OK;
537 }
538
539 if (target->state == TARGET_UNKNOWN)
540 {
541 LOG_WARNING("target was in unknown state when halt was requested");
542 }
543
544 if (target->state == TARGET_RESET)
545 {
546 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
547 {
548 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
549 return ERROR_TARGET_FAILURE;
550 }
551 else
552 {
553 /* we came here in a reset_halt or reset_init sequence
554 * debug entry was already prepared in cortex_m3_prepare_reset_halt()
555 */
556 target->debug_reason = DBG_REASON_DBGRQ;
557
558 return ERROR_OK;
559 }
560 }
561
562 /* Write to Debug Halting Control and Status Register */
563 cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
564
565 target->debug_reason = DBG_REASON_DBGRQ;
566
567 return ERROR_OK;
568 }
569
570 int cortex_m3_soft_reset_halt(struct target_s *target)
571 {
572 /* get pointers to arch-specific information */
573 armv7m_common_t *armv7m = target->arch_info;
574 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
575 swjdp_common_t *swjdp = &armv7m->swjdp_info;
576 uint32_t dcb_dhcsr = 0;
577 int retval, timeout = 0;
578
579 /* Enter debug state on reset, cf. end_reset_event() */
580 mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
581
582 /* Request a reset */
583 mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET);
584 target->state = TARGET_RESET;
585
586 /* registers are now invalid */
587 armv7m_invalidate_core_regs(target);
588
589 while (timeout < 100)
590 {
591 retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
592 if (retval == ERROR_OK)
593 {
594 mem_ap_read_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
595 if ((dcb_dhcsr & S_HALT) && (cortex_m3->nvic_dfsr & DFSR_VCATCH))
596 {
597 LOG_DEBUG("system reset-halted, dcb_dhcsr 0x%" PRIx32 ", nvic_dfsr 0x%" PRIx32 "", dcb_dhcsr, cortex_m3->nvic_dfsr);
598 cortex_m3_poll(target);
599 return ERROR_OK;
600 }
601 else
602 LOG_DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%" PRIx32 ", %i ms", dcb_dhcsr, timeout);
603 }
604 timeout++;
605 alive_sleep(1);
606 }
607
608 return ERROR_OK;
609 }
610
611 int cortex_m3_resume(struct target_s *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
612 {
613 /* get pointers to arch-specific information */
614 armv7m_common_t *armv7m = target->arch_info;
615 breakpoint_t *breakpoint = NULL;
616 uint32_t resume_pc;
617
618 if (target->state != TARGET_HALTED)
619 {
620 LOG_WARNING("target not halted");
621 return ERROR_TARGET_NOT_HALTED;
622 }
623
624 if (!debug_execution)
625 {
626 target_free_all_working_areas(target);
627 cortex_m3_enable_breakpoints(target);
628 cortex_m3_enable_watchpoints(target);
629 }
630
631 if (debug_execution)
632 {
633 /* Disable interrupts */
634 /* We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
635 * This is probably the same issue as Cortex-M3 Errata 377493:
636 * C_MASKINTS in parallel with disabled interrupts can cause local faults to not be taken. */
637 buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
638 armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
639 armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
640
641 /* Make sure we are in Thumb mode */
642 buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
643 buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24));
644 armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
645 armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
646 }
647
648 /* current = 1: continue on current pc, otherwise continue at <address> */
649 if (!current)
650 {
651 buf_set_u32(armv7m->core_cache->reg_list[15].value, 0, 32, address);
652 armv7m->core_cache->reg_list[15].dirty = 1;
653 armv7m->core_cache->reg_list[15].valid = 1;
654 }
655
656 resume_pc = buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32);
657
658 armv7m_restore_context(target);
659
660 /* the front-end may request us not to handle breakpoints */
661 if (handle_breakpoints)
662 {
663 /* Single step past breakpoint at current address */
664 if ((breakpoint = breakpoint_find(target, resume_pc)))
665 {
666 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
667 breakpoint->address,
668 breakpoint->unique_id );
669 cortex_m3_unset_breakpoint(target, breakpoint);
670 cortex_m3_single_step_core(target);
671 cortex_m3_set_breakpoint(target, breakpoint);
672 }
673 }
674
675 /* Restart core */
676 cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
677
678 target->debug_reason = DBG_REASON_NOTHALTED;
679
680 /* registers are now invalid */
681 armv7m_invalidate_core_regs(target);
682 if (!debug_execution)
683 {
684 target->state = TARGET_RUNNING;
685 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
686 LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
687 }
688 else
689 {
690 target->state = TARGET_DEBUG_RUNNING;
691 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
692 LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
693 }
694
695 return ERROR_OK;
696 }
697
698 /* int irqstepcount = 0; */
699 int cortex_m3_step(struct target_s *target, int current, uint32_t address, int handle_breakpoints)
700 {
701 /* get pointers to arch-specific information */
702 armv7m_common_t *armv7m = target->arch_info;
703 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
704 swjdp_common_t *swjdp = &armv7m->swjdp_info;
705 breakpoint_t *breakpoint = NULL;
706
707 if (target->state != TARGET_HALTED)
708 {
709 LOG_WARNING("target not halted");
710 return ERROR_TARGET_NOT_HALTED;
711 }
712
713 /* current = 1: continue on current pc, otherwise continue at <address> */
714 if (!current)
715 buf_set_u32(armv7m->core_cache->reg_list[15].value, 0, 32, address);
716
717 /* the front-end may request us not to handle breakpoints */
718 if (handle_breakpoints)
719 if ((breakpoint = breakpoint_find(target, buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32))))
720 cortex_m3_unset_breakpoint(target, breakpoint);
721
722 target->debug_reason = DBG_REASON_SINGLESTEP;
723
724 armv7m_restore_context(target);
725
726 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
727
728 /* set step and clear halt */
729 cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT);
730 mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
731
732 /* registers are now invalid */
733 armv7m_invalidate_core_regs(target);
734
735 if (breakpoint)
736 cortex_m3_set_breakpoint(target, breakpoint);
737
738 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32 " nvic_icsr = 0x%" PRIx32 "", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
739
740 cortex_m3_debug_entry(target);
741 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
742
743 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32 " nvic_icsr = 0x%" PRIx32 "", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
744 return ERROR_OK;
745 }
746
747 int cortex_m3_assert_reset(target_t *target)
748 {
749 armv7m_common_t *armv7m = target->arch_info;
750 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
751 swjdp_common_t *swjdp = &armv7m->swjdp_info;
752 int assert_srst = 1;
753
754 LOG_DEBUG("target->state: %s",
755 target_state_name(target));
756
757 enum reset_types jtag_reset_config = jtag_get_reset_config();
758 if (!(jtag_reset_config & RESET_HAS_SRST))
759 {
760 LOG_ERROR("Can't assert SRST");
761 return ERROR_FAIL;
762 }
763
764 /* Enable debug requests */
765 mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
766 if (!(cortex_m3->dcb_dhcsr & C_DEBUGEN))
767 mem_ap_write_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
768
769 mem_ap_write_u32(swjdp, DCB_DCRDR, 0);
770
771 if (!target->reset_halt)
772 {
773 /* Set/Clear C_MASKINTS in a separate operation */
774 if (cortex_m3->dcb_dhcsr & C_MASKINTS)
775 mem_ap_write_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT);
776
777 /* clear any debug flags before resuming */
778 cortex_m3_clear_halt(target);
779
780 /* clear C_HALT in dhcsr reg */
781 cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
782
783 /* Enter debug state on reset, cf. end_reset_event() */
784 mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
785 }
786 else
787 {
788 /* Enter debug state on reset, cf. end_reset_event() */
789 mem_ap_write_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
790 }
791
792 /* following hack is to handle luminary reset
793 * when srst is asserted the luminary device seesm to also clear the debug registers
794 * which does not match the armv7 debug TRM */
795
796 if (strcmp(target->variant, "lm3s") == 0)
797 {
798 /* get revision of lm3s target, only early silicon has this issue
799 * Fury Rev B, DustDevil Rev B, Tempest all ok */
800
801 uint32_t did0;
802
803 if (target_read_u32(target, 0x400fe000, &did0) == ERROR_OK)
804 {
805 switch ((did0 >> 16) & 0xff)
806 {
807 case 0:
808 /* all Sandstorm suffer issue */
809 assert_srst = 0;
810 break;
811
812 case 1:
813 case 3:
814 /* only Fury/DustDevil rev A suffer reset problems */
815 if (((did0 >> 8) & 0xff) == 0)
816 assert_srst = 0;
817 break;
818 }
819 }
820 }
821
822 if (assert_srst)
823 {
824 /* default to asserting srst */
825 if (jtag_reset_config & RESET_SRST_PULLS_TRST)
826 {
827 jtag_add_reset(1, 1);
828 }
829 else
830 {
831 jtag_add_reset(0, 1);
832 }
833 }
834 else
835 {
836 /* this causes the luminary device to reset using the watchdog */
837 mem_ap_write_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
838 LOG_DEBUG("Using Luminary Reset: SYSRESETREQ");
839
840 {
841 /* I do not know why this is necessary, but it fixes strange effects
842 * (step/resume cause a NMI after reset) on LM3S6918 -- Michael Schwingen */
843 uint32_t tmp;
844 mem_ap_read_atomic_u32(swjdp, NVIC_AIRCR, &tmp);
845 }
846 }
847
848 target->state = TARGET_RESET;
849 jtag_add_sleep(50000);
850
851 armv7m_invalidate_core_regs(target);
852
853 if (target->reset_halt)
854 {
855 int retval;
856 if ((retval = target_halt(target)) != ERROR_OK)
857 return retval;
858 }
859
860 return ERROR_OK;
861 }
862
863 int cortex_m3_deassert_reset(target_t *target)
864 {
865 LOG_DEBUG("target->state: %s",
866 target_state_name(target));
867
868 /* deassert reset lines */
869 jtag_add_reset(0, 0);
870
871 return ERROR_OK;
872 }
873
874 void cortex_m3_enable_breakpoints(struct target_s *target)
875 {
876 breakpoint_t *breakpoint = target->breakpoints;
877
878 /* set any pending breakpoints */
879 while (breakpoint)
880 {
881 if (breakpoint->set == 0)
882 cortex_m3_set_breakpoint(target, breakpoint);
883 breakpoint = breakpoint->next;
884 }
885 }
886
887 int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
888 {
889 int retval;
890 int fp_num = 0;
891 uint32_t hilo;
892
893 /* get pointers to arch-specific information */
894 armv7m_common_t *armv7m = target->arch_info;
895 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
896
897 cortex_m3_fp_comparator_t * comparator_list = cortex_m3->fp_comparator_list;
898
899 if (breakpoint->set)
900 {
901 LOG_WARNING("breakpoint (BPID: %d) already set", breakpoint->unique_id);
902 return ERROR_OK;
903 }
904
905 if (cortex_m3->auto_bp_type)
906 {
907 breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
908 }
909
910 if (breakpoint->type == BKPT_HARD)
911 {
912 while (comparator_list[fp_num].used && (fp_num < cortex_m3->fp_num_code))
913 fp_num++;
914 if (fp_num >= cortex_m3->fp_num_code)
915 {
916 LOG_DEBUG("ERROR Can not find free FP Comparator");
917 LOG_WARNING("ERROR Can not find free FP Comparator");
918 exit(-1);
919 }
920 breakpoint->set = fp_num + 1;
921 hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
922 comparator_list[fp_num].used = 1;
923 comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1;
924 target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value);
925 LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32 "", fp_num, comparator_list[fp_num].fpcr_value);
926 if (!cortex_m3->fpb_enabled)
927 {
928 LOG_DEBUG("FPB wasn't enabled, do it now");
929 target_write_u32(target, FP_CTRL, 3);
930 }
931 }
932 else if (breakpoint->type == BKPT_SOFT)
933 {
934 uint8_t code[4];
935 buf_set_u32(code, 0, 32, ARMV7M_T_BKPT(0x11));
936 if ((retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK)
937 {
938 return retval;
939 }
940 if ((retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code)) != ERROR_OK)
941 {
942 return retval;
943 }
944 breakpoint->set = 0x11; /* Any nice value but 0 */
945 }
946
947 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
948 breakpoint->unique_id,
949 (int)(breakpoint->type),
950 breakpoint->address,
951 breakpoint->length,
952 breakpoint->set);
953
954 return ERROR_OK;
955 }
956
957 int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
958 {
959 int retval;
960 /* get pointers to arch-specific information */
961 armv7m_common_t *armv7m = target->arch_info;
962 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
963 cortex_m3_fp_comparator_t * comparator_list = cortex_m3->fp_comparator_list;
964
965 if (!breakpoint->set)
966 {
967 LOG_WARNING("breakpoint not set");
968 return ERROR_OK;
969 }
970
971 LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
972 breakpoint->unique_id,
973 (int)(breakpoint->type),
974 breakpoint->address,
975 breakpoint->length,
976 breakpoint->set);
977
978 if (breakpoint->type == BKPT_HARD)
979 {
980 int fp_num = breakpoint->set - 1;
981 if ((fp_num < 0) || (fp_num >= cortex_m3->fp_num_code))
982 {
983 LOG_DEBUG("Invalid FP Comparator number in breakpoint");
984 return ERROR_OK;
985 }
986 comparator_list[fp_num].used = 0;
987 comparator_list[fp_num].fpcr_value = 0;
988 target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value);
989 }
990 else
991 {
992 /* restore original instruction (kept in target endianness) */
993 if (breakpoint->length == 4)
994 {
995 if ((retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
996 {
997 return retval;
998 }
999 }
1000 else
1001 {
1002 if ((retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
1003 {
1004 return retval;
1005 }
1006 }
1007 }
1008 breakpoint->set = 0;
1009
1010 return ERROR_OK;
1011 }
1012
1013 int cortex_m3_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
1014 {
1015 /* get pointers to arch-specific information */
1016 armv7m_common_t *armv7m = target->arch_info;
1017 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
1018
1019 if (cortex_m3->auto_bp_type)
1020 {
1021 breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
1022 #ifdef ARMV7_GDB_HACKS
1023 if (breakpoint->length != 2) {
1024 /* XXX Hack: Replace all breakpoints with length != 2 with
1025 * a hardware breakpoint. */
1026 breakpoint->type = BKPT_HARD;
1027 breakpoint->length = 2;
1028 }
1029 #endif
1030 }
1031
1032 if ((breakpoint->type == BKPT_HARD) && (breakpoint->address >= 0x20000000))
1033 {
1034 LOG_INFO("flash patch comparator requested outside code memory region");
1035 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1036 }
1037
1038 if ((breakpoint->type == BKPT_SOFT) && (breakpoint->address < 0x20000000))
1039 {
1040 LOG_INFO("soft breakpoint requested in code (flash) memory region");
1041 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1042 }
1043
1044 if ((breakpoint->type == BKPT_HARD) && (cortex_m3->fp_code_available < 1))
1045 {
1046 LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
1047 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1048 }
1049
1050 if ((breakpoint->length != 2))
1051 {
1052 LOG_INFO("only breakpoints of two bytes length supported");
1053 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1054 }
1055
1056 if (breakpoint->type == BKPT_HARD)
1057 cortex_m3->fp_code_available--;
1058 cortex_m3_set_breakpoint(target, breakpoint);
1059
1060 return ERROR_OK;
1061 }
1062
1063 int cortex_m3_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
1064 {
1065 /* get pointers to arch-specific information */
1066 armv7m_common_t *armv7m = target->arch_info;
1067 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
1068
1069 if (target->state != TARGET_HALTED)
1070 {
1071 LOG_WARNING("target not halted");
1072 return ERROR_TARGET_NOT_HALTED;
1073 }
1074
1075 if (cortex_m3->auto_bp_type)
1076 {
1077 breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
1078 }
1079
1080 if (breakpoint->set)
1081 {
1082 cortex_m3_unset_breakpoint(target, breakpoint);
1083 }
1084
1085 if (breakpoint->type == BKPT_HARD)
1086 cortex_m3->fp_code_available++;
1087
1088 return ERROR_OK;
1089 }
1090
1091 int cortex_m3_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
1092 {
1093 int dwt_num = 0;
1094 uint32_t mask, temp;
1095
1096 /* get pointers to arch-specific information */
1097 armv7m_common_t *armv7m = target->arch_info;
1098 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
1099 cortex_m3_dwt_comparator_t * comparator_list = cortex_m3->dwt_comparator_list;
1100
1101 if (watchpoint->set)
1102 {
1103 LOG_WARNING("watchpoint (%d) already set", watchpoint->unique_id );
1104 return ERROR_OK;
1105 }
1106
1107 if (watchpoint->mask == 0xffffffffu)
1108 {
1109 while (comparator_list[dwt_num].used && (dwt_num < cortex_m3->dwt_num_comp))
1110 dwt_num++;
1111 if (dwt_num >= cortex_m3->dwt_num_comp)
1112 {
1113 LOG_DEBUG("ERROR Can not find free DWT Comparator");
1114 LOG_WARNING("ERROR Can not find free DWT Comparator");
1115 return -1;
1116 }
1117 watchpoint->set = dwt_num + 1;
1118 mask = 0;
1119 temp = watchpoint->length;
1120 while (temp > 1)
1121 {
1122 temp = temp / 2;
1123 mask++;
1124 }
1125 comparator_list[dwt_num].used = 1;
1126 comparator_list[dwt_num].comp = watchpoint->address;
1127 comparator_list[dwt_num].mask = mask;
1128 comparator_list[dwt_num].function = watchpoint->rw + 5;
1129 target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address, comparator_list[dwt_num].comp);
1130 target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address | 0x4, comparator_list[dwt_num].mask);
1131 target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address | 0x8, comparator_list[dwt_num].function);
1132 LOG_DEBUG("dwt_num %i 0x%" PRIx32 " 0x%" PRIx32 " 0x%" PRIx32 "", dwt_num, comparator_list[dwt_num].comp, comparator_list[dwt_num].mask, comparator_list[dwt_num].function);
1133 }
1134 else
1135 {
1136 /* Move this test to add_watchpoint */
1137 LOG_WARNING("Cannot watch data values (id: %d)",
1138 watchpoint->unique_id );
1139 return ERROR_OK;
1140 }
1141 LOG_DEBUG("Watchpoint (ID: %d) address: 0x%08" PRIx32 " set=%d ",
1142 watchpoint->unique_id, watchpoint->address, watchpoint->set );
1143 return ERROR_OK;
1144
1145 }
1146
1147 int cortex_m3_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
1148 {
1149 /* get pointers to arch-specific information */
1150 armv7m_common_t *armv7m = target->arch_info;
1151 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
1152 cortex_m3_dwt_comparator_t * comparator_list = cortex_m3->dwt_comparator_list;
1153 int dwt_num;
1154
1155 if (!watchpoint->set)
1156 {
1157 LOG_WARNING("watchpoint (wpid: %d) not set", watchpoint->unique_id );
1158 return ERROR_OK;
1159 }
1160
1161 LOG_DEBUG("Watchpoint (ID: %d) address: 0x%08" PRIx32 " set=%d ",
1162 watchpoint->unique_id, watchpoint->address,watchpoint->set );
1163
1164 dwt_num = watchpoint->set - 1;
1165
1166 if ((dwt_num < 0) || (dwt_num >= cortex_m3->dwt_num_comp))
1167 {
1168 LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
1169 return ERROR_OK;
1170 }
1171 comparator_list[dwt_num].used = 0;
1172 comparator_list[dwt_num].function = 0;
1173 target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address | 0x8, comparator_list[dwt_num].function);
1174
1175 watchpoint->set = 0;
1176
1177 return ERROR_OK;
1178 }
1179
1180 int cortex_m3_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
1181 {
1182 /* get pointers to arch-specific information */
1183 armv7m_common_t *armv7m = target->arch_info;
1184 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
1185
1186 if (target->state != TARGET_HALTED)
1187 {
1188 LOG_WARNING("target not halted");
1189 return ERROR_TARGET_NOT_HALTED;
1190 }
1191
1192 if (cortex_m3->dwt_comp_available < 1)
1193 {
1194 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1195 }
1196
1197 if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
1198 {
1199 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1200 }
1201
1202 cortex_m3->dwt_comp_available--;
1203 LOG_DEBUG("dwt_comp_available: %d", cortex_m3->dwt_comp_available);
1204
1205 return ERROR_OK;
1206 }
1207
1208 int cortex_m3_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
1209 {
1210 /* get pointers to arch-specific information */
1211 armv7m_common_t *armv7m = target->arch_info;
1212 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
1213
1214 if (target->state != TARGET_HALTED)
1215 {
1216 LOG_WARNING("target not halted");
1217 return ERROR_TARGET_NOT_HALTED;
1218 }
1219
1220 if (watchpoint->set)
1221 {
1222 cortex_m3_unset_watchpoint(target, watchpoint);
1223 }
1224
1225 cortex_m3->dwt_comp_available++;
1226 LOG_DEBUG("dwt_comp_available: %d", cortex_m3->dwt_comp_available);
1227
1228 return ERROR_OK;
1229 }
1230
1231 void cortex_m3_enable_watchpoints(struct target_s *target)
1232 {
1233 watchpoint_t *watchpoint = target->watchpoints;
1234
1235 /* set any pending watchpoints */
1236 while (watchpoint)
1237 {
1238 if (watchpoint->set == 0)
1239 cortex_m3_set_watchpoint(target, watchpoint);
1240 watchpoint = watchpoint->next;
1241 }
1242 }
1243
1244 int cortex_m3_load_core_reg_u32(struct target_s *target, enum armv7m_regtype type, uint32_t num, uint32_t * value)
1245 {
1246 int retval;
1247 /* get pointers to arch-specific information */
1248 armv7m_common_t *armv7m = target->arch_info;
1249 swjdp_common_t *swjdp = &armv7m->swjdp_info;
1250
1251 /* NOTE: we "know" here that the register identifiers used
1252 * in the v7m header match the Cortex-M3 Debug Core Register
1253 * Selector values for R0..R15, xPSR, MSP, and PSP.
1254 */
1255 switch (num) {
1256 case 0 ... 18:
1257 /* read a normal core register */
1258 retval = cortexm3_dap_read_coreregister_u32(swjdp, value, num);
1259
1260 if (retval != ERROR_OK)
1261 {
1262 LOG_ERROR("JTAG failure %i",retval);
1263 return ERROR_JTAG_DEVICE_ERROR;
1264 }
1265 LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "",(int)num,*value);
1266 break;
1267
1268 case ARMV7M_PRIMASK:
1269 case ARMV7M_BASEPRI:
1270 case ARMV7M_FAULTMASK:
1271 case ARMV7M_CONTROL:
1272 /* Cortex-M3 packages these four registers as bitfields
1273 * in one Debug Core register. So say r0 and r2 docs;
1274 * it was removed from r1 docs, but still works.
1275 */
1276 cortexm3_dap_read_coreregister_u32(swjdp, value, 20);
1277
1278 switch (num)
1279 {
1280 case ARMV7M_PRIMASK:
1281 *value = buf_get_u32((uint8_t*)value, 0, 1);
1282 break;
1283
1284 case ARMV7M_BASEPRI:
1285 *value = buf_get_u32((uint8_t*)value, 8, 8);
1286 break;
1287
1288 case ARMV7M_FAULTMASK:
1289 *value = buf_get_u32((uint8_t*)value, 16, 1);
1290 break;
1291
1292 case ARMV7M_CONTROL:
1293 *value = buf_get_u32((uint8_t*)value, 24, 2);
1294 break;
1295 }
1296
1297 LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value);
1298 break;
1299
1300 default:
1301 return ERROR_INVALID_ARGUMENTS;
1302 }
1303
1304 return ERROR_OK;
1305 }
1306
1307 int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype type, uint32_t num, uint32_t value)
1308 {
1309 int retval;
1310 uint32_t reg;
1311
1312 /* get pointers to arch-specific information */
1313 armv7m_common_t *armv7m = target->arch_info;
1314 swjdp_common_t *swjdp = &armv7m->swjdp_info;
1315
1316 #ifdef ARMV7_GDB_HACKS
1317 /* If the LR register is being modified, make sure it will put us
1318 * in "thumb" mode, or an INVSTATE exception will occur. This is a
1319 * hack to deal with the fact that gdb will sometimes "forge"
1320 * return addresses, and doesn't set the LSB correctly (i.e., when
1321 * printing expressions containing function calls, it sets LR = 0.)
1322 * Valid exception return codes have bit 0 set too.
1323 */
1324 if (num == ARMV7M_R14)
1325 value |= 0x01;
1326 #endif
1327
1328 /* NOTE: we "know" here that the register identifiers used
1329 * in the v7m header match the Cortex-M3 Debug Core Register
1330 * Selector values for R0..R15, xPSR, MSP, and PSP.
1331 */
1332 switch (num) {
1333 case 0 ... 18:
1334 retval = cortexm3_dap_write_coreregister_u32(swjdp, value, num);
1335 if (retval != ERROR_OK)
1336 {
1337 LOG_ERROR("JTAG failure %i", retval);
1338 armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
1339 return ERROR_JTAG_DEVICE_ERROR;
1340 }
1341 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
1342 break;
1343
1344 case ARMV7M_PRIMASK:
1345 case ARMV7M_BASEPRI:
1346 case ARMV7M_FAULTMASK:
1347 case ARMV7M_CONTROL:
1348 /* Cortex-M3 packages these four registers as bitfields
1349 * in one Debug Core register. So say r0 and r2 docs;
1350 * it was removed from r1 docs, but still works.
1351 */
1352 cortexm3_dap_read_coreregister_u32(swjdp, &reg, 20);
1353
1354 switch (num)
1355 {
1356 case ARMV7M_PRIMASK:
1357 buf_set_u32((uint8_t*)&reg, 0, 1, value);
1358 break;
1359
1360 case ARMV7M_BASEPRI:
1361 buf_set_u32((uint8_t*)&reg, 8, 8, value);
1362 break;
1363
1364 case ARMV7M_FAULTMASK:
1365 buf_set_u32((uint8_t*)&reg, 16, 1, value);
1366 break;
1367
1368 case ARMV7M_CONTROL:
1369 buf_set_u32((uint8_t*)&reg, 24, 2, value);
1370 break;
1371 }
1372
1373 cortexm3_dap_write_coreregister_u32(swjdp, reg, 20);
1374
1375 LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value);
1376 break;
1377
1378 default:
1379 return ERROR_INVALID_ARGUMENTS;
1380 }
1381
1382 return ERROR_OK;
1383 }
1384
1385 int cortex_m3_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
1386 {
1387 /* get pointers to arch-specific information */
1388 armv7m_common_t *armv7m = target->arch_info;
1389 swjdp_common_t *swjdp = &armv7m->swjdp_info;
1390 int retval;
1391
1392 /* sanitize arguments */
1393 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
1394 return ERROR_INVALID_ARGUMENTS;
1395
1396 /* cortex_m3 handles unaligned memory access */
1397
1398 switch (size)
1399 {
1400 case 4:
1401 retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
1402 break;
1403 case 2:
1404 retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
1405 break;
1406 case 1:
1407 retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
1408 break;
1409 default:
1410 LOG_ERROR("BUG: we shouldn't get here");
1411 exit(-1);
1412 }
1413
1414 return retval;
1415 }
1416
1417 int cortex_m3_write_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
1418 {
1419 /* get pointers to arch-specific information */
1420 armv7m_common_t *armv7m = target->arch_info;
1421 swjdp_common_t *swjdp = &armv7m->swjdp_info;
1422 int retval;
1423
1424 /* sanitize arguments */
1425 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
1426 return ERROR_INVALID_ARGUMENTS;
1427
1428 switch (size)
1429 {
1430 case 4:
1431 retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
1432 break;
1433 case 2:
1434 retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
1435 break;
1436 case 1:
1437 retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
1438 break;
1439 default:
1440 LOG_ERROR("BUG: we shouldn't get here");
1441 exit(-1);
1442 }
1443
1444 return retval;
1445 }
1446
1447 int cortex_m3_bulk_write_memory(target_t *target, uint32_t address, uint32_t count, uint8_t *buffer)
1448 {
1449 return cortex_m3_write_memory(target, address, 4, count, buffer);
1450 }
1451
1452 void cortex_m3_build_reg_cache(target_t *target)
1453 {
1454 armv7m_build_reg_cache(target);
1455 }
1456
1457 int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
1458 {
1459 cortex_m3_build_reg_cache(target);
1460 return ERROR_OK;
1461 }
1462
1463 int cortex_m3_examine(struct target_s *target)
1464 {
1465 int retval;
1466 uint32_t cpuid, fpcr, dwtcr, ictr;
1467 int i;
1468
1469 /* get pointers to arch-specific information */
1470 armv7m_common_t *armv7m = target->arch_info;
1471 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
1472 swjdp_common_t *swjdp = &armv7m->swjdp_info;
1473
1474 if ((retval = ahbap_debugport_init(swjdp)) != ERROR_OK)
1475 return retval;
1476
1477 if (!target_was_examined(target))
1478 {
1479 target_set_examined(target);
1480
1481 /* Read from Device Identification Registers */
1482 if ((retval = target_read_u32(target, CPUID, &cpuid)) != ERROR_OK)
1483 return retval;
1484
1485 if (((cpuid >> 4) & 0xc3f) == 0xc23)
1486 LOG_DEBUG("CORTEX-M3 processor detected");
1487 LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
1488
1489 target_read_u32(target, NVIC_ICTR, &ictr);
1490 cortex_m3->intlinesnum = (ictr & 0x1F) + 1;
1491 cortex_m3->intsetenable = calloc(cortex_m3->intlinesnum, 4);
1492 for (i = 0; i < cortex_m3->intlinesnum; i++)
1493 {
1494 target_read_u32(target, NVIC_ISE0 + 4 * i, cortex_m3->intsetenable + i);
1495 LOG_DEBUG("interrupt enable[%i] = 0x%8.8" PRIx32 "", i, cortex_m3->intsetenable[i]);
1496 }
1497
1498 /* Setup FPB */
1499 target_read_u32(target, FP_CTRL, &fpcr);
1500 cortex_m3->auto_bp_type = 1;
1501 cortex_m3->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF); /* bits [14:12] and [7:4] */
1502 cortex_m3->fp_num_lit = (fpcr >> 8) & 0xF;
1503 cortex_m3->fp_code_available = cortex_m3->fp_num_code;
1504 cortex_m3->fp_comparator_list = calloc(cortex_m3->fp_num_code + cortex_m3->fp_num_lit, sizeof(cortex_m3_fp_comparator_t));
1505 cortex_m3->fpb_enabled = fpcr & 1;
1506 for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++)
1507 {
1508 cortex_m3->fp_comparator_list[i].type = (i < cortex_m3->fp_num_code) ? FPCR_CODE : FPCR_LITERAL;
1509 cortex_m3->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i;
1510 }
1511 LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i", fpcr, cortex_m3->fp_num_code, cortex_m3->fp_num_lit);
1512
1513 /* Setup DWT */
1514 target_read_u32(target, DWT_CTRL, &dwtcr);
1515 cortex_m3->dwt_num_comp = (dwtcr >> 28) & 0xF;
1516 cortex_m3->dwt_comp_available = cortex_m3->dwt_num_comp;
1517 cortex_m3->dwt_comparator_list = calloc(cortex_m3->dwt_num_comp, sizeof(cortex_m3_dwt_comparator_t));
1518 for (i = 0; i < cortex_m3->dwt_num_comp; i++)
1519 {
1520 cortex_m3->dwt_comparator_list[i].dwt_comparator_address = DWT_COMP0 + 0x10 * i;
1521 }
1522 }
1523
1524 return ERROR_OK;
1525 }
1526
1527 int cortex_m3_quit(void)
1528 {
1529
1530 return ERROR_OK;
1531 }
1532
1533 int cortex_m3_dcc_read(swjdp_common_t *swjdp, uint8_t *value, uint8_t *ctrl)
1534 {
1535 uint16_t dcrdr;
1536
1537 mem_ap_read_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
1538 *ctrl = (uint8_t)dcrdr;
1539 *value = (uint8_t)(dcrdr >> 8);
1540
1541 LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
1542
1543 /* write ack back to software dcc register
1544 * signify we have read data */
1545 if (dcrdr & (1 << 0))
1546 {
1547 dcrdr = 0;
1548 mem_ap_write_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
1549 }
1550
1551 return ERROR_OK;
1552 }
1553
1554 int cortex_m3_target_request_data(target_t *target, uint32_t size, uint8_t *buffer)
1555 {
1556 armv7m_common_t *armv7m = target->arch_info;
1557 swjdp_common_t *swjdp = &armv7m->swjdp_info;
1558 uint8_t data;
1559 uint8_t ctrl;
1560 uint32_t i;
1561
1562 for (i = 0; i < (size * 4); i++)
1563 {
1564 cortex_m3_dcc_read(swjdp, &data, &ctrl);
1565 buffer[i] = data;
1566 }
1567
1568 return ERROR_OK;
1569 }
1570
1571 int cortex_m3_handle_target_request(void *priv)
1572 {
1573 target_t *target = priv;
1574 if (!target_was_examined(target))
1575 return ERROR_OK;
1576 armv7m_common_t *armv7m = target->arch_info;
1577 swjdp_common_t *swjdp = &armv7m->swjdp_info;
1578
1579 if (!target->dbg_msg_enabled)
1580 return ERROR_OK;
1581
1582 if (target->state == TARGET_RUNNING)
1583 {
1584 uint8_t data;
1585 uint8_t ctrl;
1586
1587 cortex_m3_dcc_read(swjdp, &data, &ctrl);
1588
1589 /* check if we have data */
1590 if (ctrl & (1 << 0))
1591 {
1592 uint32_t request;
1593
1594 /* we assume target is quick enough */
1595 request = data;
1596 cortex_m3_dcc_read(swjdp, &data, &ctrl);
1597 request |= (data << 8);
1598 cortex_m3_dcc_read(swjdp, &data, &ctrl);
1599 request |= (data << 16);
1600 cortex_m3_dcc_read(swjdp, &data, &ctrl);
1601 request |= (data << 24);
1602 target_request(target, request);
1603 }
1604 }
1605
1606 return ERROR_OK;
1607 }
1608
1609 int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, jtag_tap_t *tap)
1610 {
1611 int retval;
1612 armv7m_common_t *armv7m;
1613 armv7m = &cortex_m3->armv7m;
1614
1615 armv7m_init_arch_info(target, armv7m);
1616
1617 /* prepare JTAG information for the new target */
1618 cortex_m3->jtag_info.tap = tap;
1619 cortex_m3->jtag_info.scann_size = 4;
1620
1621 armv7m->swjdp_info.dp_select_value = -1;
1622 armv7m->swjdp_info.ap_csw_value = -1;
1623 armv7m->swjdp_info.ap_tar_value = -1;
1624 armv7m->swjdp_info.jtag_info = &cortex_m3->jtag_info;
1625 armv7m->swjdp_info.memaccess_tck = 8;
1626 armv7m->swjdp_info.tar_autoincr_block = (1 << 12); /* Cortex-M3 has 4096 bytes autoincrement range */
1627
1628 /* initialize arch-specific breakpoint handling */
1629
1630 cortex_m3->common_magic = CORTEX_M3_COMMON_MAGIC;
1631 cortex_m3->arch_info = NULL;
1632
1633 /* register arch-specific functions */
1634 armv7m->examine_debug_reason = cortex_m3_examine_debug_reason;
1635
1636 armv7m->pre_debug_entry = NULL;
1637 armv7m->post_debug_entry = NULL;
1638
1639 armv7m->pre_restore_context = NULL;
1640 armv7m->post_restore_context = NULL;
1641
1642 armv7m->arch_info = cortex_m3;
1643 armv7m->load_core_reg_u32 = cortex_m3_load_core_reg_u32;
1644 armv7m->store_core_reg_u32 = cortex_m3_store_core_reg_u32;
1645
1646 target_register_timer_callback(cortex_m3_handle_target_request, 1, 1, target);
1647
1648 if ((retval = arm_jtag_setup_connection(&cortex_m3->jtag_info)) != ERROR_OK)
1649 {
1650 return retval;
1651 }
1652
1653 return ERROR_OK;
1654 }
1655
1656 int cortex_m3_target_create(struct target_s *target, Jim_Interp *interp)
1657 {
1658 cortex_m3_common_t *cortex_m3 = calloc(1,sizeof(cortex_m3_common_t));
1659
1660 cortex_m3_init_arch_info(target, cortex_m3, target->tap);
1661
1662 return ERROR_OK;
1663 }
1664
1665 /*
1666 * REVISIT Thumb2 disassembly should work for all ARMv7 cores, as well
1667 * as at least ARM-1156T2. The interesting thing about Cortex-M is
1668 * that *only* Thumb2 disassembly matters. There are also some small
1669 * additions to Thumb2 that are specific to ARMv7-M.
1670 */
1671 static int
1672 handle_cortex_m3_disassemble_command(struct command_context_s *cmd_ctx,
1673 char *cmd, char **args, int argc)
1674 {
1675 int retval = ERROR_OK;
1676 target_t *target = get_current_target(cmd_ctx);
1677 uint32_t address;
1678 unsigned long count;
1679 arm_instruction_t cur_instruction;
1680
1681 if (argc != 2) {
1682 command_print(cmd_ctx,
1683 "usage: cortex_m3 disassemble <address> <count>");
1684 return ERROR_OK;
1685 }
1686
1687 errno = 0;
1688 address = strtoul(args[0], NULL, 0);
1689 if (errno)
1690 return ERROR_FAIL;
1691 count = strtoul(args[1], NULL, 0);
1692 if (errno)
1693 return ERROR_FAIL;
1694
1695 while (count--) {
1696 retval = thumb2_opcode(target, address, &cur_instruction);
1697 if (retval != ERROR_OK)
1698 return retval;
1699 command_print(cmd_ctx, "%s", cur_instruction.text);
1700 address += cur_instruction.instruction_size;
1701 }
1702
1703 return ERROR_OK;
1704 }
1705
1706 int cortex_m3_register_commands(struct command_context_s *cmd_ctx)
1707 {
1708 int retval;
1709 command_t *cortex_m3_cmd;
1710
1711 retval = armv7m_register_commands(cmd_ctx);
1712
1713 cortex_m3_cmd = register_command(cmd_ctx, NULL, "cortex_m3",
1714 NULL, COMMAND_ANY, "cortex_m3 specific commands");
1715
1716 register_command(cmd_ctx, cortex_m3_cmd, "disassemble",
1717 handle_cortex_m3_disassemble_command, COMMAND_EXEC,
1718 "disassemble Thumb2 instructions <address> <count>");
1719 register_command(cmd_ctx, cortex_m3_cmd, "maskisr",
1720 handle_cortex_m3_mask_interrupts_command, COMMAND_EXEC,
1721 "mask cortex_m3 interrupts ['on'|'off']");
1722
1723 return retval;
1724 }
1725
1726 int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1727 {
1728 target_t *target = get_current_target(cmd_ctx);
1729 armv7m_common_t *armv7m = target->arch_info;
1730 cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
1731
1732 if (target->state != TARGET_HALTED)
1733 {
1734 command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
1735 return ERROR_OK;
1736 }
1737
1738 if (argc > 0)
1739 {
1740 if (!strcmp(args[0], "on"))
1741 {
1742 cortex_m3_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0);
1743 }
1744 else if (!strcmp(args[0], "off"))
1745 {
1746 cortex_m3_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
1747 }
1748 else
1749 {
1750 command_print(cmd_ctx, "usage: cortex_m3 maskisr ['on'|'off']");
1751 }
1752 }
1753
1754 command_print(cmd_ctx, "cortex_m3 interrupt mask %s",
1755 (cortex_m3->dcb_dhcsr & C_MASKINTS) ? "on" : "off");
1756
1757 return ERROR_OK;
1758 }

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)