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

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)