1 /***************************************************************************
2 * Copyright (C) 2011 by Mathias Kuester *
3 * Mathias Kuester <kesmtp@freenet.de> *
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. *
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. *
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 ***************************************************************************/
24 #include "jtag/jtag.h"
25 #include "jtag/stlink/stlink_interface.h"
26 #include "jtag/stlink/stlink_layout.h"
28 #include "algorithm.h"
30 #include "breakpoints.h"
31 #include "target_type.h"
35 static inline struct stlink_interface_s
*target_to_stlink(struct target
*target
)
37 return target
->tap
->priv
;
40 static int stm32_stlink_load_core_reg_u32(struct target
*target
,
41 enum armv7m_regtype type
,
42 uint32_t num
, uint32_t *value
)
45 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
47 LOG_DEBUG("%s", __func__
);
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.
55 /* read a normal core register */
57 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, num
, value
);
59 if (retval
!= ERROR_OK
) {
60 LOG_ERROR("JTAG failure %i", retval
);
61 return ERROR_JTAG_DEVICE_ERROR
;
63 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"",
69 case ARMV7M_FAULTMASK
:
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.
76 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, value
);
80 *value
= buf_get_u32((uint8_t *) value
, 0, 1);
84 *value
= buf_get_u32((uint8_t *) value
, 8, 8);
87 case ARMV7M_FAULTMASK
:
88 *value
= buf_get_u32((uint8_t *) value
, 16, 1);
92 *value
= buf_get_u32((uint8_t *) value
, 24, 2);
96 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"",
101 return ERROR_COMMAND_SYNTAX_ERROR
;
107 static int stm32_stlink_store_core_reg_u32(struct target
*target
,
108 enum armv7m_regtype type
,
109 uint32_t num
, uint32_t value
)
113 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
114 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
116 LOG_DEBUG("%s", __func__
);
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.
126 if (num
== ARMV7M_R14
)
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.
136 retval
= stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, num
, value
);
138 if (retval
!= ERROR_OK
) {
141 LOG_ERROR("JTAG failure");
142 r
= armv7m
->core_cache
->reg_list
+ num
;
144 return ERROR_JTAG_DEVICE_ERROR
;
146 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
151 case ARMV7M_FAULTMASK
:
153 /* Cortex-M3 packages these four registers as bitfields
154 * in one Debug Core register. So say r0 and r2 docs;
155 * it was removed from r1 docs, but still works.
158 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, ®
);
162 buf_set_u32((uint8_t *) ®
, 0, 1, value
);
166 buf_set_u32((uint8_t *) ®
, 8, 8, value
);
169 case ARMV7M_FAULTMASK
:
170 buf_set_u32((uint8_t *) ®
, 16, 1, value
);
174 buf_set_u32((uint8_t *) ®
, 24, 2, value
);
178 stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, 20, reg
);
180 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
184 return ERROR_COMMAND_SYNTAX_ERROR
;
190 static int stm32_stlink_init_arch_info(struct target
*target
,
191 struct cortex_m3_common
*cortex_m3
,
192 struct jtag_tap
*tap
)
194 struct armv7m_common
*armv7m
;
196 LOG_DEBUG("%s", __func__
);
198 armv7m
= &cortex_m3
->armv7m
;
199 armv7m_init_arch_info(target
, armv7m
);
201 armv7m
->load_core_reg_u32
= stm32_stlink_load_core_reg_u32
;
202 armv7m
->store_core_reg_u32
= stm32_stlink_store_core_reg_u32
;
207 static int stm32_stlink_init_target(struct command_context
*cmd_ctx
,
208 struct target
*target
)
210 LOG_DEBUG("%s", __func__
);
212 armv7m_build_reg_cache(target
);
217 static int stm32_stlink_target_create(struct target
*target
,
220 LOG_DEBUG("%s", __func__
);
222 struct cortex_m3_common
*cortex_m3
= calloc(1, sizeof(struct cortex_m3_common
));
225 return ERROR_COMMAND_SYNTAX_ERROR
;
227 stm32_stlink_init_arch_info(target
, cortex_m3
, target
->tap
);
232 static int stm32_stlink_poll(struct target
*target
);
234 static int stm32_stlink_examine(struct target
*target
)
237 uint32_t cpuid
, fpcr
;
238 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
240 LOG_DEBUG("%s", __func__
);
242 if (target
->tap
->hasidcode
== false) {
243 LOG_ERROR("no IDCODE present on device");
245 return ERROR_COMMAND_SYNTAX_ERROR
;
248 if (!target_was_examined(target
)) {
249 target_set_examined(target
);
251 stm32_stlink_poll(target
);
253 LOG_INFO("IDCODE %x", target
->tap
->idcode
);
255 /* Read from Device Identification Registers */
256 retval
= target_read_u32(target
, CPUID
, &cpuid
);
257 if (retval
!= ERROR_OK
)
260 if (((cpuid
>> 4) & 0xc3f) == 0xc23)
261 LOG_DEBUG("Cortex-M3 r%" PRId8
"p%" PRId8
" processor detected",
262 (uint8_t)((cpuid
>> 20) & 0xf), (uint8_t)((cpuid
>> 0) & 0xf));
263 LOG_DEBUG("cpuid: 0x%8.8" PRIx32
"", cpuid
);
266 target_read_u32(target
, FP_CTRL
, &fpcr
);
267 cortex_m3
->auto_bp_type
= 1;
268 cortex_m3
->fp_num_code
= ((fpcr
>> 8) & 0x70) |
269 ((fpcr
>> 4) & 0xF); /* bits [14:12] and [7:4] */
270 cortex_m3
->fp_num_lit
= (fpcr
>> 8) & 0xF;
271 cortex_m3
->fp_code_available
= cortex_m3
->fp_num_code
;
272 cortex_m3
->fp_comparator_list
= calloc(cortex_m3
->fp_num_code
+
273 cortex_m3
->fp_num_lit
, sizeof(struct cortex_m3_fp_comparator
));
274 cortex_m3
->fpb_enabled
= fpcr
& 1;
275 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++) {
276 cortex_m3
->fp_comparator_list
[i
].type
=
277 (i
< cortex_m3
->fp_num_code
) ? FPCR_CODE
: FPCR_LITERAL
;
278 cortex_m3
->fp_comparator_list
[i
].fpcr_address
= FP_COMP0
+ 4 * i
;
280 LOG_DEBUG("FPB fpcr 0x%" PRIx32
", numcode %i, numlit %i", fpcr
,
281 cortex_m3
->fp_num_code
, cortex_m3
->fp_num_lit
);
284 cortex_m3_dwt_setup(cortex_m3
, target
);
286 /* These hardware breakpoints only work for code in flash! */
287 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
289 cortex_m3
->fp_num_code
,
290 cortex_m3
->dwt_num_comp
);
296 static int stm32_stlink_load_context(struct target
*target
)
298 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
300 for (unsigned i
= 0; i
< 23; i
++) {
301 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
302 armv7m
->read_core_reg(target
, i
);
308 static int stm32_stlink_poll(struct target
*target
)
310 enum target_state state
;
311 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
312 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
314 state
= stlink_if
->layout
->api
->state(stlink_if
->fd
);
316 if (state
== TARGET_UNKNOWN
) {
318 ("jtag status contains invalid mode value - communication failure");
319 return ERROR_TARGET_FAILURE
;
322 if (target
->state
== state
)
325 if (state
== TARGET_HALTED
) {
326 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
327 target
->state
= state
;
329 stm32_stlink_load_context(target
);
331 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
337 static int stm32_stlink_arch_state(struct target
*target
)
339 LOG_DEBUG("%s", __func__
);
343 static int stm32_stlink_assert_reset(struct target
*target
)
346 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
347 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
349 LOG_DEBUG("%s", __func__
);
351 res
= stlink_if
->layout
->api
->reset(stlink_if
->fd
);
356 /* virtual assert reset, we need it for the internal
359 jtag_add_reset(1, 1);
361 /* registers are now invalid */
362 register_cache_invalidate(armv7m
->core_cache
);
364 stm32_stlink_load_context(target
);
366 target
->state
= TARGET_HALTED
;
371 static int stm32_stlink_deassert_reset(struct target
*target
)
375 LOG_DEBUG("%s", __func__
);
377 /* virtual deassert reset, we need it for the internal
380 jtag_add_reset(0, 0);
382 if (!target
->reset_halt
) {
383 res
= target_resume(target
, 1, 0, 0, 0);
392 static int stm32_stlink_soft_reset_halt(struct target
*target
)
394 LOG_DEBUG("%s", __func__
);
398 static int stm32_stlink_halt(struct target
*target
)
401 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
403 LOG_DEBUG("%s", __func__
);
405 if (target
->state
== TARGET_HALTED
) {
406 LOG_DEBUG("target was already halted");
410 if (target
->state
== TARGET_UNKNOWN
) {
412 ("target was in unknown state when halt was requested");
415 res
= stlink_if
->layout
->api
->halt(stlink_if
->fd
);
420 target
->debug_reason
= DBG_REASON_DBGRQ
;
425 static int stm32_stlink_resume(struct target
*target
, int current
,
426 uint32_t address
, int handle_breakpoints
,
430 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
431 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
433 struct breakpoint
*breakpoint
= NULL
;
436 LOG_DEBUG("%s %d %x %d %d", __func__
, current
, address
,
437 handle_breakpoints
, debug_execution
);
439 if (target
->state
!= TARGET_HALTED
) {
440 LOG_WARNING("target not halted");
441 return ERROR_TARGET_NOT_HALTED
;
446 buf_set_u32(pc
->value
, 0, 32, address
);
451 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
452 && !debug_execution
) {
453 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
456 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
458 armv7m_restore_context(target
);
460 /* registers are now invalid */
461 register_cache_invalidate(armv7m
->core_cache
);
463 /* the front-end may request us not to handle breakpoints */
464 if (handle_breakpoints
) {
465 /* Single step past breakpoint at current address */
466 breakpoint
= breakpoint_find(target
, resume_pc
);
468 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
470 breakpoint
->unique_id
);
471 cortex_m3_unset_breakpoint(target
, breakpoint
);
473 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
478 cortex_m3_set_breakpoint(target
, breakpoint
);
482 res
= stlink_if
->layout
->api
->run(stlink_if
->fd
);
487 target
->state
= TARGET_RUNNING
;
489 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
494 static int stm32_stlink_step(struct target
*target
, int current
,
495 uint32_t address
, int handle_breakpoints
)
498 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
499 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
500 struct breakpoint
*breakpoint
= NULL
;
501 struct reg
*pc
= armv7m
->arm
.pc
;
502 bool bkpt_inst_found
= false;
504 LOG_DEBUG("%s", __func__
);
506 if (target
->state
!= TARGET_HALTED
) {
507 LOG_WARNING("target not halted");
508 return ERROR_TARGET_NOT_HALTED
;
512 buf_set_u32(pc
->value
, 0, 32, address
);
517 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
519 /* the front-end may request us not to handle breakpoints */
520 if (handle_breakpoints
) {
521 breakpoint
= breakpoint_find(target
, pc_value
);
523 cortex_m3_unset_breakpoint(target
, breakpoint
);
526 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
528 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
530 armv7m_restore_context(target
);
532 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
534 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
539 /* registers are now invalid */
540 register_cache_invalidate(armv7m
->core_cache
);
543 cortex_m3_set_breakpoint(target
, breakpoint
);
545 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
546 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
548 stm32_stlink_load_context(target
);
550 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
555 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
556 uint32_t size
, uint32_t count
,
560 uint32_t buffer_threshold
= 128;
561 uint32_t addr_increment
= 4;
562 uint8_t *dst
= buffer
;
564 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
566 if (!count
|| !buffer
)
567 return ERROR_COMMAND_SYNTAX_ERROR
;
569 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
571 /* prepare byte count, buffer threshold
572 * and address increment for none 32bit access
576 buffer_threshold
= 64;
581 if (count
> buffer_threshold
)
582 c
= buffer_threshold
;
588 stlink_if
->layout
->api
->read_mem8(stlink_if
->fd
, address
,
592 stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
, address
,
598 address
+= (c
* addr_increment
);
599 dst
+= (c
* addr_increment
);
606 static int stm32_stlink_write_memory(struct target
*target
, uint32_t address
,
607 uint32_t size
, uint32_t count
,
608 const uint8_t *buffer
)
611 uint32_t buffer_threshold
= 128;
612 uint32_t addr_increment
= 4;
613 const uint8_t *dst
= buffer
;
615 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
617 if (!count
|| !buffer
)
618 return ERROR_COMMAND_SYNTAX_ERROR
;
620 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
622 /* prepare byte count, buffer threshold
623 * and address increment for none 32bit access
627 buffer_threshold
= 64;
632 if (count
> buffer_threshold
)
633 c
= buffer_threshold
;
639 stlink_if
->layout
->api
->write_mem8(stlink_if
->fd
, address
,
643 stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
, address
,
649 address
+= (c
* addr_increment
);
650 dst
+= (c
* addr_increment
);
657 static int stm32_stlink_bulk_write_memory(struct target
*target
,
658 uint32_t address
, uint32_t count
,
659 const uint8_t *buffer
)
661 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
664 struct target_type stm32_stlink_target
= {
665 .name
= "stm32_stlink",
667 .init_target
= stm32_stlink_init_target
,
668 .target_create
= stm32_stlink_target_create
,
669 .examine
= stm32_stlink_examine
,
671 .poll
= stm32_stlink_poll
,
672 .arch_state
= stm32_stlink_arch_state
,
674 .assert_reset
= stm32_stlink_assert_reset
,
675 .deassert_reset
= stm32_stlink_deassert_reset
,
676 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
678 .halt
= stm32_stlink_halt
,
679 .resume
= stm32_stlink_resume
,
680 .step
= stm32_stlink_step
,
682 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
684 .read_memory
= stm32_stlink_read_memory
,
685 .write_memory
= stm32_stlink_write_memory
,
686 .bulk_write_memory
= stm32_stlink_bulk_write_memory
,
688 .run_algorithm
= armv7m_run_algorithm
,
689 .start_algorithm
= armv7m_start_algorithm
,
690 .wait_algorithm
= armv7m_wait_algorithm
,
692 .add_breakpoint
= cortex_m3_add_breakpoint
,
693 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
694 .add_watchpoint
= cortex_m3_add_watchpoint
,
695 .remove_watchpoint
= cortex_m3_remove_watchpoint
,
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)