1 /***************************************************************************
2 * Copyright (C) 2011 by Mathias Kuester *
3 * Mathias Kuester <kesmtp@freenet.de> *
5 * Copyright (C) 2011 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
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. *
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. *
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 ***************************************************************************/
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"
33 #include "algorithm.h"
35 #include "breakpoints.h"
36 #include "target_type.h"
39 #include "arm_semihosting.h"
41 #define ARMV7M_SCS_DCRSR 0xe000edf4
42 #define ARMV7M_SCS_DCRDR 0xe000edf8
44 static inline struct stlink_interface_s
*target_to_stlink(struct target
*target
)
46 return target
->tap
->priv
;
49 static int stm32_stlink_load_core_reg_u32(struct target
*target
,
50 enum armv7m_regtype type
,
51 uint32_t num
, uint32_t *value
)
54 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
56 LOG_DEBUG("%s", __func__
);
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.
64 /* read a normal core register */
65 retval
= stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, num
, value
);
67 if (retval
!= ERROR_OK
) {
68 LOG_ERROR("JTAG failure %i", retval
);
69 return ERROR_JTAG_DEVICE_ERROR
;
71 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"", (int)num
, *value
);
80 /* Floating-point Status and Registers */
81 retval
= target_write_u32(target
, ARMV7M_SCS_DCRSR
, 33);
82 if (retval
!= ERROR_OK
)
84 retval
= target_read_u32(target
, ARMV7M_SCS_DCRDR
, value
);
85 if (retval
!= ERROR_OK
)
87 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"", (int)num
, *value
);
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
)
95 retval
= target_read_u32(target
, ARMV7M_SCS_DCRDR
, value
);
96 if (retval
!= ERROR_OK
)
98 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"", (int)num
, *value
);
101 case ARMV7M_D0
... ARMV7M_D15
:
107 case ARMV7M_FAULTMASK
:
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.
113 retval
= stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, value
);
117 *value
= buf_get_u32((uint8_t *) value
, 0, 1);
121 *value
= buf_get_u32((uint8_t *) value
, 8, 8);
124 case ARMV7M_FAULTMASK
:
125 *value
= buf_get_u32((uint8_t *) value
, 16, 1);
129 *value
= buf_get_u32((uint8_t *) value
, 24, 2);
133 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"",
138 return ERROR_COMMAND_SYNTAX_ERROR
;
144 static int stm32_stlink_store_core_reg_u32(struct target
*target
,
145 enum armv7m_regtype type
,
146 uint32_t num
, uint32_t value
)
150 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
151 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
153 LOG_DEBUG("%s", __func__
);
155 #ifdef ARMV7_GDB_HACKS
156 /* If the LR register is being modified, make sure it will put us
157 * in "thumb" mode, or an INVSTATE exception will occur. This is a
158 * hack to deal with the fact that gdb will sometimes "forge"
159 * return addresses, and doesn't set the LSB correctly (i.e., when
160 * printing expressions containing function calls, it sets LR = 0.)
161 * Valid exception return codes have bit 0 set too.
163 if (num
== ARMV7M_R14
)
167 /* NOTE: we "know" here that the register identifiers used
168 * in the v7m header match the Cortex-M3 Debug Core Register
169 * Selector values for R0..R15, xPSR, MSP, and PSP.
173 retval
= stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, num
, value
);
175 if (retval
!= ERROR_OK
) {
178 LOG_ERROR("JTAG failure");
179 r
= armv7m
->core_cache
->reg_list
+ num
;
181 return ERROR_JTAG_DEVICE_ERROR
;
183 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
191 /* Floating-point Status and Registers */
192 retval
= target_write_u32(target
, ARMV7M_SCS_DCRDR
, value
);
193 if (retval
!= ERROR_OK
)
195 retval
= target_write_u32(target
, ARMV7M_SCS_DCRSR
, 33 | (1<<16));
196 if (retval
!= ERROR_OK
)
198 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
201 case ARMV7M_S0
... ARMV7M_S31
:
202 /* Floating-point Status and Registers */
203 retval
= target_write_u32(target
, ARMV7M_SCS_DCRDR
, value
);
204 if (retval
!= ERROR_OK
)
206 retval
= target_write_u32(target
, ARMV7M_SCS_DCRSR
, (num
-ARMV7M_S0
+64) | (1<<16));
207 if (retval
!= ERROR_OK
)
209 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
212 case ARMV7M_D0
... ARMV7M_D15
:
217 case ARMV7M_FAULTMASK
:
219 /* Cortex-M3 packages these four registers as bitfields
220 * in one Debug Core register. So say r0 and r2 docs;
221 * it was removed from r1 docs, but still works.
224 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, ®
);
228 buf_set_u32((uint8_t *) ®
, 0, 1, value
);
232 buf_set_u32((uint8_t *) ®
, 8, 8, value
);
235 case ARMV7M_FAULTMASK
:
236 buf_set_u32((uint8_t *) ®
, 16, 1, value
);
240 buf_set_u32((uint8_t *) ®
, 24, 2, value
);
244 stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, 20, reg
);
246 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
250 return ERROR_COMMAND_SYNTAX_ERROR
;
256 static int stm32_stlink_examine_debug_reason(struct target
*target
)
258 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
259 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)) {
260 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
266 static int stm32_stlink_init_arch_info(struct target
*target
,
267 struct cortex_m3_common
*cortex_m3
,
268 struct jtag_tap
*tap
)
270 struct armv7m_common
*armv7m
;
272 LOG_DEBUG("%s", __func__
);
274 armv7m
= &cortex_m3
->armv7m
;
275 armv7m_init_arch_info(target
, armv7m
);
277 armv7m
->load_core_reg_u32
= stm32_stlink_load_core_reg_u32
;
278 armv7m
->store_core_reg_u32
= stm32_stlink_store_core_reg_u32
;
280 armv7m
->examine_debug_reason
= stm32_stlink_examine_debug_reason
;
285 static int stm32_stlink_init_target(struct command_context
*cmd_ctx
,
286 struct target
*target
)
288 LOG_DEBUG("%s", __func__
);
290 armv7m_build_reg_cache(target
);
295 static int stm32_stlink_target_create(struct target
*target
,
298 LOG_DEBUG("%s", __func__
);
300 struct cortex_m3_common
*cortex_m3
= calloc(1, sizeof(struct cortex_m3_common
));
303 return ERROR_COMMAND_SYNTAX_ERROR
;
305 stm32_stlink_init_arch_info(target
, cortex_m3
, target
->tap
);
310 static int stm32_stlink_load_context(struct target
*target
)
312 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
313 int num_regs
= armv7m
->core_cache
->num_regs
;
315 for (int i
= 0; i
< num_regs
; i
++) {
316 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
317 armv7m
->read_core_reg(target
, i
);
323 static int stlink_debug_entry(struct target
*target
)
325 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
326 struct arm
*arm
= &armv7m
->arm
;
331 retval
= armv7m
->examine_debug_reason(target
);
332 if (retval
!= ERROR_OK
)
335 stm32_stlink_load_context(target
);
337 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
338 xPSR
= buf_get_u32(r
->value
, 0, 32);
340 /* Are we in an exception handler */
342 armv7m
->core_mode
= ARMV7M_MODE_HANDLER
;
343 armv7m
->exception_number
= (xPSR
& 0x1FF);
345 arm
->core_mode
= ARM_MODE_HANDLER
;
346 arm
->map
= armv7m_msp_reg_map
;
348 unsigned control
= buf_get_u32(armv7m
->core_cache
349 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 2);
351 /* is this thread privileged? */
352 armv7m
->core_mode
= control
& 1;
353 arm
->core_mode
= armv7m
->core_mode
354 ? ARM_MODE_USER_THREAD
357 /* which stack is it using? */
359 arm
->map
= armv7m_psp_reg_map
;
361 arm
->map
= armv7m_msp_reg_map
;
363 armv7m
->exception_number
= 0;
366 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32
", target->state: %s",
367 armv7m_mode_strings
[armv7m
->core_mode
],
368 *(uint32_t *)(arm
->pc
->value
),
369 target_state_name(target
));
374 static int stm32_stlink_poll(struct target
*target
)
376 enum target_state state
;
377 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
378 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
380 state
= stlink_if
->layout
->api
->state(stlink_if
->fd
);
382 if (state
== TARGET_UNKNOWN
) {
383 LOG_ERROR("jtag status contains invalid mode value - communication failure");
384 return ERROR_TARGET_FAILURE
;
387 if (target
->state
== state
)
390 if (state
== TARGET_HALTED
) {
391 target
->state
= state
;
393 int retval
= stlink_debug_entry(target
);
394 if (retval
!= ERROR_OK
)
397 if (arm_semihosting(target
, &retval
) != 0)
400 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
401 LOG_DEBUG("halted: PC: 0x%08x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
407 static int stm32_stlink_assert_reset(struct target
*target
)
410 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
411 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
412 bool use_srst_fallback
= true;
414 LOG_DEBUG("%s", __func__
);
416 enum reset_types jtag_reset_config
= jtag_get_reset_config();
418 bool srst_asserted
= false;
420 if (jtag_reset_config
& RESET_SRST_NO_GATING
) {
421 jtag_add_reset(0, 1);
422 res
= stlink_if
->layout
->api
->assert_srst(stlink_if
->fd
, 0);
423 srst_asserted
= true;
426 stlink_if
->layout
->api
->write_debug_reg(stlink_if
->fd
, DCB_DHCSR
, DBGKEY
|C_DEBUGEN
);
427 stlink_if
->layout
->api
->write_debug_reg(stlink_if
->fd
, DCB_DEMCR
, VC_CORERESET
);
429 if (jtag_reset_config
& RESET_HAS_SRST
) {
430 if (!srst_asserted
) {
431 jtag_add_reset(0, 1);
432 res
= stlink_if
->layout
->api
->assert_srst(stlink_if
->fd
, 0);
434 if (res
== ERROR_COMMAND_NOTFOUND
)
435 LOG_ERROR("Hardware srst not supported, falling back to software reset");
436 else if (res
== ERROR_OK
) {
437 /* hardware srst supported */
438 use_srst_fallback
= false;
442 if (use_srst_fallback
) {
443 /* stlink v1 api does support hardware srst, so we use a software reset fallback */
444 stlink_if
->layout
->api
->write_debug_reg(stlink_if
->fd
, NVIC_AIRCR
, AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
447 res
= stlink_if
->layout
->api
->reset(stlink_if
->fd
);
452 /* registers are now invalid */
453 register_cache_invalidate(armv7m
->core_cache
);
455 if (target
->reset_halt
) {
456 target
->state
= TARGET_RESET
;
457 target
->debug_reason
= DBG_REASON_DBGRQ
;
459 target
->state
= TARGET_HALTED
;
465 static int stm32_stlink_deassert_reset(struct target
*target
)
468 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
470 enum reset_types jtag_reset_config
= jtag_get_reset_config();
472 LOG_DEBUG("%s", __func__
);
474 if (jtag_reset_config
& RESET_HAS_SRST
)
475 stlink_if
->layout
->api
->assert_srst(stlink_if
->fd
, 1);
477 /* virtual deassert reset, we need it for the internal
480 jtag_add_reset(0, 0);
482 if (!target
->reset_halt
) {
483 res
= target_resume(target
, 1, 0, 0, 0);
492 static int stm32_stlink_soft_reset_halt(struct target
*target
)
494 LOG_DEBUG("%s", __func__
);
498 static int stm32_stlink_halt(struct target
*target
)
501 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
503 LOG_DEBUG("%s", __func__
);
505 if (target
->state
== TARGET_HALTED
) {
506 LOG_DEBUG("target was already halted");
510 if (target
->state
== TARGET_UNKNOWN
)
511 LOG_WARNING("target was in unknown state when halt was requested");
513 res
= stlink_if
->layout
->api
->halt(stlink_if
->fd
);
518 target
->debug_reason
= DBG_REASON_DBGRQ
;
523 static int stm32_stlink_resume(struct target
*target
, int current
,
524 uint32_t address
, int handle_breakpoints
,
528 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
529 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
531 struct breakpoint
*breakpoint
= NULL
;
534 LOG_DEBUG("%s %d 0x%08x %d %d", __func__
, current
, address
,
535 handle_breakpoints
, debug_execution
);
537 if (target
->state
!= TARGET_HALTED
) {
538 LOG_WARNING("target not halted");
539 return ERROR_TARGET_NOT_HALTED
;
544 buf_set_u32(pc
->value
, 0, 32, address
);
549 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
550 && !debug_execution
) {
551 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
554 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
556 armv7m_restore_context(target
);
558 /* registers are now invalid */
559 register_cache_invalidate(armv7m
->core_cache
);
561 /* the front-end may request us not to handle breakpoints */
562 if (handle_breakpoints
) {
563 /* Single step past breakpoint at current address */
564 breakpoint
= breakpoint_find(target
, resume_pc
);
566 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
568 breakpoint
->unique_id
);
569 cortex_m3_unset_breakpoint(target
, breakpoint
);
571 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
576 cortex_m3_set_breakpoint(target
, breakpoint
);
580 res
= stlink_if
->layout
->api
->run(stlink_if
->fd
);
585 target
->state
= TARGET_RUNNING
;
587 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
592 static int stm32_stlink_step(struct target
*target
, int current
,
593 uint32_t address
, int handle_breakpoints
)
596 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
597 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
598 struct breakpoint
*breakpoint
= NULL
;
599 struct reg
*pc
= armv7m
->arm
.pc
;
600 bool bkpt_inst_found
= false;
602 LOG_DEBUG("%s", __func__
);
604 if (target
->state
!= TARGET_HALTED
) {
605 LOG_WARNING("target not halted");
606 return ERROR_TARGET_NOT_HALTED
;
610 buf_set_u32(pc
->value
, 0, 32, address
);
615 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
617 /* the front-end may request us not to handle breakpoints */
618 if (handle_breakpoints
) {
619 breakpoint
= breakpoint_find(target
, pc_value
);
621 cortex_m3_unset_breakpoint(target
, breakpoint
);
624 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
626 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
628 armv7m_restore_context(target
);
630 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
632 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
637 /* registers are now invalid */
638 register_cache_invalidate(armv7m
->core_cache
);
641 cortex_m3_set_breakpoint(target
, breakpoint
);
643 stlink_debug_entry(target
);
644 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
646 LOG_INFO("halted: PC: 0x%08x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
651 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
652 uint32_t size
, uint32_t count
,
656 uint32_t buffer_threshold
= 128;
657 uint32_t addr_increment
= 4;
659 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
661 if (!count
|| !buffer
)
662 return ERROR_COMMAND_SYNTAX_ERROR
;
664 LOG_DEBUG("%s 0x%08x %d %d", __func__
, address
, size
, count
);
666 /* prepare byte count, buffer threshold
667 * and address increment for none 32bit access
671 buffer_threshold
= 64;
676 if (count
> buffer_threshold
)
677 c
= buffer_threshold
;
682 res
= stlink_if
->layout
->api
->read_mem8(stlink_if
->fd
,
685 res
= stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
,
691 address
+= (c
* addr_increment
);
692 buffer
+= (c
* addr_increment
);
699 static int stm32_stlink_write_memory(struct target
*target
, uint32_t address
,
700 uint32_t size
, uint32_t count
,
701 const uint8_t *buffer
)
704 uint32_t buffer_threshold
= 128;
705 uint32_t addr_increment
= 4;
707 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
709 if (!count
|| !buffer
)
710 return ERROR_COMMAND_SYNTAX_ERROR
;
712 LOG_DEBUG("%s 0x%08x %d %d", __func__
, address
, size
, count
);
714 /* prepare byte count, buffer threshold
715 * and address increment for none 32bit access
719 buffer_threshold
= 64;
724 if (count
> buffer_threshold
)
725 c
= buffer_threshold
;
730 res
= stlink_if
->layout
->api
->write_mem8(stlink_if
->fd
,
733 res
= stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
,
739 address
+= (c
* addr_increment
);
740 buffer
+= (c
* addr_increment
);
747 static int stm32_stlink_bulk_write_memory(struct target
*target
,
748 uint32_t address
, uint32_t count
,
749 const uint8_t *buffer
)
751 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
754 struct target_type stm32_stlink_target
= {
755 .name
= "stm32_stlink",
757 .init_target
= stm32_stlink_init_target
,
758 .target_create
= stm32_stlink_target_create
,
759 .examine
= cortex_m3_examine
,
761 .poll
= stm32_stlink_poll
,
762 .arch_state
= armv7m_arch_state
,
764 .assert_reset
= stm32_stlink_assert_reset
,
765 .deassert_reset
= stm32_stlink_deassert_reset
,
766 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
768 .halt
= stm32_stlink_halt
,
769 .resume
= stm32_stlink_resume
,
770 .step
= stm32_stlink_step
,
772 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
774 .read_memory
= stm32_stlink_read_memory
,
775 .write_memory
= stm32_stlink_write_memory
,
776 .bulk_write_memory
= stm32_stlink_bulk_write_memory
,
777 .checksum_memory
= armv7m_checksum_memory
,
778 .blank_check_memory
= armv7m_blank_check_memory
,
780 .run_algorithm
= armv7m_run_algorithm
,
781 .start_algorithm
= armv7m_start_algorithm
,
782 .wait_algorithm
= armv7m_wait_algorithm
,
784 .add_breakpoint
= cortex_m3_add_breakpoint
,
785 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
786 .add_watchpoint
= cortex_m3_add_watchpoint
,
787 .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)