build: cleanup src/target directory
[openocd.git] / src / target / stm32_stlink.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Mathias Kuester *
3 * Mathias Kuester <kesmtp@freenet.de> *
4 * *
5 * Copyright (C) 2011 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "jtag/jtag.h"
29 #include "jtag/stlink/stlink_transport.h"
30 #include "jtag/stlink/stlink_interface.h"
31 #include "jtag/stlink/stlink_layout.h"
32 #include "register.h"
33 #include "algorithm.h"
34 #include "target.h"
35 #include "breakpoints.h"
36 #include "target_type.h"
37 #include "armv7m.h"
38 #include "cortex_m.h"
39
40 static inline struct stlink_interface_s *target_to_stlink(struct target *target)
41 {
42 return target->tap->priv;
43 }
44
45 static int stm32_stlink_load_core_reg_u32(struct target *target,
46 enum armv7m_regtype type,
47 uint32_t num, uint32_t *value)
48 {
49 int retval;
50 struct stlink_interface_s *stlink_if = target_to_stlink(target);
51
52 LOG_DEBUG("%s", __func__);
53
54 /* NOTE: we "know" here that the register identifiers used
55 * in the v7m header match the Cortex-M3 Debug Core Register
56 * Selector values for R0..R15, xPSR, MSP, and PSP.
57 */
58 switch (num) {
59 case 0 ... 18:
60 /* read a normal core register */
61 retval = stlink_if->layout->api->read_reg(stlink_if->fd, num, value);
62
63 if (retval != ERROR_OK) {
64 LOG_ERROR("JTAG failure %i", retval);
65 return ERROR_JTAG_DEVICE_ERROR;
66 }
67 LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "",
68 (int)num, *value);
69 break;
70
71 case ARMV7M_PRIMASK:
72 case ARMV7M_BASEPRI:
73 case ARMV7M_FAULTMASK:
74 case ARMV7M_CONTROL:
75 /* Cortex-M3 packages these four registers as bitfields
76 * in one Debug Core register. So say r0 and r2 docs;
77 * it was removed from r1 docs, but still works.
78 */
79 retval = stlink_if->layout->api->read_reg(stlink_if->fd, 20, value);
80
81 switch (num) {
82 case ARMV7M_PRIMASK:
83 *value = buf_get_u32((uint8_t *) value, 0, 1);
84 break;
85
86 case ARMV7M_BASEPRI:
87 *value = buf_get_u32((uint8_t *) value, 8, 8);
88 break;
89
90 case ARMV7M_FAULTMASK:
91 *value = buf_get_u32((uint8_t *) value, 16, 1);
92 break;
93
94 case ARMV7M_CONTROL:
95 *value = buf_get_u32((uint8_t *) value, 24, 2);
96 break;
97 }
98
99 LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "",
100 (int)num, *value);
101 break;
102
103 default:
104 return ERROR_COMMAND_SYNTAX_ERROR;
105 }
106
107 return ERROR_OK;
108 }
109
110 static int stm32_stlink_store_core_reg_u32(struct target *target,
111 enum armv7m_regtype type,
112 uint32_t num, uint32_t value)
113 {
114 int retval;
115 uint32_t reg;
116 struct armv7m_common *armv7m = target_to_armv7m(target);
117 struct stlink_interface_s *stlink_if = target_to_stlink(target);
118
119 LOG_DEBUG("%s", __func__);
120
121 #ifdef ARMV7_GDB_HACKS
122 /* If the LR register is being modified, make sure it will put us
123 * in "thumb" mode, or an INVSTATE exception will occur. This is a
124 * hack to deal with the fact that gdb will sometimes "forge"
125 * return addresses, and doesn't set the LSB correctly (i.e., when
126 * printing expressions containing function calls, it sets LR = 0.)
127 * Valid exception return codes have bit 0 set too.
128 */
129 if (num == ARMV7M_R14)
130 value |= 0x01;
131 #endif
132
133 /* NOTE: we "know" here that the register identifiers used
134 * in the v7m header match the Cortex-M3 Debug Core Register
135 * Selector values for R0..R15, xPSR, MSP, and PSP.
136 */
137 switch (num) {
138 case 0 ... 18:
139 retval = stlink_if->layout->api->write_reg(stlink_if->fd, num, value);
140
141 if (retval != ERROR_OK) {
142 struct reg *r;
143
144 LOG_ERROR("JTAG failure");
145 r = armv7m->core_cache->reg_list + num;
146 r->dirty = r->valid;
147 return ERROR_JTAG_DEVICE_ERROR;
148 }
149 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
150 break;
151
152 case ARMV7M_PRIMASK:
153 case ARMV7M_BASEPRI:
154 case ARMV7M_FAULTMASK:
155 case ARMV7M_CONTROL:
156 /* Cortex-M3 packages these four registers as bitfields
157 * in one Debug Core register. So say r0 and r2 docs;
158 * it was removed from r1 docs, but still works.
159 */
160
161 stlink_if->layout->api->read_reg(stlink_if->fd, 20, &reg);
162
163 switch (num) {
164 case ARMV7M_PRIMASK:
165 buf_set_u32((uint8_t *) &reg, 0, 1, value);
166 break;
167
168 case ARMV7M_BASEPRI:
169 buf_set_u32((uint8_t *) &reg, 8, 8, value);
170 break;
171
172 case ARMV7M_FAULTMASK:
173 buf_set_u32((uint8_t *) &reg, 16, 1, value);
174 break;
175
176 case ARMV7M_CONTROL:
177 buf_set_u32((uint8_t *) &reg, 24, 2, value);
178 break;
179 }
180
181 stlink_if->layout->api->write_reg(stlink_if->fd, 20, reg);
182
183 LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value);
184 break;
185
186 default:
187 return ERROR_COMMAND_SYNTAX_ERROR;
188 }
189
190 return ERROR_OK;
191 }
192
193 static int stm32_stlink_examine_debug_reason(struct target *target)
194 {
195 if ((target->debug_reason != DBG_REASON_DBGRQ)
196 && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
197 target->debug_reason = DBG_REASON_BREAKPOINT;
198 }
199
200 return ERROR_OK;
201 }
202
203 static int stm32_stlink_init_arch_info(struct target *target,
204 struct cortex_m3_common *cortex_m3,
205 struct jtag_tap *tap)
206 {
207 struct armv7m_common *armv7m;
208
209 LOG_DEBUG("%s", __func__);
210
211 armv7m = &cortex_m3->armv7m;
212 armv7m_init_arch_info(target, armv7m);
213
214 armv7m->load_core_reg_u32 = stm32_stlink_load_core_reg_u32;
215 armv7m->store_core_reg_u32 = stm32_stlink_store_core_reg_u32;
216
217 armv7m->examine_debug_reason = stm32_stlink_examine_debug_reason;
218
219 return ERROR_OK;
220 }
221
222 static int stm32_stlink_init_target(struct command_context *cmd_ctx,
223 struct target *target)
224 {
225 LOG_DEBUG("%s", __func__);
226
227 armv7m_build_reg_cache(target);
228
229 return ERROR_OK;
230 }
231
232 static int stm32_stlink_target_create(struct target *target,
233 Jim_Interp *interp)
234 {
235 LOG_DEBUG("%s", __func__);
236
237 struct cortex_m3_common *cortex_m3 = calloc(1, sizeof(struct cortex_m3_common));
238
239 if (!cortex_m3)
240 return ERROR_COMMAND_SYNTAX_ERROR;
241
242 stm32_stlink_init_arch_info(target, cortex_m3, target->tap);
243
244 return ERROR_OK;
245 }
246
247 static int stm32_stlink_examine(struct target *target)
248 {
249 int retval, i;
250 uint32_t cpuid, fpcr;
251 struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
252
253 LOG_DEBUG("%s", __func__);
254
255 if (target->tap->hasidcode == false) {
256 LOG_ERROR("no IDCODE present on device");
257
258 return ERROR_COMMAND_SYNTAX_ERROR;
259 }
260
261 if (!target_was_examined(target)) {
262 target_set_examined(target);
263
264 LOG_INFO("IDCODE %x", target->tap->idcode);
265
266 /* Read from Device Identification Registers */
267 retval = target_read_u32(target, CPUID, &cpuid);
268 if (retval != ERROR_OK)
269 return retval;
270
271 if (((cpuid >> 4) & 0xc3f) == 0xc23)
272 LOG_DEBUG("Cortex-M3 r%" PRId8 "p%" PRId8 " processor detected",
273 (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
274 LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
275
276 /* Setup FPB */
277 target_read_u32(target, FP_CTRL, &fpcr);
278 cortex_m3->auto_bp_type = 1;
279 cortex_m3->fp_num_code = ((fpcr >> 8) & 0x70) |
280 ((fpcr >> 4) & 0xF); /* bits [14:12] and [7:4] */
281 cortex_m3->fp_num_lit = (fpcr >> 8) & 0xF;
282 cortex_m3->fp_code_available = cortex_m3->fp_num_code;
283 cortex_m3->fp_comparator_list = calloc(cortex_m3->fp_num_code +
284 cortex_m3->fp_num_lit, sizeof(struct cortex_m3_fp_comparator));
285 cortex_m3->fpb_enabled = fpcr & 1;
286 for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++) {
287 cortex_m3->fp_comparator_list[i].type =
288 (i < cortex_m3->fp_num_code) ? FPCR_CODE : FPCR_LITERAL;
289 cortex_m3->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i;
290 }
291 LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i", fpcr,
292 cortex_m3->fp_num_code, cortex_m3->fp_num_lit);
293
294 /* Setup DWT */
295 cortex_m3_dwt_setup(cortex_m3, target);
296
297 /* These hardware breakpoints only work for code in flash! */
298 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
299 target_name(target),
300 cortex_m3->fp_num_code,
301 cortex_m3->dwt_num_comp);
302 }
303
304 return ERROR_OK;
305 }
306
307 static int stm32_stlink_load_context(struct target *target)
308 {
309 struct armv7m_common *armv7m = target_to_armv7m(target);
310 int num_regs = armv7m->core_cache->num_regs;
311
312 for (int i = 0; i < num_regs; i++) {
313 if (!armv7m->core_cache->reg_list[i].valid)
314 armv7m->read_core_reg(target, i);
315 }
316
317 return ERROR_OK;
318 }
319
320 static int stlink_debug_entry(struct target *target)
321 {
322 struct armv7m_common *armv7m = target_to_armv7m(target);
323 struct arm *arm = &armv7m->arm;
324 struct reg *r;
325 uint32_t xPSR;
326 int retval;
327
328 retval = armv7m->examine_debug_reason(target);
329 if (retval != ERROR_OK)
330 return retval;
331
332 stm32_stlink_load_context(target);
333
334 r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
335 xPSR = buf_get_u32(r->value, 0, 32);
336
337 /* Are we in an exception handler */
338 if (xPSR & 0x1FF) {
339 armv7m->core_mode = ARMV7M_MODE_HANDLER;
340 armv7m->exception_number = (xPSR & 0x1FF);
341
342 arm->core_mode = ARM_MODE_HANDLER;
343 arm->map = armv7m_msp_reg_map;
344 } else {
345 unsigned control = buf_get_u32(armv7m->core_cache
346 ->reg_list[ARMV7M_CONTROL].value, 0, 2);
347
348 /* is this thread privileged? */
349 armv7m->core_mode = control & 1;
350 arm->core_mode = armv7m->core_mode
351 ? ARM_MODE_USER_THREAD
352 : ARM_MODE_THREAD;
353
354 /* which stack is it using? */
355 if (control & 2)
356 arm->map = armv7m_psp_reg_map;
357 else
358 arm->map = armv7m_msp_reg_map;
359
360 armv7m->exception_number = 0;
361 }
362
363 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
364 armv7m_mode_strings[armv7m->core_mode],
365 *(uint32_t *)(arm->pc->value),
366 target_state_name(target));
367
368 return retval;
369 }
370
371 static int stm32_stlink_poll(struct target *target)
372 {
373 enum target_state state;
374 struct stlink_interface_s *stlink_if = target_to_stlink(target);
375 struct armv7m_common *armv7m = target_to_armv7m(target);
376
377 state = stlink_if->layout->api->state(stlink_if->fd);
378
379 if (state == TARGET_UNKNOWN) {
380 LOG_ERROR("jtag status contains invalid mode value - communication failure");
381 return ERROR_TARGET_FAILURE;
382 }
383
384 if (target->state == state)
385 return ERROR_OK;
386
387 if (state == TARGET_HALTED) {
388 target->state = state;
389
390 stlink_debug_entry(target);
391
392 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
393 LOG_DEBUG("halted: PC: 0x%x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
394 }
395
396 return ERROR_OK;
397 }
398
399 static int stm32_stlink_assert_reset(struct target *target)
400 {
401 int res;
402 struct stlink_interface_s *stlink_if = target_to_stlink(target);
403 struct armv7m_common *armv7m = target_to_armv7m(target);
404
405 LOG_DEBUG("%s", __func__);
406
407 res = stlink_if->layout->api->reset(stlink_if->fd);
408
409 if (res != ERROR_OK)
410 return res;
411
412 /* virtual assert reset, we need it for the internal
413 * jtag state machine
414 */
415 jtag_add_reset(1, 1);
416
417 /* registers are now invalid */
418 register_cache_invalidate(armv7m->core_cache);
419
420 if (target->reset_halt) {
421 target->state = TARGET_RESET;
422 target->debug_reason = DBG_REASON_DBGRQ;
423 } else {
424 target->state = TARGET_HALTED;
425 }
426
427 return ERROR_OK;
428 }
429
430 static int stm32_stlink_deassert_reset(struct target *target)
431 {
432 int res;
433
434 LOG_DEBUG("%s", __func__);
435
436 /* virtual deassert reset, we need it for the internal
437 * jtag state machine
438 */
439 jtag_add_reset(0, 0);
440
441 if (!target->reset_halt) {
442 res = target_resume(target, 1, 0, 0, 0);
443
444 if (res != ERROR_OK)
445 return res;
446 }
447
448 return ERROR_OK;
449 }
450
451 static int stm32_stlink_soft_reset_halt(struct target *target)
452 {
453 LOG_DEBUG("%s", __func__);
454 return ERROR_OK;
455 }
456
457 static int stm32_stlink_halt(struct target *target)
458 {
459 int res;
460 struct stlink_interface_s *stlink_if = target_to_stlink(target);
461
462 LOG_DEBUG("%s", __func__);
463
464 if (target->state == TARGET_HALTED) {
465 LOG_DEBUG("target was already halted");
466 return ERROR_OK;
467 }
468
469 if (target->state == TARGET_UNKNOWN)
470 LOG_WARNING("target was in unknown state when halt was requested");
471
472 res = stlink_if->layout->api->halt(stlink_if->fd);
473
474 if (res != ERROR_OK)
475 return res;
476
477 target->debug_reason = DBG_REASON_DBGRQ;
478
479 return ERROR_OK;
480 }
481
482 static int stm32_stlink_resume(struct target *target, int current,
483 uint32_t address, int handle_breakpoints,
484 int debug_execution)
485 {
486 int res;
487 struct stlink_interface_s *stlink_if = target_to_stlink(target);
488 struct armv7m_common *armv7m = target_to_armv7m(target);
489 uint32_t resume_pc;
490 struct breakpoint *breakpoint = NULL;
491 struct reg *pc;
492
493 LOG_DEBUG("%s %d %x %d %d", __func__, current, address,
494 handle_breakpoints, debug_execution);
495
496 if (target->state != TARGET_HALTED) {
497 LOG_WARNING("target not halted");
498 return ERROR_TARGET_NOT_HALTED;
499 }
500
501 pc = armv7m->arm.pc;
502 if (!current) {
503 buf_set_u32(pc->value, 0, 32, address);
504 pc->dirty = true;
505 pc->valid = true;
506 }
507
508 if (!breakpoint_find(target, buf_get_u32(pc->value, 0, 32))
509 && !debug_execution) {
510 armv7m_maybe_skip_bkpt_inst(target, NULL);
511 }
512
513 resume_pc = buf_get_u32(pc->value, 0, 32);
514
515 armv7m_restore_context(target);
516
517 /* registers are now invalid */
518 register_cache_invalidate(armv7m->core_cache);
519
520 /* the front-end may request us not to handle breakpoints */
521 if (handle_breakpoints) {
522 /* Single step past breakpoint at current address */
523 breakpoint = breakpoint_find(target, resume_pc);
524 if (breakpoint) {
525 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
526 breakpoint->address,
527 breakpoint->unique_id);
528 cortex_m3_unset_breakpoint(target, breakpoint);
529
530 res = stlink_if->layout->api->step(stlink_if->fd);
531
532 if (res != ERROR_OK)
533 return res;
534
535 cortex_m3_set_breakpoint(target, breakpoint);
536 }
537 }
538
539 res = stlink_if->layout->api->run(stlink_if->fd);
540
541 if (res != ERROR_OK)
542 return res;
543
544 target->state = TARGET_RUNNING;
545
546 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
547
548 return ERROR_OK;
549 }
550
551 static int stm32_stlink_step(struct target *target, int current,
552 uint32_t address, int handle_breakpoints)
553 {
554 int res;
555 struct stlink_interface_s *stlink_if = target_to_stlink(target);
556 struct armv7m_common *armv7m = target_to_armv7m(target);
557 struct breakpoint *breakpoint = NULL;
558 struct reg *pc = armv7m->arm.pc;
559 bool bkpt_inst_found = false;
560
561 LOG_DEBUG("%s", __func__);
562
563 if (target->state != TARGET_HALTED) {
564 LOG_WARNING("target not halted");
565 return ERROR_TARGET_NOT_HALTED;
566 }
567
568 if (!current) {
569 buf_set_u32(pc->value, 0, 32, address);
570 pc->dirty = true;
571 pc->valid = true;
572 }
573
574 uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
575
576 /* the front-end may request us not to handle breakpoints */
577 if (handle_breakpoints) {
578 breakpoint = breakpoint_find(target, pc_value);
579 if (breakpoint)
580 cortex_m3_unset_breakpoint(target, breakpoint);
581 }
582
583 armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
584
585 target->debug_reason = DBG_REASON_SINGLESTEP;
586
587 armv7m_restore_context(target);
588
589 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
590
591 res = stlink_if->layout->api->step(stlink_if->fd);
592
593 if (res != ERROR_OK)
594 return res;
595
596 /* registers are now invalid */
597 register_cache_invalidate(armv7m->core_cache);
598
599 if (breakpoint)
600 cortex_m3_set_breakpoint(target, breakpoint);
601
602 target->debug_reason = DBG_REASON_SINGLESTEP;
603 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
604
605 stlink_debug_entry(target);
606
607 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
608
609 return ERROR_OK;
610 }
611
612 static int stm32_stlink_read_memory(struct target *target, uint32_t address,
613 uint32_t size, uint32_t count,
614 uint8_t *buffer)
615 {
616 int res;
617 uint32_t buffer_threshold = 128;
618 uint32_t addr_increment = 4;
619 uint8_t *dst = buffer;
620 uint32_t c;
621 struct stlink_interface_s *stlink_if = target_to_stlink(target);
622
623 if (!count || !buffer)
624 return ERROR_COMMAND_SYNTAX_ERROR;
625
626 LOG_DEBUG("%s %x %d %d", __func__, address, size, count);
627
628 /* prepare byte count, buffer threshold
629 * and address increment for none 32bit access
630 */
631 if (size != 4) {
632 count *= size;
633 buffer_threshold = 64;
634 addr_increment = 1;
635 }
636
637 while (count) {
638 if (count > buffer_threshold)
639 c = buffer_threshold;
640 else
641 c = count;
642
643 if (size != 4)
644 res = stlink_if->layout->api->read_mem8(stlink_if->fd,
645 address, c, dst);
646 else
647 res = stlink_if->layout->api->read_mem32(stlink_if->fd,
648 address, c, (uint32_t *)dst);
649
650 if (res != ERROR_OK)
651 return res;
652
653 address += (c * addr_increment);
654 dst += (c * addr_increment);
655 count -= c;
656 }
657
658 return ERROR_OK;
659 }
660
661 static int stm32_stlink_write_memory(struct target *target, uint32_t address,
662 uint32_t size, uint32_t count,
663 const uint8_t *buffer)
664 {
665 int res;
666 uint32_t buffer_threshold = 128;
667 uint32_t addr_increment = 4;
668 const uint8_t *dst = buffer;
669 uint32_t c;
670 struct stlink_interface_s *stlink_if = target_to_stlink(target);
671
672 if (!count || !buffer)
673 return ERROR_COMMAND_SYNTAX_ERROR;
674
675 LOG_DEBUG("%s %x %d %d", __func__, address, size, count);
676
677 /* prepare byte count, buffer threshold
678 * and address increment for none 32bit access
679 */
680 if (size != 4) {
681 count *= size;
682 buffer_threshold = 64;
683 addr_increment = 1;
684 }
685
686 while (count) {
687 if (count > buffer_threshold)
688 c = buffer_threshold;
689 else
690 c = count;
691
692 if (size != 4)
693 res = stlink_if->layout->api->write_mem8(stlink_if->fd,
694 address, c, dst);
695 else
696 res = stlink_if->layout->api->write_mem32(stlink_if->fd,
697 address, c, (uint32_t *)dst);
698
699 if (res != ERROR_OK)
700 return res;
701
702 address += (c * addr_increment);
703 dst += (c * addr_increment);
704 count -= c;
705 }
706
707 return ERROR_OK;
708 }
709
710 static int stm32_stlink_bulk_write_memory(struct target *target,
711 uint32_t address, uint32_t count,
712 const uint8_t *buffer)
713 {
714 return stm32_stlink_write_memory(target, address, 4, count, buffer);
715 }
716
717 struct target_type stm32_stlink_target = {
718 .name = "stm32_stlink",
719
720 .init_target = stm32_stlink_init_target,
721 .target_create = stm32_stlink_target_create,
722 .examine = stm32_stlink_examine,
723
724 .poll = stm32_stlink_poll,
725 .arch_state = armv7m_arch_state,
726
727 .assert_reset = stm32_stlink_assert_reset,
728 .deassert_reset = stm32_stlink_deassert_reset,
729 .soft_reset_halt = stm32_stlink_soft_reset_halt,
730
731 .halt = stm32_stlink_halt,
732 .resume = stm32_stlink_resume,
733 .step = stm32_stlink_step,
734
735 .get_gdb_reg_list = armv7m_get_gdb_reg_list,
736
737 .read_memory = stm32_stlink_read_memory,
738 .write_memory = stm32_stlink_write_memory,
739 .bulk_write_memory = stm32_stlink_bulk_write_memory,
740 .checksum_memory = armv7m_checksum_memory,
741 .blank_check_memory = armv7m_blank_check_memory,
742
743 .run_algorithm = armv7m_run_algorithm,
744 .start_algorithm = armv7m_start_algorithm,
745 .wait_algorithm = armv7m_wait_algorithm,
746
747 .add_breakpoint = cortex_m3_add_breakpoint,
748 .remove_breakpoint = cortex_m3_remove_breakpoint,
749 .add_watchpoint = cortex_m3_add_watchpoint,
750 .remove_watchpoint = cortex_m3_remove_watchpoint,
751 };

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)