build: remove unused variables
[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_COMMAND_SYNTAX_ERROR;
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_COMMAND_SYNTAX_ERROR;
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_COMMAND_SYNTAX_ERROR;
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_COMMAND_SYNTAX_ERROR;
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 if (!current) {
515 buf_set_u32(pc->value, 0, 32, address);
516 pc->dirty = true;
517 pc->valid = true;
518 }
519
520 uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
521
522 /* the front-end may request us not to handle breakpoints */
523 if (handle_breakpoints) {
524 breakpoint = breakpoint_find(target, pc_value);
525 if (breakpoint)
526 cortex_m3_unset_breakpoint(target, breakpoint);
527 }
528
529 armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
530
531 target->debug_reason = DBG_REASON_SINGLESTEP;
532
533 armv7m_restore_context(target);
534
535 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
536
537 res = stlink_if->layout->api->step(stlink_if->fd);
538
539 if (res != ERROR_OK)
540 return res;
541
542 /* registers are now invalid */
543 register_cache_invalidate(armv7m->core_cache);
544
545 if (breakpoint)
546 cortex_m3_set_breakpoint(target, breakpoint);
547
548 target->debug_reason = DBG_REASON_SINGLESTEP;
549 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
550
551 stm32_stlink_load_context(target);
552
553 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m->arm.pc->value, 0, 32));
554
555 return ERROR_OK;
556 }
557
558 static int stm32_stlink_read_memory(struct target *target, uint32_t address,
559 uint32_t size, uint32_t count,
560 uint8_t *buffer)
561 {
562 int res;
563 uint32_t *dst = (uint32_t *) buffer;
564 uint32_t c;
565 struct stlink_interface_s *stlink_if = target_to_stlink(target);
566
567 if (!count || !buffer)
568 return ERROR_COMMAND_SYNTAX_ERROR;
569 if (size != 4) {
570 LOG_DEBUG("%s %x %d %d", __func__, address, size, count);
571 return ERROR_COMMAND_SYNTAX_ERROR;
572 }
573
574 while (count) {
575 if (count > 128)
576 c = 128;
577 else
578 c = count;
579
580 res =
581 stlink_if->layout->api->read_mem32(stlink_if->fd, address,
582 c, dst);
583
584 if (res != ERROR_OK)
585 return res;
586 dst += c;
587 address += (c * 4);
588 count -= c;
589 }
590
591 return ERROR_OK;
592 }
593
594 static int stm32_stlink_write_memory(struct target *target, uint32_t address,
595 uint32_t size, uint32_t count,
596 const uint8_t *buffer)
597 {
598 int res;
599 uint32_t *dst = (uint32_t *) buffer;
600 uint32_t c;
601 struct stlink_interface_s *stlink_if = target_to_stlink(target);
602
603 if (!count || !buffer)
604 return ERROR_COMMAND_SYNTAX_ERROR;
605 if (size != 4) {
606 LOG_DEBUG("%s %x %d %d", __func__, address, size, count);
607 return ERROR_COMMAND_SYNTAX_ERROR;
608 }
609
610 while (count) {
611 if (count > 128)
612 c = 128;
613 else
614 c = count;
615
616 res =
617 stlink_if->layout->api->write_mem32(stlink_if->fd, address,
618 c, dst);
619
620 if (res != ERROR_OK)
621 return res;
622 dst += c;
623 address += (c * 4);
624 count -= c;
625 }
626
627 return ERROR_OK;
628 }
629
630 static int stm32_stlink_bulk_write_memory(struct target *target,
631 uint32_t address, uint32_t count,
632 const uint8_t *buffer)
633 {
634 return stm32_stlink_write_memory(target, address, 4, count, buffer);
635 }
636
637 struct target_type stm32_stlink_target = {
638 .name = "stm32_stlink",
639
640 .init_target = stm32_stlink_init_target,
641 .target_create = stm32_stlink_target_create,
642 .examine = stm32_stlink_examine,
643
644 .poll = stm32_stlink_poll,
645 .arch_state = stm32_stlink_arch_state,
646
647 .assert_reset = stm32_stlink_assert_reset,
648 .deassert_reset = stm32_stlink_deassert_reset,
649 .soft_reset_halt = stm32_stlink_soft_reset_halt,
650
651 .halt = stm32_stlink_halt,
652 .resume = stm32_stlink_resume,
653 .step = stm32_stlink_step,
654
655 .get_gdb_reg_list = armv7m_get_gdb_reg_list,
656
657 .read_memory = stm32_stlink_read_memory,
658 .write_memory = stm32_stlink_write_memory,
659 .bulk_write_memory = stm32_stlink_bulk_write_memory,
660
661 .run_algorithm = armv7m_run_algorithm,
662 .start_algorithm = armv7m_start_algorithm,
663 .wait_algorithm = armv7m_wait_algorithm,
664
665 .add_breakpoint = cortex_m3_add_breakpoint,
666 .remove_breakpoint = cortex_m3_remove_breakpoint,
667 .add_watchpoint = cortex_m3_add_watchpoint,
668 .remove_watchpoint = cortex_m3_remove_watchpoint,
669 };

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)