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
);
413 LOG_DEBUG("%s", __func__
);
415 res
= stlink_if
->layout
->api
->reset(stlink_if
->fd
);
420 /* virtual assert reset, we need it for the internal
423 jtag_add_reset(1, 1);
425 /* registers are now invalid */
426 register_cache_invalidate(armv7m
->core_cache
);
428 if (target
->reset_halt
) {
429 target
->state
= TARGET_RESET
;
430 target
->debug_reason
= DBG_REASON_DBGRQ
;
432 target
->state
= TARGET_HALTED
;
438 static int stm32_stlink_deassert_reset(struct target
*target
)
442 LOG_DEBUG("%s", __func__
);
444 /* virtual deassert reset, we need it for the internal
447 jtag_add_reset(0, 0);
449 if (!target
->reset_halt
) {
450 res
= target_resume(target
, 1, 0, 0, 0);
459 static int stm32_stlink_soft_reset_halt(struct target
*target
)
461 LOG_DEBUG("%s", __func__
);
465 static int stm32_stlink_halt(struct target
*target
)
468 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
470 LOG_DEBUG("%s", __func__
);
472 if (target
->state
== TARGET_HALTED
) {
473 LOG_DEBUG("target was already halted");
477 if (target
->state
== TARGET_UNKNOWN
)
478 LOG_WARNING("target was in unknown state when halt was requested");
480 res
= stlink_if
->layout
->api
->halt(stlink_if
->fd
);
485 target
->debug_reason
= DBG_REASON_DBGRQ
;
490 static int stm32_stlink_resume(struct target
*target
, int current
,
491 uint32_t address
, int handle_breakpoints
,
495 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
496 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
498 struct breakpoint
*breakpoint
= NULL
;
501 LOG_DEBUG("%s %d 0x%08x %d %d", __func__
, current
, address
,
502 handle_breakpoints
, debug_execution
);
504 if (target
->state
!= TARGET_HALTED
) {
505 LOG_WARNING("target not halted");
506 return ERROR_TARGET_NOT_HALTED
;
511 buf_set_u32(pc
->value
, 0, 32, address
);
516 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
517 && !debug_execution
) {
518 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
521 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
523 armv7m_restore_context(target
);
525 /* registers are now invalid */
526 register_cache_invalidate(armv7m
->core_cache
);
528 /* the front-end may request us not to handle breakpoints */
529 if (handle_breakpoints
) {
530 /* Single step past breakpoint at current address */
531 breakpoint
= breakpoint_find(target
, resume_pc
);
533 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
535 breakpoint
->unique_id
);
536 cortex_m3_unset_breakpoint(target
, breakpoint
);
538 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
543 cortex_m3_set_breakpoint(target
, breakpoint
);
547 res
= stlink_if
->layout
->api
->run(stlink_if
->fd
);
552 target
->state
= TARGET_RUNNING
;
554 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
559 static int stm32_stlink_step(struct target
*target
, int current
,
560 uint32_t address
, int handle_breakpoints
)
563 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
564 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
565 struct breakpoint
*breakpoint
= NULL
;
566 struct reg
*pc
= armv7m
->arm
.pc
;
567 bool bkpt_inst_found
= false;
569 LOG_DEBUG("%s", __func__
);
571 if (target
->state
!= TARGET_HALTED
) {
572 LOG_WARNING("target not halted");
573 return ERROR_TARGET_NOT_HALTED
;
577 buf_set_u32(pc
->value
, 0, 32, address
);
582 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
584 /* the front-end may request us not to handle breakpoints */
585 if (handle_breakpoints
) {
586 breakpoint
= breakpoint_find(target
, pc_value
);
588 cortex_m3_unset_breakpoint(target
, breakpoint
);
591 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
593 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
595 armv7m_restore_context(target
);
597 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
599 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
604 /* registers are now invalid */
605 register_cache_invalidate(armv7m
->core_cache
);
608 cortex_m3_set_breakpoint(target
, breakpoint
);
610 stlink_debug_entry(target
);
611 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
613 LOG_INFO("halted: PC: 0x%08x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
618 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
619 uint32_t size
, uint32_t count
,
623 uint32_t buffer_threshold
= 128;
624 uint32_t addr_increment
= 4;
626 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
628 if (!count
|| !buffer
)
629 return ERROR_COMMAND_SYNTAX_ERROR
;
631 LOG_DEBUG("%s 0x%08x %d %d", __func__
, address
, size
, count
);
633 /* prepare byte count, buffer threshold
634 * and address increment for none 32bit access
638 buffer_threshold
= 64;
643 if (count
> buffer_threshold
)
644 c
= buffer_threshold
;
649 res
= stlink_if
->layout
->api
->read_mem8(stlink_if
->fd
,
652 res
= stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
,
658 address
+= (c
* addr_increment
);
659 buffer
+= (c
* addr_increment
);
666 static int stm32_stlink_write_memory(struct target
*target
, uint32_t address
,
667 uint32_t size
, uint32_t count
,
668 const uint8_t *buffer
)
671 uint32_t buffer_threshold
= 128;
672 uint32_t addr_increment
= 4;
674 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
676 if (!count
|| !buffer
)
677 return ERROR_COMMAND_SYNTAX_ERROR
;
679 LOG_DEBUG("%s 0x%08x %d %d", __func__
, address
, size
, count
);
681 /* prepare byte count, buffer threshold
682 * and address increment for none 32bit access
686 buffer_threshold
= 64;
691 if (count
> buffer_threshold
)
692 c
= buffer_threshold
;
697 res
= stlink_if
->layout
->api
->write_mem8(stlink_if
->fd
,
700 res
= stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
,
706 address
+= (c
* addr_increment
);
707 buffer
+= (c
* addr_increment
);
714 static int stm32_stlink_bulk_write_memory(struct target
*target
,
715 uint32_t address
, uint32_t count
,
716 const uint8_t *buffer
)
718 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
721 struct target_type stm32_stlink_target
= {
722 .name
= "stm32_stlink",
724 .init_target
= stm32_stlink_init_target
,
725 .target_create
= stm32_stlink_target_create
,
726 .examine
= cortex_m3_examine
,
728 .poll
= stm32_stlink_poll
,
729 .arch_state
= armv7m_arch_state
,
731 .assert_reset
= stm32_stlink_assert_reset
,
732 .deassert_reset
= stm32_stlink_deassert_reset
,
733 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
735 .halt
= stm32_stlink_halt
,
736 .resume
= stm32_stlink_resume
,
737 .step
= stm32_stlink_step
,
739 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
741 .read_memory
= stm32_stlink_read_memory
,
742 .write_memory
= stm32_stlink_write_memory
,
743 .bulk_write_memory
= stm32_stlink_bulk_write_memory
,
744 .checksum_memory
= armv7m_checksum_memory
,
745 .blank_check_memory
= armv7m_blank_check_memory
,
747 .run_algorithm
= armv7m_run_algorithm
,
748 .start_algorithm
= armv7m_start_algorithm
,
749 .wait_algorithm
= armv7m_wait_algorithm
,
751 .add_breakpoint
= cortex_m3_add_breakpoint
,
752 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
753 .add_watchpoint
= cortex_m3_add_watchpoint
,
754 .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)