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

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)