cortex_m: Discover the AP to use, just like Cortex-A
[openocd.git] / src / target / cortex_m.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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 "jtag/interface.h"
35 #include "breakpoints.h"
36 #include "cortex_m.h"
37 #include "target_request.h"
38 #include "target_type.h"
39 #include "arm_disassembler.h"
40 #include "register.h"
41 #include "arm_opcodes.h"
42 #include "arm_semihosting.h"
43 #include <helper/time_support.h>
44
45 /* NOTE: most of this should work fine for the Cortex-M1 and
46 * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
47 * Some differences: M0/M1 doesn't have FBP remapping or the
48 * DWT tracing/profiling support. (So the cycle counter will
49 * not be usable; the other stuff isn't currently used here.)
50 *
51 * Although there are some workarounds for errata seen only in r0p0
52 * silicon, such old parts are hard to find and thus not much tested
53 * any longer.
54 */
55
56 /**
57 * Returns the type of a break point required by address location
58 */
59 #define BKPT_TYPE_BY_ADDR(addr) ((addr) < 0x20000000 ? BKPT_HARD : BKPT_SOFT)
60
61 /* forward declarations */
62 static int cortex_m_store_core_reg_u32(struct target *target,
63 uint32_t num, uint32_t value);
64 static void cortex_m_dwt_free(struct target *target);
65
66 static int cortexm_dap_read_coreregister_u32(struct target *target,
67 uint32_t *value, int regnum)
68 {
69 struct armv7m_common *armv7m = target_to_armv7m(target);
70 struct adiv5_dap *swjdp = armv7m->arm.dap;
71 int retval;
72 uint32_t dcrdr;
73
74 /* because the DCB_DCRDR is used for the emulated dcc channel
75 * we have to save/restore the DCB_DCRDR when used */
76 if (target->dbg_msg_enabled) {
77 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, DCB_DCRDR, &dcrdr);
78 if (retval != ERROR_OK)
79 return retval;
80 }
81
82 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DCRSR, regnum);
83 if (retval != ERROR_OK)
84 return retval;
85
86 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DCRDR, value);
87 if (retval != ERROR_OK)
88 return retval;
89
90 if (target->dbg_msg_enabled) {
91 /* restore DCB_DCRDR - this needs to be in a separate
92 * transaction otherwise the emulated DCC channel breaks */
93 if (retval == ERROR_OK)
94 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, DCB_DCRDR, dcrdr);
95 }
96
97 return retval;
98 }
99
100 static int cortexm_dap_write_coreregister_u32(struct target *target,
101 uint32_t value, int regnum)
102 {
103 struct armv7m_common *armv7m = target_to_armv7m(target);
104 struct adiv5_dap *swjdp = armv7m->arm.dap;
105 int retval;
106 uint32_t dcrdr;
107
108 /* because the DCB_DCRDR is used for the emulated dcc channel
109 * we have to save/restore the DCB_DCRDR when used */
110 if (target->dbg_msg_enabled) {
111 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, DCB_DCRDR, &dcrdr);
112 if (retval != ERROR_OK)
113 return retval;
114 }
115
116 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DCRDR, value);
117 if (retval != ERROR_OK)
118 return retval;
119
120 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, DCB_DCRSR, regnum | DCRSR_WnR);
121 if (retval != ERROR_OK)
122 return retval;
123
124 if (target->dbg_msg_enabled) {
125 /* restore DCB_DCRDR - this needs to be in a seperate
126 * transaction otherwise the emulated DCC channel breaks */
127 if (retval == ERROR_OK)
128 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, DCB_DCRDR, dcrdr);
129 }
130
131 return retval;
132 }
133
134 static int cortex_m_write_debug_halt_mask(struct target *target,
135 uint32_t mask_on, uint32_t mask_off)
136 {
137 struct cortex_m_common *cortex_m = target_to_cm(target);
138 struct armv7m_common *armv7m = &cortex_m->armv7m;
139 struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
140
141 /* mask off status bits */
142 cortex_m->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
143 /* create new register mask */
144 cortex_m->dcb_dhcsr |= DBGKEY | C_DEBUGEN | mask_on;
145
146 return mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, cortex_m->dcb_dhcsr);
147 }
148
149 static int cortex_m_clear_halt(struct target *target)
150 {
151 struct cortex_m_common *cortex_m = target_to_cm(target);
152 struct armv7m_common *armv7m = &cortex_m->armv7m;
153 struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
154 int retval;
155
156 /* clear step if any */
157 cortex_m_write_debug_halt_mask(target, C_HALT, C_STEP);
158
159 /* Read Debug Fault Status Register */
160 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, NVIC_DFSR, &cortex_m->nvic_dfsr);
161 if (retval != ERROR_OK)
162 return retval;
163
164 /* Clear Debug Fault Status */
165 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, NVIC_DFSR, cortex_m->nvic_dfsr);
166 if (retval != ERROR_OK)
167 return retval;
168 LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m->nvic_dfsr);
169
170 return ERROR_OK;
171 }
172
173 static int cortex_m_single_step_core(struct target *target)
174 {
175 struct cortex_m_common *cortex_m = target_to_cm(target);
176 struct armv7m_common *armv7m = &cortex_m->armv7m;
177 struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
178 uint32_t dhcsr_save;
179 int retval;
180
181 /* backup dhcsr reg */
182 dhcsr_save = cortex_m->dcb_dhcsr;
183
184 /* Mask interrupts before clearing halt, if done already. This avoids
185 * Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
186 * HALT can put the core into an unknown state.
187 */
188 if (!(cortex_m->dcb_dhcsr & C_MASKINTS)) {
189 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR,
190 DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
191 if (retval != ERROR_OK)
192 return retval;
193 }
194 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR,
195 DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN);
196 if (retval != ERROR_OK)
197 return retval;
198 LOG_DEBUG(" ");
199
200 /* restore dhcsr reg */
201 cortex_m->dcb_dhcsr = dhcsr_save;
202 cortex_m_clear_halt(target);
203
204 return ERROR_OK;
205 }
206
207 static int cortex_m_enable_fpb(struct target *target)
208 {
209 int retval = target_write_u32(target, FP_CTRL, 3);
210 if (retval != ERROR_OK)
211 return retval;
212
213 /* check the fpb is actually enabled */
214 uint32_t fpctrl;
215 retval = target_read_u32(target, FP_CTRL, &fpctrl);
216 if (retval != ERROR_OK)
217 return retval;
218
219 if (fpctrl & 1)
220 return ERROR_OK;
221
222 return ERROR_FAIL;
223 }
224
225 static int cortex_m_endreset_event(struct target *target)
226 {
227 int i;
228 int retval;
229 uint32_t dcb_demcr;
230 struct cortex_m_common *cortex_m = target_to_cm(target);
231 struct armv7m_common *armv7m = &cortex_m->armv7m;
232 struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
233 struct cortex_m_fp_comparator *fp_list = cortex_m->fp_comparator_list;
234 struct cortex_m_dwt_comparator *dwt_list = cortex_m->dwt_comparator_list;
235
236 /* REVISIT The four debug monitor bits are currently ignored... */
237 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DEMCR, &dcb_demcr);
238 if (retval != ERROR_OK)
239 return retval;
240 LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "", dcb_demcr);
241
242 /* this register is used for emulated dcc channel */
243 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DCRDR, 0);
244 if (retval != ERROR_OK)
245 return retval;
246
247 /* Enable debug requests */
248 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
249 if (retval != ERROR_OK)
250 return retval;
251 if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
252 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN);
253 if (retval != ERROR_OK)
254 return retval;
255 }
256
257 /* clear any interrupt masking */
258 cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS);
259
260 /* Enable features controlled by ITM and DWT blocks, and catch only
261 * the vectors we were told to pay attention to.
262 *
263 * Target firmware is responsible for all fault handling policy
264 * choices *EXCEPT* explicitly scripted overrides like "vector_catch"
265 * or manual updates to the NVIC SHCSR and CCR registers.
266 */
267 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DEMCR, TRCENA | armv7m->demcr);
268 if (retval != ERROR_OK)
269 return retval;
270
271 /* Paranoia: evidently some (early?) chips don't preserve all the
272 * debug state (including FBP, DWT, etc) across reset...
273 */
274
275 /* Enable FPB */
276 retval = cortex_m_enable_fpb(target);
277 if (retval != ERROR_OK) {
278 LOG_ERROR("Failed to enable the FPB");
279 return retval;
280 }
281
282 cortex_m->fpb_enabled = 1;
283
284 /* Restore FPB registers */
285 for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) {
286 retval = target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
287 if (retval != ERROR_OK)
288 return retval;
289 }
290
291 /* Restore DWT registers */
292 for (i = 0; i < cortex_m->dwt_num_comp; i++) {
293 retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 0,
294 dwt_list[i].comp);
295 if (retval != ERROR_OK)
296 return retval;
297 retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 4,
298 dwt_list[i].mask);
299 if (retval != ERROR_OK)
300 return retval;
301 retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 8,
302 dwt_list[i].function);
303 if (retval != ERROR_OK)
304 return retval;
305 }
306 retval = dap_run(swjdp);
307 if (retval != ERROR_OK)
308 return retval;
309
310 register_cache_invalidate(armv7m->arm.core_cache);
311
312 /* make sure we have latest dhcsr flags */
313 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
314
315 return retval;
316 }
317
318 static int cortex_m_examine_debug_reason(struct target *target)
319 {
320 struct cortex_m_common *cortex_m = target_to_cm(target);
321
322 /* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason
323 * only check the debug reason if we don't know it already */
324
325 if ((target->debug_reason != DBG_REASON_DBGRQ)
326 && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
327 if (cortex_m->nvic_dfsr & DFSR_BKPT) {
328 target->debug_reason = DBG_REASON_BREAKPOINT;
329 if (cortex_m->nvic_dfsr & DFSR_DWTTRAP)
330 target->debug_reason = DBG_REASON_WPTANDBKPT;
331 } else if (cortex_m->nvic_dfsr & DFSR_DWTTRAP)
332 target->debug_reason = DBG_REASON_WATCHPOINT;
333 else if (cortex_m->nvic_dfsr & DFSR_VCATCH)
334 target->debug_reason = DBG_REASON_BREAKPOINT;
335 else /* EXTERNAL, HALTED */
336 target->debug_reason = DBG_REASON_UNDEFINED;
337 }
338
339 return ERROR_OK;
340 }
341
342 static int cortex_m_examine_exception_reason(struct target *target)
343 {
344 uint32_t shcsr = 0, except_sr = 0, cfsr = -1, except_ar = -1;
345 struct armv7m_common *armv7m = target_to_armv7m(target);
346 struct adiv5_dap *swjdp = armv7m->arm.dap;
347 int retval;
348
349 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, NVIC_SHCSR, &shcsr);
350 if (retval != ERROR_OK)
351 return retval;
352 switch (armv7m->exception_number) {
353 case 2: /* NMI */
354 break;
355 case 3: /* Hard Fault */
356 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, NVIC_HFSR, &except_sr);
357 if (retval != ERROR_OK)
358 return retval;
359 if (except_sr & 0x40000000) {
360 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, NVIC_CFSR, &cfsr);
361 if (retval != ERROR_OK)
362 return retval;
363 }
364 break;
365 case 4: /* Memory Management */
366 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, NVIC_CFSR, &except_sr);
367 if (retval != ERROR_OK)
368 return retval;
369 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, NVIC_MMFAR, &except_ar);
370 if (retval != ERROR_OK)
371 return retval;
372 break;
373 case 5: /* Bus Fault */
374 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, NVIC_CFSR, &except_sr);
375 if (retval != ERROR_OK)
376 return retval;
377 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, NVIC_BFAR, &except_ar);
378 if (retval != ERROR_OK)
379 return retval;
380 break;
381 case 6: /* Usage Fault */
382 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, NVIC_CFSR, &except_sr);
383 if (retval != ERROR_OK)
384 return retval;
385 break;
386 case 11: /* SVCall */
387 break;
388 case 12: /* Debug Monitor */
389 retval = mem_ap_sel_read_u32(swjdp, armv7m->debug_ap, NVIC_DFSR, &except_sr);
390 if (retval != ERROR_OK)
391 return retval;
392 break;
393 case 14: /* PendSV */
394 break;
395 case 15: /* SysTick */
396 break;
397 default:
398 except_sr = 0;
399 break;
400 }
401 retval = dap_run(swjdp);
402 if (retval == ERROR_OK)
403 LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32
404 ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32,
405 armv7m_exception_string(armv7m->exception_number),
406 shcsr, except_sr, cfsr, except_ar);
407 return retval;
408 }
409
410 static int cortex_m_debug_entry(struct target *target)
411 {
412 int i;
413 uint32_t xPSR;
414 int retval;
415 struct cortex_m_common *cortex_m = target_to_cm(target);
416 struct armv7m_common *armv7m = &cortex_m->armv7m;
417 struct arm *arm = &armv7m->arm;
418 struct adiv5_dap *swjdp = armv7m->arm.dap;
419 struct reg *r;
420
421 LOG_DEBUG(" ");
422
423 cortex_m_clear_halt(target);
424 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
425 if (retval != ERROR_OK)
426 return retval;
427
428 retval = armv7m->examine_debug_reason(target);
429 if (retval != ERROR_OK)
430 return retval;
431
432 /* Examine target state and mode
433 * First load register accessible through core debug port */
434 int num_regs = arm->core_cache->num_regs;
435
436 for (i = 0; i < num_regs; i++) {
437 r = &armv7m->arm.core_cache->reg_list[i];
438 if (!r->valid)
439 arm->read_core_reg(target, r, i, ARM_MODE_ANY);
440 }
441
442 r = arm->cpsr;
443 xPSR = buf_get_u32(r->value, 0, 32);
444
445 /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
446 if (xPSR & 0xf00) {
447 r->dirty = r->valid;
448 cortex_m_store_core_reg_u32(target, 16, xPSR & ~0xff);
449 }
450
451 /* Are we in an exception handler */
452 if (xPSR & 0x1FF) {
453 armv7m->exception_number = (xPSR & 0x1FF);
454
455 arm->core_mode = ARM_MODE_HANDLER;
456 arm->map = armv7m_msp_reg_map;
457 } else {
458 unsigned control = buf_get_u32(arm->core_cache
459 ->reg_list[ARMV7M_CONTROL].value, 0, 2);
460
461 /* is this thread privileged? */
462 arm->core_mode = control & 1
463 ? ARM_MODE_USER_THREAD
464 : ARM_MODE_THREAD;
465
466 /* which stack is it using? */
467 if (control & 2)
468 arm->map = armv7m_psp_reg_map;
469 else
470 arm->map = armv7m_msp_reg_map;
471
472 armv7m->exception_number = 0;
473 }
474
475 if (armv7m->exception_number)
476 cortex_m_examine_exception_reason(target);
477
478 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
479 arm_mode_name(arm->core_mode),
480 buf_get_u32(arm->pc->value, 0, 32),
481 target_state_name(target));
482
483 if (armv7m->post_debug_entry) {
484 retval = armv7m->post_debug_entry(target);
485 if (retval != ERROR_OK)
486 return retval;
487 }
488
489 return ERROR_OK;
490 }
491
492 static int cortex_m_poll(struct target *target)
493 {
494 int detected_failure = ERROR_OK;
495 int retval = ERROR_OK;
496 enum target_state prev_target_state = target->state;
497 struct cortex_m_common *cortex_m = target_to_cm(target);
498 struct armv7m_common *armv7m = &cortex_m->armv7m;
499 struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
500
501 /* Read from Debug Halting Control and Status Register */
502 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
503 if (retval != ERROR_OK) {
504 target->state = TARGET_UNKNOWN;
505 return retval;
506 }
507
508 /* Recover from lockup. See ARMv7-M architecture spec,
509 * section B1.5.15 "Unrecoverable exception cases".
510 */
511 if (cortex_m->dcb_dhcsr & S_LOCKUP) {
512 LOG_ERROR("%s -- clearing lockup after double fault",
513 target_name(target));
514 cortex_m_write_debug_halt_mask(target, C_HALT, 0);
515 target->debug_reason = DBG_REASON_DBGRQ;
516
517 /* We have to execute the rest (the "finally" equivalent, but
518 * still throw this exception again).
519 */
520 detected_failure = ERROR_FAIL;
521
522 /* refresh status bits */
523 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
524 if (retval != ERROR_OK)
525 return retval;
526 }
527
528 if (cortex_m->dcb_dhcsr & S_RESET_ST) {
529 target->state = TARGET_RESET;
530 return ERROR_OK;
531 }
532
533 if (target->state == TARGET_RESET) {
534 /* Cannot switch context while running so endreset is
535 * called with target->state == TARGET_RESET
536 */
537 LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32,
538 cortex_m->dcb_dhcsr);
539 retval = cortex_m_endreset_event(target);
540 if (retval != ERROR_OK) {
541 target->state = TARGET_UNKNOWN;
542 return retval;
543 }
544 target->state = TARGET_RUNNING;
545 prev_target_state = TARGET_RUNNING;
546 }
547
548 if (cortex_m->dcb_dhcsr & S_HALT) {
549 target->state = TARGET_HALTED;
550
551 if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) {
552 retval = cortex_m_debug_entry(target);
553 if (retval != ERROR_OK)
554 return retval;
555
556 if (arm_semihosting(target, &retval) != 0)
557 return retval;
558
559 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
560 }
561 if (prev_target_state == TARGET_DEBUG_RUNNING) {
562 LOG_DEBUG(" ");
563 retval = cortex_m_debug_entry(target);
564 if (retval != ERROR_OK)
565 return retval;
566
567 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
568 }
569 }
570
571 /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
572 * How best to model low power modes?
573 */
574
575 if (target->state == TARGET_UNKNOWN) {
576 /* check if processor is retiring instructions */
577 if (cortex_m->dcb_dhcsr & S_RETIRE_ST) {
578 target->state = TARGET_RUNNING;
579 retval = ERROR_OK;
580 }
581 }
582
583 /* Did we detect a failure condition that we cleared? */
584 if (detected_failure != ERROR_OK)
585 retval = detected_failure;
586 return retval;
587 }
588
589 static int cortex_m_halt(struct target *target)
590 {
591 LOG_DEBUG("target->state: %s",
592 target_state_name(target));
593
594 if (target->state == TARGET_HALTED) {
595 LOG_DEBUG("target was already halted");
596 return ERROR_OK;
597 }
598
599 if (target->state == TARGET_UNKNOWN)
600 LOG_WARNING("target was in unknown state when halt was requested");
601
602 if (target->state == TARGET_RESET) {
603 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
604 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
605 return ERROR_TARGET_FAILURE;
606 } else {
607 /* we came here in a reset_halt or reset_init sequence
608 * debug entry was already prepared in cortex_m3_assert_reset()
609 */
610 target->debug_reason = DBG_REASON_DBGRQ;
611
612 return ERROR_OK;
613 }
614 }
615
616 /* Write to Debug Halting Control and Status Register */
617 cortex_m_write_debug_halt_mask(target, C_HALT, 0);
618
619 target->debug_reason = DBG_REASON_DBGRQ;
620
621 return ERROR_OK;
622 }
623
624 static int cortex_m_soft_reset_halt(struct target *target)
625 {
626 struct cortex_m_common *cortex_m = target_to_cm(target);
627 struct armv7m_common *armv7m = &cortex_m->armv7m;
628 struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
629 uint32_t dcb_dhcsr = 0;
630 int retval, timeout = 0;
631
632 /* soft_reset_halt is deprecated on cortex_m as the same functionality
633 * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset'
634 * As this reset only used VC_CORERESET it would only ever reset the cortex_m
635 * core, not the peripherals */
636 LOG_WARNING("soft_reset_halt is deprecated, please use 'reset halt' instead.");
637
638 /* Enter debug state on reset; restore DEMCR in endreset_event() */
639 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DEMCR,
640 TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
641 if (retval != ERROR_OK)
642 return retval;
643
644 /* Request a core-only reset */
645 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, NVIC_AIRCR,
646 AIRCR_VECTKEY | AIRCR_VECTRESET);
647 if (retval != ERROR_OK)
648 return retval;
649 target->state = TARGET_RESET;
650
651 /* registers are now invalid */
652 register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
653
654 while (timeout < 100) {
655 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, &dcb_dhcsr);
656 if (retval == ERROR_OK) {
657 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, NVIC_DFSR,
658 &cortex_m->nvic_dfsr);
659 if (retval != ERROR_OK)
660 return retval;
661 if ((dcb_dhcsr & S_HALT)
662 && (cortex_m->nvic_dfsr & DFSR_VCATCH)) {
663 LOG_DEBUG("system reset-halted, DHCSR 0x%08x, "
664 "DFSR 0x%08x",
665 (unsigned) dcb_dhcsr,
666 (unsigned) cortex_m->nvic_dfsr);
667 cortex_m_poll(target);
668 /* FIXME restore user's vector catch config */
669 return ERROR_OK;
670 } else
671 LOG_DEBUG("waiting for system reset-halt, "
672 "DHCSR 0x%08x, %d ms",
673 (unsigned) dcb_dhcsr, timeout);
674 }
675 timeout++;
676 alive_sleep(1);
677 }
678
679 return ERROR_OK;
680 }
681
682 void cortex_m_enable_breakpoints(struct target *target)
683 {
684 struct breakpoint *breakpoint = target->breakpoints;
685
686 /* set any pending breakpoints */
687 while (breakpoint) {
688 if (!breakpoint->set)
689 cortex_m_set_breakpoint(target, breakpoint);
690 breakpoint = breakpoint->next;
691 }
692 }
693
694 static int cortex_m_resume(struct target *target, int current,
695 uint32_t address, int handle_breakpoints, int debug_execution)
696 {
697 struct armv7m_common *armv7m = target_to_armv7m(target);
698 struct breakpoint *breakpoint = NULL;
699 uint32_t resume_pc;
700 struct reg *r;
701
702 if (target->state != TARGET_HALTED) {
703 LOG_WARNING("target not halted");
704 return ERROR_TARGET_NOT_HALTED;
705 }
706
707 if (!debug_execution) {
708 target_free_all_working_areas(target);
709 cortex_m_enable_breakpoints(target);
710 cortex_m_enable_watchpoints(target);
711 }
712
713 if (debug_execution) {
714 r = armv7m->arm.core_cache->reg_list + ARMV7M_PRIMASK;
715
716 /* Disable interrupts */
717 /* We disable interrupts in the PRIMASK register instead of
718 * masking with C_MASKINTS. This is probably the same issue
719 * as Cortex-M3 Erratum 377493 (fixed in r1p0): C_MASKINTS
720 * in parallel with disabled interrupts can cause local faults
721 * to not be taken.
722 *
723 * REVISIT this clearly breaks non-debug execution, since the
724 * PRIMASK register state isn't saved/restored... workaround
725 * by never resuming app code after debug execution.
726 */
727 buf_set_u32(r->value, 0, 1, 1);
728 r->dirty = true;
729 r->valid = true;
730
731 /* Make sure we are in Thumb mode */
732 r = armv7m->arm.cpsr;
733 buf_set_u32(r->value, 24, 1, 1);
734 r->dirty = true;
735 r->valid = true;
736 }
737
738 /* current = 1: continue on current pc, otherwise continue at <address> */
739 r = armv7m->arm.pc;
740 if (!current) {
741 buf_set_u32(r->value, 0, 32, address);
742 r->dirty = true;
743 r->valid = true;
744 }
745
746 /* if we halted last time due to a bkpt instruction
747 * then we have to manually step over it, otherwise
748 * the core will break again */
749
750 if (!breakpoint_find(target, buf_get_u32(r->value, 0, 32))
751 && !debug_execution)
752 armv7m_maybe_skip_bkpt_inst(target, NULL);
753
754 resume_pc = buf_get_u32(r->value, 0, 32);
755
756 armv7m_restore_context(target);
757
758 /* the front-end may request us not to handle breakpoints */
759 if (handle_breakpoints) {
760 /* Single step past breakpoint at current address */
761 breakpoint = breakpoint_find(target, resume_pc);
762 if (breakpoint) {
763 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")",
764 breakpoint->address,
765 breakpoint->unique_id);
766 cortex_m_unset_breakpoint(target, breakpoint);
767 cortex_m_single_step_core(target);
768 cortex_m_set_breakpoint(target, breakpoint);
769 }
770 }
771
772 /* Restart core */
773 cortex_m_write_debug_halt_mask(target, 0, C_HALT);
774
775 target->debug_reason = DBG_REASON_NOTHALTED;
776
777 /* registers are now invalid */
778 register_cache_invalidate(armv7m->arm.core_cache);
779
780 if (!debug_execution) {
781 target->state = TARGET_RUNNING;
782 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
783 LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
784 } else {
785 target->state = TARGET_DEBUG_RUNNING;
786 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
787 LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
788 }
789
790 return ERROR_OK;
791 }
792
793 /* int irqstepcount = 0; */
794 static int cortex_m_step(struct target *target, int current,
795 uint32_t address, int handle_breakpoints)
796 {
797 struct cortex_m_common *cortex_m = target_to_cm(target);
798 struct armv7m_common *armv7m = &cortex_m->armv7m;
799 struct adiv5_dap *swjdp = armv7m->arm.dap;
800 struct breakpoint *breakpoint = NULL;
801 struct reg *pc = armv7m->arm.pc;
802 bool bkpt_inst_found = false;
803 int retval;
804 bool isr_timed_out = false;
805
806 if (target->state != TARGET_HALTED) {
807 LOG_WARNING("target not halted");
808 return ERROR_TARGET_NOT_HALTED;
809 }
810
811 /* current = 1: continue on current pc, otherwise continue at <address> */
812 if (!current)
813 buf_set_u32(pc->value, 0, 32, address);
814
815 uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
816
817 /* the front-end may request us not to handle breakpoints */
818 if (handle_breakpoints) {
819 breakpoint = breakpoint_find(target, pc_value);
820 if (breakpoint)
821 cortex_m_unset_breakpoint(target, breakpoint);
822 }
823
824 armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
825
826 target->debug_reason = DBG_REASON_SINGLESTEP;
827
828 armv7m_restore_context(target);
829
830 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
831
832 /* if no bkpt instruction is found at pc then we can perform
833 * a normal step, otherwise we have to manually step over the bkpt
834 * instruction - as such simulate a step */
835 if (bkpt_inst_found == false) {
836 /* Automatic ISR masking mode off: Just step over the next instruction */
837 if ((cortex_m->isrmasking_mode != CORTEX_M_ISRMASK_AUTO))
838 cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
839 else {
840 /* Process interrupts during stepping in a way they don't interfere
841 * debugging.
842 *
843 * Principle:
844 *
845 * Set a temporary break point at the current pc and let the core run
846 * with interrupts enabled. Pending interrupts get served and we run
847 * into the breakpoint again afterwards. Then we step over the next
848 * instruction with interrupts disabled.
849 *
850 * If the pending interrupts don't complete within time, we leave the
851 * core running. This may happen if the interrupts trigger faster
852 * than the core can process them or the handler doesn't return.
853 *
854 * If no more breakpoints are available we simply do a step with
855 * interrupts enabled.
856 *
857 */
858
859 /* 2012-09-29 ph
860 *
861 * If a break point is already set on the lower half word then a break point on
862 * the upper half word will not break again when the core is restarted. So we
863 * just step over the instruction with interrupts disabled.
864 *
865 * The documentation has no information about this, it was found by observation
866 * on STM32F1 and STM32F2. Proper explanation welcome. STM32F0 dosen't seem to
867 * suffer from this problem.
868 *
869 * To add some confusion: pc_value has bit 0 always set, while the breakpoint
870 * address has it always cleared. The former is done to indicate thumb mode
871 * to gdb.
872 *
873 */
874 if ((pc_value & 0x02) && breakpoint_find(target, pc_value & ~0x03)) {
875 LOG_DEBUG("Stepping over next instruction with interrupts disabled");
876 cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0);
877 cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
878 /* Re-enable interrupts */
879 cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
880 }
881 else {
882
883 /* Set a temporary break point */
884 if (breakpoint)
885 retval = cortex_m_set_breakpoint(target, breakpoint);
886 else
887 retval = breakpoint_add(target, pc_value, 2, BKPT_TYPE_BY_ADDR(pc_value));
888 bool tmp_bp_set = (retval == ERROR_OK);
889
890 /* No more breakpoints left, just do a step */
891 if (!tmp_bp_set)
892 cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
893 else {
894 /* Start the core */
895 LOG_DEBUG("Starting core to serve pending interrupts");
896 int64_t t_start = timeval_ms();
897 cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP);
898
899 /* Wait for pending handlers to complete or timeout */
900 do {
901 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap,
902 DCB_DHCSR,
903 &cortex_m->dcb_dhcsr);
904 if (retval != ERROR_OK) {
905 target->state = TARGET_UNKNOWN;
906 return retval;
907 }
908 isr_timed_out = ((timeval_ms() - t_start) > 500);
909 } while (!((cortex_m->dcb_dhcsr & S_HALT) || isr_timed_out));
910
911 /* only remove breakpoint if we created it */
912 if (breakpoint)
913 cortex_m_unset_breakpoint(target, breakpoint);
914 else {
915 /* Remove the temporary breakpoint */
916 breakpoint_remove(target, pc_value);
917 }
918
919 if (isr_timed_out) {
920 LOG_DEBUG("Interrupt handlers didn't complete within time, "
921 "leaving target running");
922 } else {
923 /* Step over next instruction with interrupts disabled */
924 cortex_m_write_debug_halt_mask(target,
925 C_HALT | C_MASKINTS,
926 0);
927 cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
928 /* Re-enable interrupts */
929 cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
930 }
931 }
932 }
933 }
934 }
935
936 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
937 if (retval != ERROR_OK)
938 return retval;
939
940 /* registers are now invalid */
941 register_cache_invalidate(armv7m->arm.core_cache);
942
943 if (breakpoint)
944 cortex_m_set_breakpoint(target, breakpoint);
945
946 if (isr_timed_out) {
947 /* Leave the core running. The user has to stop execution manually. */
948 target->debug_reason = DBG_REASON_NOTHALTED;
949 target->state = TARGET_RUNNING;
950 return ERROR_OK;
951 }
952
953 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
954 " nvic_icsr = 0x%" PRIx32,
955 cortex_m->dcb_dhcsr, cortex_m->nvic_icsr);
956
957 retval = cortex_m_debug_entry(target);
958 if (retval != ERROR_OK)
959 return retval;
960 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
961
962 LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
963 " nvic_icsr = 0x%" PRIx32,
964 cortex_m->dcb_dhcsr, cortex_m->nvic_icsr);
965
966 return ERROR_OK;
967 }
968
969 static int cortex_m_assert_reset(struct target *target)
970 {
971 struct cortex_m_common *cortex_m = target_to_cm(target);
972 struct armv7m_common *armv7m = &cortex_m->armv7m;
973 struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
974 enum cortex_m_soft_reset_config reset_config = cortex_m->soft_reset_config;
975
976 LOG_DEBUG("target->state: %s",
977 target_state_name(target));
978
979 enum reset_types jtag_reset_config = jtag_get_reset_config();
980
981 if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
982 /* allow scripts to override the reset event */
983
984 target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
985 register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
986 target->state = TARGET_RESET;
987
988 return ERROR_OK;
989 }
990
991 /* some cores support connecting while srst is asserted
992 * use that mode is it has been configured */
993
994 bool srst_asserted = false;
995
996 if ((jtag_reset_config & RESET_HAS_SRST) &&
997 (jtag_reset_config & RESET_SRST_NO_GATING)) {
998 adapter_assert_reset();
999 srst_asserted = true;
1000 }
1001
1002 /* Enable debug requests */
1003 int retval;
1004 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
1005 if (retval != ERROR_OK)
1006 return retval;
1007 if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
1008 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN);
1009 if (retval != ERROR_OK)
1010 return retval;
1011 }
1012
1013 /* If the processor is sleeping in a WFI or WFE instruction, the
1014 * C_HALT bit must be asserted to regain control */
1015 if (cortex_m->dcb_dhcsr & S_SLEEP) {
1016 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
1017 if (retval != ERROR_OK)
1018 return retval;
1019 }
1020
1021 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DCRDR, 0);
1022 if (retval != ERROR_OK)
1023 return retval;
1024
1025 if (!target->reset_halt) {
1026 /* Set/Clear C_MASKINTS in a separate operation */
1027 if (cortex_m->dcb_dhcsr & C_MASKINTS) {
1028 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, DCB_DHCSR,
1029 DBGKEY | C_DEBUGEN | C_HALT);
1030 if (retval != ERROR_OK)
1031 return retval;
1032 }
1033
1034 /* clear any debug flags before resuming */
1035 cortex_m_clear_halt(target);
1036
1037 /* clear C_HALT in dhcsr reg */
1038 cortex_m_write_debug_halt_mask(target, 0, C_HALT);
1039 } else {
1040 /* Halt in debug on reset; endreset_event() restores DEMCR.
1041 *
1042 * REVISIT catching BUSERR presumably helps to defend against
1043 * bad vector table entries. Should this include MMERR or
1044 * other flags too?
1045 */
1046 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, DCB_DEMCR,
1047 TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
1048 if (retval != ERROR_OK)
1049 return retval;
1050 }
1051
1052 if (jtag_reset_config & RESET_HAS_SRST) {
1053 /* default to asserting srst */
1054 if (!srst_asserted)
1055 adapter_assert_reset();
1056 } else {
1057 /* Use a standard Cortex-M3 software reset mechanism.
1058 * We default to using VECRESET as it is supported on all current cores.
1059 * This has the disadvantage of not resetting the peripherals, so a
1060 * reset-init event handler is needed to perform any peripheral resets.
1061 */
1062 LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ)
1063 ? "SYSRESETREQ" : "VECTRESET");
1064
1065 if (reset_config == CORTEX_M_RESET_VECTRESET) {
1066 LOG_WARNING("Only resetting the Cortex-M core, use a reset-init event "
1067 "handler to reset any peripherals or configure hardware srst support.");
1068 }
1069
1070 retval = mem_ap_sel_write_atomic_u32(swjdp, armv7m->debug_ap, NVIC_AIRCR,
1071 AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ)
1072 ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET));
1073 if (retval != ERROR_OK)
1074 LOG_DEBUG("Ignoring AP write error right after reset");
1075
1076 retval = ahbap_debugport_init(swjdp, armv7m->debug_ap);
1077 if (retval != ERROR_OK) {
1078 LOG_ERROR("DP initialisation failed");
1079 return retval;
1080 }
1081
1082 {
1083 /* I do not know why this is necessary, but it
1084 * fixes strange effects (step/resume cause NMI
1085 * after reset) on LM3S6918 -- Michael Schwingen
1086 */
1087 uint32_t tmp;
1088 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, NVIC_AIRCR, &tmp);
1089 if (retval != ERROR_OK)
1090 return retval;
1091 }
1092 }
1093
1094 target->state = TARGET_RESET;
1095 jtag_add_sleep(50000);
1096
1097 register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
1098
1099 if (target->reset_halt) {
1100 retval = target_halt(target);
1101 if (retval != ERROR_OK)
1102 return retval;
1103 }
1104
1105 return ERROR_OK;
1106 }
1107
1108 static int cortex_m_deassert_reset(struct target *target)
1109 {
1110 struct armv7m_common *armv7m = &target_to_cm(target)->armv7m;
1111
1112 LOG_DEBUG("target->state: %s",
1113 target_state_name(target));
1114
1115 /* deassert reset lines */
1116 adapter_deassert_reset();
1117
1118 enum reset_types jtag_reset_config = jtag_get_reset_config();
1119
1120 if ((jtag_reset_config & RESET_HAS_SRST) &&
1121 !(jtag_reset_config & RESET_SRST_NO_GATING)) {
1122 int retval = ahbap_debugport_init(armv7m->arm.dap, armv7m->debug_ap);
1123 if (retval != ERROR_OK) {
1124 LOG_ERROR("DP initialisation failed");
1125 return retval;
1126 }
1127 }
1128
1129 return ERROR_OK;
1130 }
1131
1132 int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint)
1133 {
1134 int retval;
1135 int fp_num = 0;
1136 struct cortex_m_common *cortex_m = target_to_cm(target);
1137 struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list;
1138
1139 if (breakpoint->set) {
1140 LOG_WARNING("breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id);
1141 return ERROR_OK;
1142 }
1143
1144 if (cortex_m->auto_bp_type)
1145 breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
1146
1147 if (breakpoint->type == BKPT_HARD) {
1148 uint32_t fpcr_value;
1149 while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code))
1150 fp_num++;
1151 if (fp_num >= cortex_m->fp_num_code) {
1152 LOG_ERROR("Can not find free FPB Comparator!");
1153 return ERROR_FAIL;
1154 }
1155 breakpoint->set = fp_num + 1;
1156 fpcr_value = breakpoint->address | 1;
1157 if (cortex_m->fp_rev == 0) {
1158 uint32_t hilo;
1159 hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
1160 fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1;
1161 } else if (cortex_m->fp_rev > 1) {
1162 LOG_ERROR("Unhandled Cortex-M Flash Patch Breakpoint architecture revision");
1163 return ERROR_FAIL;
1164 }
1165 comparator_list[fp_num].used = 1;
1166 comparator_list[fp_num].fpcr_value = fpcr_value;
1167 target_write_u32(target, comparator_list[fp_num].fpcr_address,
1168 comparator_list[fp_num].fpcr_value);
1169 LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32 "",
1170 fp_num,
1171 comparator_list[fp_num].fpcr_value);
1172 if (!cortex_m->fpb_enabled) {
1173 LOG_DEBUG("FPB wasn't enabled, do it now");
1174 retval = cortex_m_enable_fpb(target);
1175 if (retval != ERROR_OK) {
1176 LOG_ERROR("Failed to enable the FPB");
1177 return retval;
1178 }
1179
1180 cortex_m->fpb_enabled = 1;
1181 }
1182 } else if (breakpoint->type == BKPT_SOFT) {
1183 uint8_t code[4];
1184
1185 /* NOTE: on ARMv6-M and ARMv7-M, BKPT(0xab) is used for
1186 * semihosting; don't use that. Otherwise the BKPT
1187 * parameter is arbitrary.
1188 */
1189 buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
1190 retval = target_read_memory(target,
1191 breakpoint->address & 0xFFFFFFFE,
1192 breakpoint->length, 1,
1193 breakpoint->orig_instr);
1194 if (retval != ERROR_OK)
1195 return retval;
1196 retval = target_write_memory(target,
1197 breakpoint->address & 0xFFFFFFFE,
1198 breakpoint->length, 1,
1199 code);
1200 if (retval != ERROR_OK)
1201 return retval;
1202 breakpoint->set = true;
1203 }
1204
1205 LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
1206 breakpoint->unique_id,
1207 (int)(breakpoint->type),
1208 breakpoint->address,
1209 breakpoint->length,
1210 breakpoint->set);
1211
1212 return ERROR_OK;
1213 }
1214
1215 int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
1216 {
1217 int retval;
1218 struct cortex_m_common *cortex_m = target_to_cm(target);
1219 struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list;
1220
1221 if (!breakpoint->set) {
1222 LOG_WARNING("breakpoint not set");
1223 return ERROR_OK;
1224 }
1225
1226 LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
1227 breakpoint->unique_id,
1228 (int)(breakpoint->type),
1229 breakpoint->address,
1230 breakpoint->length,
1231 breakpoint->set);
1232
1233 if (breakpoint->type == BKPT_HARD) {
1234 int fp_num = breakpoint->set - 1;
1235 if ((fp_num < 0) || (fp_num >= cortex_m->fp_num_code)) {
1236 LOG_DEBUG("Invalid FP Comparator number in breakpoint");
1237 return ERROR_OK;
1238 }
1239 comparator_list[fp_num].used = 0;
1240 comparator_list[fp_num].fpcr_value = 0;
1241 target_write_u32(target, comparator_list[fp_num].fpcr_address,
1242 comparator_list[fp_num].fpcr_value);
1243 } else {
1244 /* restore original instruction (kept in target endianness) */
1245 if (breakpoint->length == 4) {
1246 retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1,
1247 breakpoint->orig_instr);
1248 if (retval != ERROR_OK)
1249 return retval;
1250 } else {
1251 retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1,
1252 breakpoint->orig_instr);
1253 if (retval != ERROR_OK)
1254 return retval;
1255 }
1256 }
1257 breakpoint->set = false;
1258
1259 return ERROR_OK;
1260 }
1261
1262 int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
1263 {
1264 struct cortex_m_common *cortex_m = target_to_cm(target);
1265
1266 if (cortex_m->auto_bp_type)
1267 breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
1268
1269 if (breakpoint->type != BKPT_TYPE_BY_ADDR(breakpoint->address)) {
1270 if (breakpoint->type == BKPT_HARD) {
1271 LOG_INFO("flash patch comparator requested outside code memory region");
1272 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1273 }
1274
1275 if (breakpoint->type == BKPT_SOFT) {
1276 LOG_INFO("soft breakpoint requested in code (flash) memory region");
1277 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1278 }
1279 }
1280
1281 if ((breakpoint->type == BKPT_HARD) && (cortex_m->fp_code_available < 1)) {
1282 LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
1283 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1284 }
1285
1286 if (breakpoint->length == 3) {
1287 LOG_DEBUG("Using a two byte breakpoint for 32bit Thumb-2 request");
1288 breakpoint->length = 2;
1289 }
1290
1291 if ((breakpoint->length != 2)) {
1292 LOG_INFO("only breakpoints of two bytes length supported");
1293 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1294 }
1295
1296 if (breakpoint->type == BKPT_HARD)
1297 cortex_m->fp_code_available--;
1298
1299 return cortex_m_set_breakpoint(target, breakpoint);
1300 }
1301
1302 int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
1303 {
1304 struct cortex_m_common *cortex_m = target_to_cm(target);
1305
1306 /* REVISIT why check? FBP can be updated with core running ... */
1307 if (target->state != TARGET_HALTED) {
1308 LOG_WARNING("target not halted");
1309 return ERROR_TARGET_NOT_HALTED;
1310 }
1311
1312 if (cortex_m->auto_bp_type)
1313 breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
1314
1315 if (breakpoint->set)
1316 cortex_m_unset_breakpoint(target, breakpoint);
1317
1318 if (breakpoint->type == BKPT_HARD)
1319 cortex_m->fp_code_available++;
1320
1321 return ERROR_OK;
1322 }
1323
1324 int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
1325 {
1326 int dwt_num = 0;
1327 uint32_t mask, temp;
1328 struct cortex_m_common *cortex_m = target_to_cm(target);
1329
1330 /* watchpoint params were validated earlier */
1331 mask = 0;
1332 temp = watchpoint->length;
1333 while (temp) {
1334 temp >>= 1;
1335 mask++;
1336 }
1337 mask--;
1338
1339 /* REVISIT Don't fully trust these "not used" records ... users
1340 * may set up breakpoints by hand, e.g. dual-address data value
1341 * watchpoint using comparator #1; comparator #0 matching cycle
1342 * count; send data trace info through ITM and TPIU; etc
1343 */
1344 struct cortex_m_dwt_comparator *comparator;
1345
1346 for (comparator = cortex_m->dwt_comparator_list;
1347 comparator->used && dwt_num < cortex_m->dwt_num_comp;
1348 comparator++, dwt_num++)
1349 continue;
1350 if (dwt_num >= cortex_m->dwt_num_comp) {
1351 LOG_ERROR("Can not find free DWT Comparator");
1352 return ERROR_FAIL;
1353 }
1354 comparator->used = 1;
1355 watchpoint->set = dwt_num + 1;
1356
1357 comparator->comp = watchpoint->address;
1358 target_write_u32(target, comparator->dwt_comparator_address + 0,
1359 comparator->comp);
1360
1361 comparator->mask = mask;
1362 target_write_u32(target, comparator->dwt_comparator_address + 4,
1363 comparator->mask);
1364
1365 switch (watchpoint->rw) {
1366 case WPT_READ:
1367 comparator->function = 5;
1368 break;
1369 case WPT_WRITE:
1370 comparator->function = 6;
1371 break;
1372 case WPT_ACCESS:
1373 comparator->function = 7;
1374 break;
1375 }
1376 target_write_u32(target, comparator->dwt_comparator_address + 8,
1377 comparator->function);
1378
1379 LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x",
1380 watchpoint->unique_id, dwt_num,
1381 (unsigned) comparator->comp,
1382 (unsigned) comparator->mask,
1383 (unsigned) comparator->function);
1384 return ERROR_OK;
1385 }
1386
1387 int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
1388 {
1389 struct cortex_m_common *cortex_m = target_to_cm(target);
1390 struct cortex_m_dwt_comparator *comparator;
1391 int dwt_num;
1392
1393 if (!watchpoint->set) {
1394 LOG_WARNING("watchpoint (wpid: %d) not set",
1395 watchpoint->unique_id);
1396 return ERROR_OK;
1397 }
1398
1399 dwt_num = watchpoint->set - 1;
1400
1401 LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
1402 watchpoint->unique_id, dwt_num,
1403 (unsigned) watchpoint->address);
1404
1405 if ((dwt_num < 0) || (dwt_num >= cortex_m->dwt_num_comp)) {
1406 LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
1407 return ERROR_OK;
1408 }
1409
1410 comparator = cortex_m->dwt_comparator_list + dwt_num;
1411 comparator->used = 0;
1412 comparator->function = 0;
1413 target_write_u32(target, comparator->dwt_comparator_address + 8,
1414 comparator->function);
1415
1416 watchpoint->set = false;
1417
1418 return ERROR_OK;
1419 }
1420
1421 int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
1422 {
1423 struct cortex_m_common *cortex_m = target_to_cm(target);
1424
1425 if (cortex_m->dwt_comp_available < 1) {
1426 LOG_DEBUG("no comparators?");
1427 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1428 }
1429
1430 /* hardware doesn't support data value masking */
1431 if (watchpoint->mask != ~(uint32_t)0) {
1432 LOG_DEBUG("watchpoint value masks not supported");
1433 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1434 }
1435
1436 /* hardware allows address masks of up to 32K */
1437 unsigned mask;
1438
1439 for (mask = 0; mask < 16; mask++) {
1440 if ((1u << mask) == watchpoint->length)
1441 break;
1442 }
1443 if (mask == 16) {
1444 LOG_DEBUG("unsupported watchpoint length");
1445 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1446 }
1447 if (watchpoint->address & ((1 << mask) - 1)) {
1448 LOG_DEBUG("watchpoint address is unaligned");
1449 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1450 }
1451
1452 /* Caller doesn't seem to be able to describe watching for data
1453 * values of zero; that flags "no value".
1454 *
1455 * REVISIT This DWT may well be able to watch for specific data
1456 * values. Requires comparator #1 to set DATAVMATCH and match
1457 * the data, and another comparator (DATAVADDR0) matching addr.
1458 */
1459 if (watchpoint->value) {
1460 LOG_DEBUG("data value watchpoint not YET supported");
1461 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1462 }
1463
1464 cortex_m->dwt_comp_available--;
1465 LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available);
1466
1467 return ERROR_OK;
1468 }
1469
1470 int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
1471 {
1472 struct cortex_m_common *cortex_m = target_to_cm(target);
1473
1474 /* REVISIT why check? DWT can be updated with core running ... */
1475 if (target->state != TARGET_HALTED) {
1476 LOG_WARNING("target not halted");
1477 return ERROR_TARGET_NOT_HALTED;
1478 }
1479
1480 if (watchpoint->set)
1481 cortex_m_unset_watchpoint(target, watchpoint);
1482
1483 cortex_m->dwt_comp_available++;
1484 LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available);
1485
1486 return ERROR_OK;
1487 }
1488
1489 void cortex_m_enable_watchpoints(struct target *target)
1490 {
1491 struct watchpoint *watchpoint = target->watchpoints;
1492
1493 /* set any pending watchpoints */
1494 while (watchpoint) {
1495 if (!watchpoint->set)
1496 cortex_m_set_watchpoint(target, watchpoint);
1497 watchpoint = watchpoint->next;
1498 }
1499 }
1500
1501 static int cortex_m_load_core_reg_u32(struct target *target,
1502 uint32_t num, uint32_t *value)
1503 {
1504 int retval;
1505
1506 /* NOTE: we "know" here that the register identifiers used
1507 * in the v7m header match the Cortex-M3 Debug Core Register
1508 * Selector values for R0..R15, xPSR, MSP, and PSP.
1509 */
1510 switch (num) {
1511 case 0 ... 18:
1512 /* read a normal core register */
1513 retval = cortexm_dap_read_coreregister_u32(target, value, num);
1514
1515 if (retval != ERROR_OK) {
1516 LOG_ERROR("JTAG failure %i", retval);
1517 return ERROR_JTAG_DEVICE_ERROR;
1518 }
1519 LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value);
1520 break;
1521
1522 case ARMV7M_FPSCR:
1523 /* Floating-point Status and Registers */
1524 retval = target_write_u32(target, DCB_DCRSR, 0x21);
1525 if (retval != ERROR_OK)
1526 return retval;
1527 retval = target_read_u32(target, DCB_DCRDR, value);
1528 if (retval != ERROR_OK)
1529 return retval;
1530 LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value);
1531 break;
1532
1533 case ARMV7M_S0 ... ARMV7M_S31:
1534 /* Floating-point Status and Registers */
1535 retval = target_write_u32(target, DCB_DCRSR, num - ARMV7M_S0 + 0x40);
1536 if (retval != ERROR_OK)
1537 return retval;
1538 retval = target_read_u32(target, DCB_DCRDR, value);
1539 if (retval != ERROR_OK)
1540 return retval;
1541 LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32,
1542 (int)(num - ARMV7M_S0), *value);
1543 break;
1544
1545 case ARMV7M_PRIMASK:
1546 case ARMV7M_BASEPRI:
1547 case ARMV7M_FAULTMASK:
1548 case ARMV7M_CONTROL:
1549 /* Cortex-M3 packages these four registers as bitfields
1550 * in one Debug Core register. So say r0 and r2 docs;
1551 * it was removed from r1 docs, but still works.
1552 */
1553 cortexm_dap_read_coreregister_u32(target, value, 20);
1554
1555 switch (num) {
1556 case ARMV7M_PRIMASK:
1557 *value = buf_get_u32((uint8_t *)value, 0, 1);
1558 break;
1559
1560 case ARMV7M_BASEPRI:
1561 *value = buf_get_u32((uint8_t *)value, 8, 8);
1562 break;
1563
1564 case ARMV7M_FAULTMASK:
1565 *value = buf_get_u32((uint8_t *)value, 16, 1);
1566 break;
1567
1568 case ARMV7M_CONTROL:
1569 *value = buf_get_u32((uint8_t *)value, 24, 2);
1570 break;
1571 }
1572
1573 LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value);
1574 break;
1575
1576 default:
1577 return ERROR_COMMAND_SYNTAX_ERROR;
1578 }
1579
1580 return ERROR_OK;
1581 }
1582
1583 static int cortex_m_store_core_reg_u32(struct target *target,
1584 uint32_t num, uint32_t value)
1585 {
1586 int retval;
1587 uint32_t reg;
1588 struct armv7m_common *armv7m = target_to_armv7m(target);
1589
1590 /* NOTE: we "know" here that the register identifiers used
1591 * in the v7m header match the Cortex-M3 Debug Core Register
1592 * Selector values for R0..R15, xPSR, MSP, and PSP.
1593 */
1594 switch (num) {
1595 case 0 ... 18:
1596 retval = cortexm_dap_write_coreregister_u32(target, value, num);
1597 if (retval != ERROR_OK) {
1598 struct reg *r;
1599
1600 LOG_ERROR("JTAG failure");
1601 r = armv7m->arm.core_cache->reg_list + num;
1602 r->dirty = r->valid;
1603 return ERROR_JTAG_DEVICE_ERROR;
1604 }
1605 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
1606 break;
1607
1608 case ARMV7M_FPSCR:
1609 /* Floating-point Status and Registers */
1610 retval = target_write_u32(target, DCB_DCRDR, value);
1611 if (retval != ERROR_OK)
1612 return retval;
1613 retval = target_write_u32(target, DCB_DCRSR, 0x21 | (1<<16));
1614 if (retval != ERROR_OK)
1615 return retval;
1616 LOG_DEBUG("write FPSCR value 0x%" PRIx32, value);
1617 break;
1618
1619 case ARMV7M_S0 ... ARMV7M_S31:
1620 /* Floating-point Status and Registers */
1621 retval = target_write_u32(target, DCB_DCRDR, value);
1622 if (retval != ERROR_OK)
1623 return retval;
1624 retval = target_write_u32(target, DCB_DCRSR, (num - ARMV7M_S0 + 0x40) | (1<<16));
1625 if (retval != ERROR_OK)
1626 return retval;
1627 LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32,
1628 (int)(num - ARMV7M_S0), value);
1629 break;
1630
1631 case ARMV7M_PRIMASK:
1632 case ARMV7M_BASEPRI:
1633 case ARMV7M_FAULTMASK:
1634 case ARMV7M_CONTROL:
1635 /* Cortex-M3 packages these four registers as bitfields
1636 * in one Debug Core register. So say r0 and r2 docs;
1637 * it was removed from r1 docs, but still works.
1638 */
1639 cortexm_dap_read_coreregister_u32(target, &reg, 20);
1640
1641 switch (num) {
1642 case ARMV7M_PRIMASK:
1643 buf_set_u32((uint8_t *)&reg, 0, 1, value);
1644 break;
1645
1646 case ARMV7M_BASEPRI:
1647 buf_set_u32((uint8_t *)&reg, 8, 8, value);
1648 break;
1649
1650 case ARMV7M_FAULTMASK:
1651 buf_set_u32((uint8_t *)&reg, 16, 1, value);
1652 break;
1653
1654 case ARMV7M_CONTROL:
1655 buf_set_u32((uint8_t *)&reg, 24, 2, value);
1656 break;
1657 }
1658
1659 cortexm_dap_write_coreregister_u32(target, reg, 20);
1660
1661 LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value);
1662 break;
1663
1664 default:
1665 return ERROR_COMMAND_SYNTAX_ERROR;
1666 }
1667
1668 return ERROR_OK;
1669 }
1670
1671 static int cortex_m_read_memory(struct target *target, uint32_t address,
1672 uint32_t size, uint32_t count, uint8_t *buffer)
1673 {
1674 struct armv7m_common *armv7m = target_to_armv7m(target);
1675 struct adiv5_dap *swjdp = armv7m->arm.dap;
1676
1677 if (armv7m->arm.is_armv6m) {
1678 /* armv6m does not handle unaligned memory access */
1679 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
1680 return ERROR_TARGET_UNALIGNED_ACCESS;
1681 }
1682
1683 return mem_ap_sel_read_buf(swjdp, armv7m->debug_ap, buffer, size, count, address);
1684 }
1685
1686 static int cortex_m_write_memory(struct target *target, uint32_t address,
1687 uint32_t size, uint32_t count, const uint8_t *buffer)
1688 {
1689 struct armv7m_common *armv7m = target_to_armv7m(target);
1690 struct adiv5_dap *swjdp = armv7m->arm.dap;
1691
1692 if (armv7m->arm.is_armv6m) {
1693 /* armv6m does not handle unaligned memory access */
1694 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
1695 return ERROR_TARGET_UNALIGNED_ACCESS;
1696 }
1697
1698 return mem_ap_sel_write_buf(swjdp, armv7m->debug_ap, buffer, size, count, address);
1699 }
1700
1701 static int cortex_m_init_target(struct command_context *cmd_ctx,
1702 struct target *target)
1703 {
1704 armv7m_build_reg_cache(target);
1705 return ERROR_OK;
1706 }
1707
1708 void cortex_m_deinit_target(struct target *target)
1709 {
1710 struct cortex_m_common *cortex_m = target_to_cm(target);
1711
1712 free(cortex_m->fp_comparator_list);
1713
1714 cortex_m_dwt_free(target);
1715 armv7m_free_reg_cache(target);
1716
1717 free(cortex_m);
1718 }
1719
1720 /* REVISIT cache valid/dirty bits are unmaintained. We could set "valid"
1721 * on r/w if the core is not running, and clear on resume or reset ... or
1722 * at least, in a post_restore_context() method.
1723 */
1724
1725 struct dwt_reg_state {
1726 struct target *target;
1727 uint32_t addr;
1728 uint8_t value[4]; /* scratch/cache */
1729 };
1730
1731 static int cortex_m_dwt_get_reg(struct reg *reg)
1732 {
1733 struct dwt_reg_state *state = reg->arch_info;
1734
1735 uint32_t tmp;
1736 int retval = target_read_u32(state->target, state->addr, &tmp);
1737 if (retval != ERROR_OK)
1738 return retval;
1739
1740 buf_set_u32(state->value, 0, 32, tmp);
1741 return ERROR_OK;
1742 }
1743
1744 static int cortex_m_dwt_set_reg(struct reg *reg, uint8_t *buf)
1745 {
1746 struct dwt_reg_state *state = reg->arch_info;
1747
1748 return target_write_u32(state->target, state->addr,
1749 buf_get_u32(buf, 0, reg->size));
1750 }
1751
1752 struct dwt_reg {
1753 uint32_t addr;
1754 char *name;
1755 unsigned size;
1756 };
1757
1758 static struct dwt_reg dwt_base_regs[] = {
1759 { DWT_CTRL, "dwt_ctrl", 32, },
1760 /* NOTE that Erratum 532314 (fixed r2p0) affects CYCCNT: it wrongly
1761 * increments while the core is asleep.
1762 */
1763 { DWT_CYCCNT, "dwt_cyccnt", 32, },
1764 /* plus some 8 bit counters, useful for profiling with TPIU */
1765 };
1766
1767 static struct dwt_reg dwt_comp[] = {
1768 #define DWT_COMPARATOR(i) \
1769 { DWT_COMP0 + 0x10 * (i), "dwt_" #i "_comp", 32, }, \
1770 { DWT_MASK0 + 0x10 * (i), "dwt_" #i "_mask", 4, }, \
1771 { DWT_FUNCTION0 + 0x10 * (i), "dwt_" #i "_function", 32, }
1772 DWT_COMPARATOR(0),
1773 DWT_COMPARATOR(1),
1774 DWT_COMPARATOR(2),
1775 DWT_COMPARATOR(3),
1776 #undef DWT_COMPARATOR
1777 };
1778
1779 static const struct reg_arch_type dwt_reg_type = {
1780 .get = cortex_m_dwt_get_reg,
1781 .set = cortex_m_dwt_set_reg,
1782 };
1783
1784 static void cortex_m_dwt_addreg(struct target *t, struct reg *r, struct dwt_reg *d)
1785 {
1786 struct dwt_reg_state *state;
1787
1788 state = calloc(1, sizeof *state);
1789 if (!state)
1790 return;
1791 state->addr = d->addr;
1792 state->target = t;
1793
1794 r->name = d->name;
1795 r->size = d->size;
1796 r->value = state->value;
1797 r->arch_info = state;
1798 r->type = &dwt_reg_type;
1799 }
1800
1801 void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target)
1802 {
1803 uint32_t dwtcr;
1804 struct reg_cache *cache;
1805 struct cortex_m_dwt_comparator *comparator;
1806 int reg, i;
1807
1808 target_read_u32(target, DWT_CTRL, &dwtcr);
1809 if (!dwtcr) {
1810 LOG_DEBUG("no DWT");
1811 return;
1812 }
1813
1814 cm->dwt_num_comp = (dwtcr >> 28) & 0xF;
1815 cm->dwt_comp_available = cm->dwt_num_comp;
1816 cm->dwt_comparator_list = calloc(cm->dwt_num_comp,
1817 sizeof(struct cortex_m_dwt_comparator));
1818 if (!cm->dwt_comparator_list) {
1819 fail0:
1820 cm->dwt_num_comp = 0;
1821 LOG_ERROR("out of mem");
1822 return;
1823 }
1824
1825 cache = calloc(1, sizeof *cache);
1826 if (!cache) {
1827 fail1:
1828 free(cm->dwt_comparator_list);
1829 goto fail0;
1830 }
1831 cache->name = "Cortex-M DWT registers";
1832 cache->num_regs = 2 + cm->dwt_num_comp * 3;
1833 cache->reg_list = calloc(cache->num_regs, sizeof *cache->reg_list);
1834 if (!cache->reg_list) {
1835 free(cache);
1836 goto fail1;
1837 }
1838
1839 for (reg = 0; reg < 2; reg++)
1840 cortex_m_dwt_addreg(target, cache->reg_list + reg,
1841 dwt_base_regs + reg);
1842
1843 comparator = cm->dwt_comparator_list;
1844 for (i = 0; i < cm->dwt_num_comp; i++, comparator++) {
1845 int j;
1846
1847 comparator->dwt_comparator_address = DWT_COMP0 + 0x10 * i;
1848 for (j = 0; j < 3; j++, reg++)
1849 cortex_m_dwt_addreg(target, cache->reg_list + reg,
1850 dwt_comp + 3 * i + j);
1851
1852 /* make sure we clear any watchpoints enabled on the target */
1853 target_write_u32(target, comparator->dwt_comparator_address + 8, 0);
1854 }
1855
1856 *register_get_last_cache_p(&target->reg_cache) = cache;
1857 cm->dwt_cache = cache;
1858
1859 LOG_DEBUG("DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s",
1860 dwtcr, cm->dwt_num_comp,
1861 (dwtcr & (0xf << 24)) ? " only" : "/trigger");
1862
1863 /* REVISIT: if num_comp > 1, check whether comparator #1 can
1864 * implement single-address data value watchpoints ... so we
1865 * won't need to check it later, when asked to set one up.
1866 */
1867 }
1868
1869 static void cortex_m_dwt_free(struct target *target)
1870 {
1871 struct cortex_m_common *cm = target_to_cm(target);
1872 struct reg_cache *cache = cm->dwt_cache;
1873
1874 free(cm->dwt_comparator_list);
1875 cm->dwt_comparator_list = NULL;
1876 cm->dwt_num_comp = 0;
1877
1878 if (cache) {
1879 register_unlink_cache(&target->reg_cache, cache);
1880
1881 if (cache->reg_list) {
1882 for (size_t i = 0; i < cache->num_regs; i++)
1883 free(cache->reg_list[i].arch_info);
1884 free(cache->reg_list);
1885 }
1886 free(cache);
1887 }
1888 cm->dwt_cache = NULL;
1889 }
1890
1891 #define MVFR0 0xe000ef40
1892 #define MVFR1 0xe000ef44
1893
1894 #define MVFR0_DEFAULT_M4 0x10110021
1895 #define MVFR1_DEFAULT_M4 0x11000011
1896
1897 int cortex_m_examine(struct target *target)
1898 {
1899 int retval;
1900 uint32_t cpuid, fpcr, mvfr0, mvfr1;
1901 int i;
1902 struct cortex_m_common *cortex_m = target_to_cm(target);
1903 struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
1904 struct armv7m_common *armv7m = target_to_armv7m(target);
1905
1906 /* Search for the MEM-AP */
1907 retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7m->debug_ap);
1908 if (retval != ERROR_OK) {
1909 LOG_ERROR("Could not find MEM-AP to control the core");
1910 return retval;
1911 }
1912
1913 /* Leave (only) generic DAP stuff for debugport_init(); */
1914 swjdp->ap[armv7m->debug_ap].memaccess_tck = 8;
1915
1916 /* stlink shares the examine handler but does not support
1917 * all its calls */
1918 if (!armv7m->stlink) {
1919 retval = ahbap_debugport_init(swjdp, armv7m->debug_ap);
1920 if (retval != ERROR_OK)
1921 return retval;
1922 }
1923
1924 if (!target_was_examined(target)) {
1925 target_set_examined(target);
1926
1927 /* Read from Device Identification Registers */
1928 retval = target_read_u32(target, CPUID, &cpuid);
1929 if (retval != ERROR_OK)
1930 return retval;
1931
1932 /* Get CPU Type */
1933 i = (cpuid >> 4) & 0xf;
1934
1935 LOG_DEBUG("Cortex-M%d r%" PRId8 "p%" PRId8 " processor detected",
1936 i, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
1937 LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
1938
1939 /* test for floating point feature on cortex-m4 */
1940 if (i == 4) {
1941 target_read_u32(target, MVFR0, &mvfr0);
1942 target_read_u32(target, MVFR1, &mvfr1);
1943
1944 if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) {
1945 LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i);
1946 armv7m->fp_feature = FPv4_SP;
1947 }
1948 } else if (i == 0) {
1949 /* Cortex-M0 does not support unaligned memory access */
1950 armv7m->arm.is_armv6m = true;
1951 }
1952
1953 if (armv7m->fp_feature != FPv4_SP &&
1954 armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) {
1955 /* free unavailable FPU registers */
1956 size_t idx;
1957
1958 for (idx = ARMV7M_NUM_CORE_REGS_NOFP;
1959 idx < armv7m->arm.core_cache->num_regs;
1960 idx++) {
1961 free(armv7m->arm.core_cache->reg_list[idx].value);
1962 free(armv7m->arm.core_cache->reg_list[idx].feature);
1963 free(armv7m->arm.core_cache->reg_list[idx].reg_data_type);
1964 }
1965 armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP;
1966 }
1967
1968 if (i == 4 || i == 3) {
1969 /* Cortex-M3/M4 has 4096 bytes autoincrement range */
1970 swjdp->ap[armv7m->debug_ap].tar_autoincr_block = (1 << 12);
1971 }
1972
1973 /* Configure trace modules */
1974 retval = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr);
1975 if (retval != ERROR_OK)
1976 return retval;
1977
1978 if (armv7m->trace_config.config_type != DISABLED) {
1979 armv7m_trace_tpiu_config(target);
1980 armv7m_trace_itm_config(target);
1981 }
1982
1983 /* NOTE: FPB and DWT are both optional. */
1984
1985 /* Setup FPB */
1986 target_read_u32(target, FP_CTRL, &fpcr);
1987 cortex_m->auto_bp_type = 1;
1988 /* bits [14:12] and [7:4] */
1989 cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF);
1990 cortex_m->fp_num_lit = (fpcr >> 8) & 0xF;
1991 cortex_m->fp_code_available = cortex_m->fp_num_code;
1992 /* Detect flash patch revision, see RM DDI 0403E.b page C1-817.
1993 Revision is zero base, fp_rev == 1 means Rev.2 ! */
1994 cortex_m->fp_rev = (fpcr >> 28) & 0xf;
1995 free(cortex_m->fp_comparator_list);
1996 cortex_m->fp_comparator_list = calloc(
1997 cortex_m->fp_num_code + cortex_m->fp_num_lit,
1998 sizeof(struct cortex_m_fp_comparator));
1999 cortex_m->fpb_enabled = fpcr & 1;
2000 for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) {
2001 cortex_m->fp_comparator_list[i].type =
2002 (i < cortex_m->fp_num_code) ? FPCR_CODE : FPCR_LITERAL;
2003 cortex_m->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i;
2004
2005 /* make sure we clear any breakpoints enabled on the target */
2006 target_write_u32(target, cortex_m->fp_comparator_list[i].fpcr_address, 0);
2007 }
2008 LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i",
2009 fpcr,
2010 cortex_m->fp_num_code,
2011 cortex_m->fp_num_lit);
2012
2013 /* Setup DWT */
2014 cortex_m_dwt_free(target);
2015 cortex_m_dwt_setup(cortex_m, target);
2016
2017 /* These hardware breakpoints only work for code in flash! */
2018 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
2019 target_name(target),
2020 cortex_m->fp_num_code,
2021 cortex_m->dwt_num_comp);
2022 }
2023
2024 return ERROR_OK;
2025 }
2026
2027 static int cortex_m_dcc_read(struct target *target, uint8_t *value, uint8_t *ctrl)
2028 {
2029 struct armv7m_common *armv7m = target_to_armv7m(target);
2030 struct adiv5_dap *swjdp = armv7m->arm.dap;
2031 uint16_t dcrdr;
2032 uint8_t buf[2];
2033 int retval;
2034
2035 retval = mem_ap_sel_read_buf_noincr(swjdp, armv7m->debug_ap, buf, 2, 1, DCB_DCRDR);
2036 if (retval != ERROR_OK)
2037 return retval;
2038
2039 dcrdr = target_buffer_get_u16(target, buf);
2040 *ctrl = (uint8_t)dcrdr;
2041 *value = (uint8_t)(dcrdr >> 8);
2042
2043 LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
2044
2045 /* write ack back to software dcc register
2046 * signify we have read data */
2047 if (dcrdr & (1 << 0)) {
2048 target_buffer_set_u16(target, buf, 0);
2049 retval = mem_ap_sel_write_buf_noincr(swjdp, armv7m->debug_ap, buf, 2, 1, DCB_DCRDR);
2050 if (retval != ERROR_OK)
2051 return retval;
2052 }
2053
2054 return ERROR_OK;
2055 }
2056
2057 static int cortex_m_target_request_data(struct target *target,
2058 uint32_t size, uint8_t *buffer)
2059 {
2060 uint8_t data;
2061 uint8_t ctrl;
2062 uint32_t i;
2063
2064 for (i = 0; i < (size * 4); i++) {
2065 int retval = cortex_m_dcc_read(target, &data, &ctrl);
2066 if (retval != ERROR_OK)
2067 return retval;
2068 buffer[i] = data;
2069 }
2070
2071 return ERROR_OK;
2072 }
2073
2074 static int cortex_m_handle_target_request(void *priv)
2075 {
2076 struct target *target = priv;
2077 if (!target_was_examined(target))
2078 return ERROR_OK;
2079
2080 if (!target->dbg_msg_enabled)
2081 return ERROR_OK;
2082
2083 if (target->state == TARGET_RUNNING) {
2084 uint8_t data;
2085 uint8_t ctrl;
2086 int retval;
2087
2088 retval = cortex_m_dcc_read(target, &data, &ctrl);
2089 if (retval != ERROR_OK)
2090 return retval;
2091
2092 /* check if we have data */
2093 if (ctrl & (1 << 0)) {
2094 uint32_t request;
2095
2096 /* we assume target is quick enough */
2097 request = data;
2098 for (int i = 1; i <= 3; i++) {
2099 retval = cortex_m_dcc_read(target, &data, &ctrl);
2100 if (retval != ERROR_OK)
2101 return retval;
2102 request |= ((uint32_t)data << (i * 8));
2103 }
2104 target_request(target, request);
2105 }
2106 }
2107
2108 return ERROR_OK;
2109 }
2110
2111 static int cortex_m_init_arch_info(struct target *target,
2112 struct cortex_m_common *cortex_m, struct jtag_tap *tap)
2113 {
2114 struct armv7m_common *armv7m = &cortex_m->armv7m;
2115
2116 armv7m_init_arch_info(target, armv7m);
2117
2118 /* tap has no dap initialized */
2119 if (!tap->dap) {
2120 tap->dap = dap_init();
2121
2122 /* Leave (only) generic DAP stuff for debugport_init() */
2123 tap->dap->tap = tap;
2124 }
2125
2126 /* default reset mode is to use srst if fitted
2127 * if not it will use CORTEX_M3_RESET_VECTRESET */
2128 cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
2129
2130 armv7m->arm.dap = tap->dap;
2131
2132 /* Leave (only) generic DAP stuff for debugport_init(); */
2133 tap->dap->ap[dap_ap_get_select(tap->dap)].memaccess_tck = 8;
2134
2135 /* register arch-specific functions */
2136 armv7m->examine_debug_reason = cortex_m_examine_debug_reason;
2137
2138 armv7m->post_debug_entry = NULL;
2139
2140 armv7m->pre_restore_context = NULL;
2141
2142 armv7m->load_core_reg_u32 = cortex_m_load_core_reg_u32;
2143 armv7m->store_core_reg_u32 = cortex_m_store_core_reg_u32;
2144
2145 target_register_timer_callback(cortex_m_handle_target_request, 1, 1, target);
2146
2147 return ERROR_OK;
2148 }
2149
2150 static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
2151 {
2152 struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
2153
2154 cortex_m->common_magic = CORTEX_M_COMMON_MAGIC;
2155 cortex_m_init_arch_info(target, cortex_m, target->tap);
2156
2157 return ERROR_OK;
2158 }
2159
2160 /*--------------------------------------------------------------------------*/
2161
2162 static int cortex_m_verify_pointer(struct command_context *cmd_ctx,
2163 struct cortex_m_common *cm)
2164 {
2165 if (cm->common_magic != CORTEX_M_COMMON_MAGIC) {
2166 command_print(cmd_ctx, "target is not a Cortex-M");
2167 return ERROR_TARGET_INVALID;
2168 }
2169 return ERROR_OK;
2170 }
2171
2172 /*
2173 * Only stuff below this line should need to verify that its target
2174 * is a Cortex-M3. Everything else should have indirected through the
2175 * cortexm3_target structure, which is only used with CM3 targets.
2176 */
2177
2178 static const struct {
2179 char name[10];
2180 unsigned mask;
2181 } vec_ids[] = {
2182 { "hard_err", VC_HARDERR, },
2183 { "int_err", VC_INTERR, },
2184 { "bus_err", VC_BUSERR, },
2185 { "state_err", VC_STATERR, },
2186 { "chk_err", VC_CHKERR, },
2187 { "nocp_err", VC_NOCPERR, },
2188 { "mm_err", VC_MMERR, },
2189 { "reset", VC_CORERESET, },
2190 };
2191
2192 COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
2193 {
2194 struct target *target = get_current_target(CMD_CTX);
2195 struct cortex_m_common *cortex_m = target_to_cm(target);
2196 struct armv7m_common *armv7m = &cortex_m->armv7m;
2197 struct adiv5_dap *swjdp = armv7m->arm.dap;
2198 uint32_t demcr = 0;
2199 int retval;
2200
2201 retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
2202 if (retval != ERROR_OK)
2203 return retval;
2204
2205 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DEMCR, &demcr);
2206 if (retval != ERROR_OK)
2207 return retval;
2208
2209 if (CMD_ARGC > 0) {
2210 unsigned catch = 0;
2211
2212 if (CMD_ARGC == 1) {
2213 if (strcmp(CMD_ARGV[0], "all") == 0) {
2214 catch = VC_HARDERR | VC_INTERR | VC_BUSERR
2215 | VC_STATERR | VC_CHKERR | VC_NOCPERR
2216 | VC_MMERR | VC_CORERESET;
2217 goto write;
2218 } else if (strcmp(CMD_ARGV[0], "none") == 0)
2219 goto write;
2220 }
2221 while (CMD_ARGC-- > 0) {
2222 unsigned i;
2223 for (i = 0; i < ARRAY_SIZE(vec_ids); i++) {
2224 if (strcmp(CMD_ARGV[CMD_ARGC], vec_ids[i].name) != 0)
2225 continue;
2226 catch |= vec_ids[i].mask;
2227 break;
2228 }
2229 if (i == ARRAY_SIZE(vec_ids)) {
2230 LOG_ERROR("No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]);
2231 return ERROR_COMMAND_SYNTAX_ERROR;
2232 }
2233 }
2234 write:
2235 /* For now, armv7m->demcr only stores vector catch flags. */
2236 armv7m->demcr = catch;
2237
2238 demcr &= ~0xffff;
2239 demcr |= catch;
2240
2241 /* write, but don't assume it stuck (why not??) */
2242 retval = mem_ap_sel_write_u32(swjdp, armv7m->debug_ap, DCB_DEMCR, demcr);
2243 if (retval != ERROR_OK)
2244 return retval;
2245 retval = mem_ap_sel_read_atomic_u32(swjdp, armv7m->debug_ap, DCB_DEMCR, &demcr);
2246 if (retval != ERROR_OK)
2247 return retval;
2248
2249 /* FIXME be sure to clear DEMCR on clean server shutdown.
2250 * Otherwise the vector catch hardware could fire when there's
2251 * no debugger hooked up, causing much confusion...
2252 */
2253 }
2254
2255 for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) {
2256 command_print(CMD_CTX, "%9s: %s", vec_ids[i].name,
2257 (demcr & vec_ids[i].mask) ? "catch" : "ignore");
2258 }
2259
2260 return ERROR_OK;
2261 }
2262
2263 COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
2264 {
2265 struct target *target = get_current_target(CMD_CTX);
2266 struct cortex_m_common *cortex_m = target_to_cm(target);
2267 int retval;
2268
2269 static const Jim_Nvp nvp_maskisr_modes[] = {
2270 { .name = "auto", .value = CORTEX_M_ISRMASK_AUTO },
2271 { .name = "off", .value = CORTEX_M_ISRMASK_OFF },
2272 { .name = "on", .value = CORTEX_M_ISRMASK_ON },
2273 { .name = NULL, .value = -1 },
2274 };
2275 const Jim_Nvp *n;
2276
2277
2278 retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
2279 if (retval != ERROR_OK)
2280 return retval;
2281
2282 if (target->state != TARGET_HALTED) {
2283 command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
2284 return ERROR_OK;
2285 }
2286
2287 if (CMD_ARGC > 0) {
2288 n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
2289 if (n->name == NULL)
2290 return ERROR_COMMAND_SYNTAX_ERROR;
2291 cortex_m->isrmasking_mode = n->value;
2292
2293
2294 if (cortex_m->isrmasking_mode == CORTEX_M_ISRMASK_ON)
2295 cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0);
2296 else
2297 cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
2298 }
2299
2300 n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_m->isrmasking_mode);
2301 command_print(CMD_CTX, "cortex_m interrupt mask %s", n->name);
2302
2303 return ERROR_OK;
2304 }
2305
2306 COMMAND_HANDLER(handle_cortex_m_reset_config_command)
2307 {
2308 struct target *target = get_current_target(CMD_CTX);
2309 struct cortex_m_common *cortex_m = target_to_cm(target);
2310 int retval;
2311 char *reset_config;
2312
2313 retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
2314 if (retval != ERROR_OK)
2315 return retval;
2316
2317 if (CMD_ARGC > 0) {
2318 if (strcmp(*CMD_ARGV, "sysresetreq") == 0)
2319 cortex_m->soft_reset_config = CORTEX_M_RESET_SYSRESETREQ;
2320 else if (strcmp(*CMD_ARGV, "vectreset") == 0)
2321 cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
2322 }
2323
2324 switch (cortex_m->soft_reset_config) {
2325 case CORTEX_M_RESET_SYSRESETREQ:
2326 reset_config = "sysresetreq";
2327 break;
2328
2329 case CORTEX_M_RESET_VECTRESET:
2330 reset_config = "vectreset";
2331 break;
2332
2333 default:
2334 reset_config = "unknown";
2335 break;
2336 }
2337
2338 command_print(CMD_CTX, "cortex_m reset_config %s", reset_config);
2339
2340 return ERROR_OK;
2341 }
2342
2343 static const struct command_registration cortex_m_exec_command_handlers[] = {
2344 {
2345 .name = "maskisr",
2346 .handler = handle_cortex_m_mask_interrupts_command,
2347 .mode = COMMAND_EXEC,
2348 .help = "mask cortex_m interrupts",
2349 .usage = "['auto'|'on'|'off']",
2350 },
2351 {
2352 .name = "vector_catch",
2353 .handler = handle_cortex_m_vector_catch_command,
2354 .mode = COMMAND_EXEC,
2355 .help = "configure hardware vectors to trigger debug entry",
2356 .usage = "['all'|'none'|('bus_err'|'chk_err'|...)*]",
2357 },
2358 {
2359 .name = "reset_config",
2360 .handler = handle_cortex_m_reset_config_command,
2361 .mode = COMMAND_ANY,
2362 .help = "configure software reset handling",
2363 .usage = "['srst'|'sysresetreq'|'vectreset']",
2364 },
2365 COMMAND_REGISTRATION_DONE
2366 };
2367 static const struct command_registration cortex_m_command_handlers[] = {
2368 {
2369 .chain = armv7m_command_handlers,
2370 },
2371 {
2372 .chain = armv7m_trace_command_handlers,
2373 },
2374 {
2375 .name = "cortex_m",
2376 .mode = COMMAND_EXEC,
2377 .help = "Cortex-M command group",
2378 .usage = "",
2379 .chain = cortex_m_exec_command_handlers,
2380 },
2381 COMMAND_REGISTRATION_DONE
2382 };
2383
2384 struct target_type cortexm_target = {
2385 .name = "cortex_m",
2386 .deprecated_name = "cortex_m3",
2387
2388 .poll = cortex_m_poll,
2389 .arch_state = armv7m_arch_state,
2390
2391 .target_request_data = cortex_m_target_request_data,
2392
2393 .halt = cortex_m_halt,
2394 .resume = cortex_m_resume,
2395 .step = cortex_m_step,
2396
2397 .assert_reset = cortex_m_assert_reset,
2398 .deassert_reset = cortex_m_deassert_reset,
2399 .soft_reset_halt = cortex_m_soft_reset_halt,
2400
2401 .get_gdb_reg_list = armv7m_get_gdb_reg_list,
2402
2403 .read_memory = cortex_m_read_memory,
2404 .write_memory = cortex_m_write_memory,
2405 .checksum_memory = armv7m_checksum_memory,
2406 .blank_check_memory = armv7m_blank_check_memory,
2407
2408 .run_algorithm = armv7m_run_algorithm,
2409 .start_algorithm = armv7m_start_algorithm,
2410 .wait_algorithm = armv7m_wait_algorithm,
2411
2412 .add_breakpoint = cortex_m_add_breakpoint,
2413 .remove_breakpoint = cortex_m_remove_breakpoint,
2414 .add_watchpoint = cortex_m_add_watchpoint,
2415 .remove_watchpoint = cortex_m_remove_watchpoint,
2416
2417 .commands = cortex_m_command_handlers,
2418 .target_create = cortex_m_target_create,
2419 .init_target = cortex_m_init_target,
2420 .examine = cortex_m_examine,
2421 .deinit_target = cortex_m_deinit_target,
2422 };

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)