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

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)