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

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)