9afaae0bfc383acabafce477ea5b6cdc085c8f1a
[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 armv7m->stlink = true;
282
283 return ERROR_OK;
284 }
285
286 static int stm32_stlink_init_target(struct command_context *cmd_ctx,
287 struct target *target)
288 {
289 LOG_DEBUG("%s", __func__);
290
291 armv7m_build_reg_cache(target);
292
293 return ERROR_OK;
294 }
295
296 static int stm32_stlink_target_create(struct target *target,
297 Jim_Interp *interp)
298 {
299 LOG_DEBUG("%s", __func__);
300
301 struct cortex_m3_common *cortex_m3 = calloc(1, sizeof(struct cortex_m3_common));
302
303 if (!cortex_m3)
304 return ERROR_COMMAND_SYNTAX_ERROR;
305
306 stm32_stlink_init_arch_info(target, cortex_m3, target->tap);
307
308 return ERROR_OK;
309 }
310
311 static int stm32_stlink_load_context(struct target *target)
312 {
313 struct armv7m_common *armv7m = target_to_armv7m(target);
314 int num_regs = armv7m->core_cache->num_regs;
315
316 for (int i = 0; i < num_regs; i++) {
317 if (!armv7m->core_cache->reg_list[i].valid)
318 armv7m->read_core_reg(target, i);
319 }
320
321 return ERROR_OK;
322 }
323
324 static int stlink_debug_entry(struct target *target)
325 {
326 struct armv7m_common *armv7m = target_to_armv7m(target);
327 struct arm *arm = &armv7m->arm;
328 struct reg *r;
329 uint32_t xPSR;
330 int retval;
331
332 retval = armv7m->examine_debug_reason(target);
333 if (retval != ERROR_OK)
334 return retval;
335
336 stm32_stlink_load_context(target);
337
338 r = armv7m->core_cache->reg_list + ARMV7M_xPSR;
339 xPSR = buf_get_u32(r->value, 0, 32);
340
341 /* Are we in an exception handler */
342 if (xPSR & 0x1FF) {
343 armv7m->core_mode = ARMV7M_MODE_HANDLER;
344 armv7m->exception_number = (xPSR & 0x1FF);
345
346 arm->core_mode = ARM_MODE_HANDLER;
347 arm->map = armv7m_msp_reg_map;
348 } else {
349 unsigned control = buf_get_u32(armv7m->core_cache
350 ->reg_list[ARMV7M_CONTROL].value, 0, 2);
351
352 /* is this thread privileged? */
353 armv7m->core_mode = control & 1;
354 arm->core_mode = armv7m->core_mode
355 ? ARM_MODE_USER_THREAD
356 : ARM_MODE_THREAD;
357
358 /* which stack is it using? */
359 if (control & 2)
360 arm->map = armv7m_psp_reg_map;
361 else
362 arm->map = armv7m_msp_reg_map;
363
364 armv7m->exception_number = 0;
365 }
366
367 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32 ", target->state: %s",
368 armv7m_mode_strings[armv7m->core_mode],
369 *(uint32_t *)(arm->pc->value),
370 target_state_name(target));
371
372 return retval;
373 }
374
375 static int stm32_stlink_poll(struct target *target)
376 {
377 enum target_state state;
378 struct stlink_interface_s *stlink_if = target_to_stlink(target);
379 struct armv7m_common *armv7m = target_to_armv7m(target);
380
381 state = stlink_if->layout->api->state(stlink_if->fd);
382
383 if (state == TARGET_UNKNOWN) {
384 LOG_ERROR("jtag status contains invalid mode value - communication failure");
385 return ERROR_TARGET_FAILURE;
386 }
387
388 if (target->state == state)
389 return ERROR_OK;
390
391 if (state == TARGET_HALTED) {
392 target->state = state;
393
394 int retval = stlink_debug_entry(target);
395 if (retval != ERROR_OK)
396 return retval;
397
398 if (arm_semihosting(target, &retval) != 0)
399 return retval;
400
401 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
402 LOG_DEBUG("halted: PC: 0x%08x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
403 }
404
405 return ERROR_OK;
406 }
407
408 static int stm32_stlink_assert_reset(struct target *target)
409 {
410 int res = ERROR_OK;
411 struct stlink_interface_s *stlink_if = target_to_stlink(target);
412 struct armv7m_common *armv7m = target_to_armv7m(target);
413 bool use_srst_fallback = true;
414
415 LOG_DEBUG("%s", __func__);
416
417 enum reset_types jtag_reset_config = jtag_get_reset_config();
418
419 bool srst_asserted = false;
420
421 if (jtag_reset_config & RESET_SRST_NO_GATING) {
422 jtag_add_reset(0, 1);
423 res = stlink_if->layout->api->assert_srst(stlink_if->fd, 0);
424 srst_asserted = true;
425 }
426
427 stlink_if->layout->api->write_debug_reg(stlink_if->fd, DCB_DHCSR, DBGKEY|C_DEBUGEN);
428 stlink_if->layout->api->write_debug_reg(stlink_if->fd, DCB_DEMCR, VC_CORERESET);
429
430 if (jtag_reset_config & RESET_HAS_SRST) {
431 if (!srst_asserted) {
432 jtag_add_reset(0, 1);
433 res = stlink_if->layout->api->assert_srst(stlink_if->fd, 0);
434 }
435 if (res == ERROR_COMMAND_NOTFOUND)
436 LOG_ERROR("Hardware srst not supported, falling back to software reset");
437 else if (res == ERROR_OK) {
438 /* hardware srst supported */
439 use_srst_fallback = false;
440 }
441 }
442
443 if (use_srst_fallback) {
444 /* stlink v1 api does support hardware srst, so we use a software reset fallback */
445 stlink_if->layout->api->write_debug_reg(stlink_if->fd, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
446 }
447
448 res = stlink_if->layout->api->reset(stlink_if->fd);
449
450 if (res != ERROR_OK)
451 return res;
452
453 /* registers are now invalid */
454 register_cache_invalidate(armv7m->core_cache);
455
456 if (target->reset_halt) {
457 target->state = TARGET_RESET;
458 target->debug_reason = DBG_REASON_DBGRQ;
459 } else {
460 target->state = TARGET_HALTED;
461 }
462
463 return ERROR_OK;
464 }
465
466 static int stm32_stlink_deassert_reset(struct target *target)
467 {
468 int res;
469 struct stlink_interface_s *stlink_if = target_to_stlink(target);
470
471 enum reset_types jtag_reset_config = jtag_get_reset_config();
472
473 LOG_DEBUG("%s", __func__);
474
475 if (jtag_reset_config & RESET_HAS_SRST)
476 stlink_if->layout->api->assert_srst(stlink_if->fd, 1);
477
478 /* virtual deassert reset, we need it for the internal
479 * jtag state machine
480 */
481 jtag_add_reset(0, 0);
482
483 if (!target->reset_halt) {
484 res = target_resume(target, 1, 0, 0, 0);
485
486 if (res != ERROR_OK)
487 return res;
488 }
489
490 return ERROR_OK;
491 }
492
493 static int stm32_stlink_soft_reset_halt(struct target *target)
494 {
495 LOG_DEBUG("%s", __func__);
496 return ERROR_OK;
497 }
498
499 static int stm32_stlink_halt(struct target *target)
500 {
501 int res;
502 struct stlink_interface_s *stlink_if = target_to_stlink(target);
503
504 LOG_DEBUG("%s", __func__);
505
506 if (target->state == TARGET_HALTED) {
507 LOG_DEBUG("target was already halted");
508 return ERROR_OK;
509 }
510
511 if (target->state == TARGET_UNKNOWN)
512 LOG_WARNING("target was in unknown state when halt was requested");
513
514 res = stlink_if->layout->api->halt(stlink_if->fd);
515
516 if (res != ERROR_OK)
517 return res;
518
519 target->debug_reason = DBG_REASON_DBGRQ;
520
521 return ERROR_OK;
522 }
523
524 static int stm32_stlink_resume(struct target *target, int current,
525 uint32_t address, int handle_breakpoints,
526 int debug_execution)
527 {
528 int res;
529 struct stlink_interface_s *stlink_if = target_to_stlink(target);
530 struct armv7m_common *armv7m = target_to_armv7m(target);
531 uint32_t resume_pc;
532 struct breakpoint *breakpoint = NULL;
533 struct reg *pc;
534
535 LOG_DEBUG("%s %d 0x%08x %d %d", __func__, current, address,
536 handle_breakpoints, debug_execution);
537
538 if (target->state != TARGET_HALTED) {
539 LOG_WARNING("target not halted");
540 return ERROR_TARGET_NOT_HALTED;
541 }
542
543 pc = armv7m->arm.pc;
544 if (!current) {
545 buf_set_u32(pc->value, 0, 32, address);
546 pc->dirty = true;
547 pc->valid = true;
548 }
549
550 if (!breakpoint_find(target, buf_get_u32(pc->value, 0, 32))
551 && !debug_execution) {
552 armv7m_maybe_skip_bkpt_inst(target, NULL);
553 }
554
555 resume_pc = buf_get_u32(pc->value, 0, 32);
556
557 armv7m_restore_context(target);
558
559 /* registers are now invalid */
560 register_cache_invalidate(armv7m->core_cache);
561
562 /* the front-end may request us not to handle breakpoints */
563 if (handle_breakpoints) {
564 /* Single step past breakpoint at current address */
565 breakpoint = breakpoint_find(target, resume_pc);
566 if (breakpoint) {
567 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %d)",
568 breakpoint->address,
569 breakpoint->unique_id);
570 cortex_m3_unset_breakpoint(target, breakpoint);
571
572 res = stlink_if->layout->api->step(stlink_if->fd);
573
574 if (res != ERROR_OK)
575 return res;
576
577 cortex_m3_set_breakpoint(target, breakpoint);
578 }
579 }
580
581 res = stlink_if->layout->api->run(stlink_if->fd);
582
583 if (res != ERROR_OK)
584 return res;
585
586 target->state = TARGET_RUNNING;
587
588 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
589
590 return ERROR_OK;
591 }
592
593 static int stm32_stlink_step(struct target *target, int current,
594 uint32_t address, int handle_breakpoints)
595 {
596 int res;
597 struct stlink_interface_s *stlink_if = target_to_stlink(target);
598 struct armv7m_common *armv7m = target_to_armv7m(target);
599 struct breakpoint *breakpoint = NULL;
600 struct reg *pc = armv7m->arm.pc;
601 bool bkpt_inst_found = false;
602
603 LOG_DEBUG("%s", __func__);
604
605 if (target->state != TARGET_HALTED) {
606 LOG_WARNING("target not halted");
607 return ERROR_TARGET_NOT_HALTED;
608 }
609
610 if (!current) {
611 buf_set_u32(pc->value, 0, 32, address);
612 pc->dirty = true;
613 pc->valid = true;
614 }
615
616 uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
617
618 /* the front-end may request us not to handle breakpoints */
619 if (handle_breakpoints) {
620 breakpoint = breakpoint_find(target, pc_value);
621 if (breakpoint)
622 cortex_m3_unset_breakpoint(target, breakpoint);
623 }
624
625 armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
626
627 target->debug_reason = DBG_REASON_SINGLESTEP;
628
629 armv7m_restore_context(target);
630
631 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
632
633 res = stlink_if->layout->api->step(stlink_if->fd);
634
635 if (res != ERROR_OK)
636 return res;
637
638 /* registers are now invalid */
639 register_cache_invalidate(armv7m->core_cache);
640
641 if (breakpoint)
642 cortex_m3_set_breakpoint(target, breakpoint);
643
644 stlink_debug_entry(target);
645 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
646
647 LOG_INFO("halted: PC: 0x%08x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
648
649 return ERROR_OK;
650 }
651
652 static int stm32_stlink_read_memory(struct target *target, uint32_t address,
653 uint32_t size, uint32_t count,
654 uint8_t *buffer)
655 {
656 int res;
657 uint32_t buffer_threshold = 128;
658 uint32_t addr_increment = 4;
659 uint32_t c;
660 struct stlink_interface_s *stlink_if = target_to_stlink(target);
661
662 if (!count || !buffer)
663 return ERROR_COMMAND_SYNTAX_ERROR;
664
665 LOG_DEBUG("%s 0x%08x %d %d", __func__, address, size, count);
666
667 /* prepare byte count, buffer threshold
668 * and address increment for none 32bit access
669 */
670 if (size != 4) {
671 count *= size;
672 buffer_threshold = 64;
673 addr_increment = 1;
674 }
675
676 while (count) {
677 if (count > buffer_threshold)
678 c = buffer_threshold;
679 else
680 c = count;
681
682 if (size != 4)
683 res = stlink_if->layout->api->read_mem8(stlink_if->fd,
684 address, c, buffer);
685 else
686 res = stlink_if->layout->api->read_mem32(stlink_if->fd,
687 address, c, buffer);
688
689 if (res != ERROR_OK)
690 return res;
691
692 address += (c * addr_increment);
693 buffer += (c * addr_increment);
694 count -= c;
695 }
696
697 return ERROR_OK;
698 }
699
700 static int stm32_stlink_write_memory(struct target *target, uint32_t address,
701 uint32_t size, uint32_t count,
702 const uint8_t *buffer)
703 {
704 int res;
705 uint32_t buffer_threshold = 128;
706 uint32_t addr_increment = 4;
707 uint32_t c;
708 struct stlink_interface_s *stlink_if = target_to_stlink(target);
709
710 if (!count || !buffer)
711 return ERROR_COMMAND_SYNTAX_ERROR;
712
713 LOG_DEBUG("%s 0x%08x %d %d", __func__, address, size, count);
714
715 /* prepare byte count, buffer threshold
716 * and address increment for none 32bit access
717 */
718 if (size != 4) {
719 count *= size;
720 buffer_threshold = 64;
721 addr_increment = 1;
722 }
723
724 while (count) {
725 if (count > buffer_threshold)
726 c = buffer_threshold;
727 else
728 c = count;
729
730 if (size != 4)
731 res = stlink_if->layout->api->write_mem8(stlink_if->fd,
732 address, c, buffer);
733 else
734 res = stlink_if->layout->api->write_mem32(stlink_if->fd,
735 address, c, buffer);
736
737 if (res != ERROR_OK)
738 return res;
739
740 address += (c * addr_increment);
741 buffer += (c * addr_increment);
742 count -= c;
743 }
744
745 return ERROR_OK;
746 }
747
748 static int stm32_stlink_bulk_write_memory(struct target *target,
749 uint32_t address, uint32_t count,
750 const uint8_t *buffer)
751 {
752 return stm32_stlink_write_memory(target, address, 4, count, buffer);
753 }
754
755 struct target_type stm32_stlink_target = {
756 .name = "stm32_stlink",
757
758 .init_target = stm32_stlink_init_target,
759 .target_create = stm32_stlink_target_create,
760 .examine = cortex_m3_examine,
761
762 .poll = stm32_stlink_poll,
763 .arch_state = armv7m_arch_state,
764
765 .assert_reset = stm32_stlink_assert_reset,
766 .deassert_reset = stm32_stlink_deassert_reset,
767 .soft_reset_halt = stm32_stlink_soft_reset_halt,
768
769 .halt = stm32_stlink_halt,
770 .resume = stm32_stlink_resume,
771 .step = stm32_stlink_step,
772
773 .get_gdb_reg_list = armv7m_get_gdb_reg_list,
774
775 .read_memory = stm32_stlink_read_memory,
776 .write_memory = stm32_stlink_write_memory,
777 .bulk_write_memory = stm32_stlink_bulk_write_memory,
778 .checksum_memory = armv7m_checksum_memory,
779 .blank_check_memory = armv7m_blank_check_memory,
780
781 .run_algorithm = armv7m_run_algorithm,
782 .start_algorithm = armv7m_start_algorithm,
783 .wait_algorithm = armv7m_wait_algorithm,
784
785 .add_breakpoint = cortex_m3_add_breakpoint,
786 .remove_breakpoint = cortex_m3_remove_breakpoint,
787 .add_watchpoint = cortex_m3_add_watchpoint,
788 .remove_watchpoint = cortex_m3_remove_watchpoint,
789 };

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)