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

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)