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
);
76 /* Floating-point Status and Registers */
77 retval
= target_write_u32(target
, ARMV7M_SCS_DCRSR
, num
);
78 if (retval
!= ERROR_OK
)
80 retval
= target_read_u32(target
, ARMV7M_SCS_DCRDR
, value
);
81 if (retval
!= ERROR_OK
)
83 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"", (int)num
, *value
);
88 case ARMV7M_FAULTMASK
:
90 /* Cortex-M3 packages these four registers as bitfields
91 * in one Debug Core register. So say r0 and r2 docs;
92 * it was removed from r1 docs, but still works.
94 retval
= stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, value
);
98 *value
= buf_get_u32((uint8_t *) value
, 0, 1);
102 *value
= buf_get_u32((uint8_t *) value
, 8, 8);
105 case ARMV7M_FAULTMASK
:
106 *value
= buf_get_u32((uint8_t *) value
, 16, 1);
110 *value
= buf_get_u32((uint8_t *) value
, 24, 2);
114 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"",
119 return ERROR_COMMAND_SYNTAX_ERROR
;
125 static int stm32_stlink_store_core_reg_u32(struct target
*target
,
126 enum armv7m_regtype type
,
127 uint32_t num
, uint32_t value
)
131 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
132 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
134 LOG_DEBUG("%s", __func__
);
136 #ifdef ARMV7_GDB_HACKS
137 /* If the LR register is being modified, make sure it will put us
138 * in "thumb" mode, or an INVSTATE exception will occur. This is a
139 * hack to deal with the fact that gdb will sometimes "forge"
140 * return addresses, and doesn't set the LSB correctly (i.e., when
141 * printing expressions containing function calls, it sets LR = 0.)
142 * Valid exception return codes have bit 0 set too.
144 if (num
== ARMV7M_R14
)
148 /* NOTE: we "know" here that the register identifiers used
149 * in the v7m header match the Cortex-M3 Debug Core Register
150 * Selector values for R0..R15, xPSR, MSP, and PSP.
154 retval
= stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, num
, value
);
156 if (retval
!= ERROR_OK
) {
159 LOG_ERROR("JTAG failure");
160 r
= armv7m
->core_cache
->reg_list
+ num
;
162 return ERROR_JTAG_DEVICE_ERROR
;
164 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
169 /* Floating-point Status and Registers */
170 retval
= target_write_u32(target
, ARMV7M_SCS_DCRDR
, value
);
171 if (retval
!= ERROR_OK
)
173 retval
= target_write_u32(target
, ARMV7M_SCS_DCRSR
, num
| (1<<16));
174 if (retval
!= ERROR_OK
)
176 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
181 case ARMV7M_FAULTMASK
:
183 /* Cortex-M3 packages these four registers as bitfields
184 * in one Debug Core register. So say r0 and r2 docs;
185 * it was removed from r1 docs, but still works.
188 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, ®
);
192 buf_set_u32((uint8_t *) ®
, 0, 1, value
);
196 buf_set_u32((uint8_t *) ®
, 8, 8, value
);
199 case ARMV7M_FAULTMASK
:
200 buf_set_u32((uint8_t *) ®
, 16, 1, value
);
204 buf_set_u32((uint8_t *) ®
, 24, 2, value
);
208 stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, 20, reg
);
210 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
214 return ERROR_COMMAND_SYNTAX_ERROR
;
220 static int stm32_stlink_examine_debug_reason(struct target
*target
)
222 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
223 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)) {
224 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
230 static int stm32_stlink_init_arch_info(struct target
*target
,
231 struct cortex_m3_common
*cortex_m3
,
232 struct jtag_tap
*tap
)
234 struct armv7m_common
*armv7m
;
236 LOG_DEBUG("%s", __func__
);
238 armv7m
= &cortex_m3
->armv7m
;
239 armv7m_init_arch_info(target
, armv7m
);
241 armv7m
->load_core_reg_u32
= stm32_stlink_load_core_reg_u32
;
242 armv7m
->store_core_reg_u32
= stm32_stlink_store_core_reg_u32
;
244 armv7m
->examine_debug_reason
= stm32_stlink_examine_debug_reason
;
249 static int stm32_stlink_init_target(struct command_context
*cmd_ctx
,
250 struct target
*target
)
252 LOG_DEBUG("%s", __func__
);
254 armv7m_build_reg_cache(target
);
259 static int stm32_stlink_target_create(struct target
*target
,
262 LOG_DEBUG("%s", __func__
);
264 struct cortex_m3_common
*cortex_m3
= calloc(1, sizeof(struct cortex_m3_common
));
267 return ERROR_COMMAND_SYNTAX_ERROR
;
269 stm32_stlink_init_arch_info(target
, cortex_m3
, target
->tap
);
274 static int stm32_stlink_load_context(struct target
*target
)
276 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
277 int num_regs
= armv7m
->core_cache
->num_regs
;
279 for (int i
= 0; i
< num_regs
; i
++) {
280 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
281 armv7m
->read_core_reg(target
, i
);
287 static int stlink_debug_entry(struct target
*target
)
289 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
290 struct arm
*arm
= &armv7m
->arm
;
295 retval
= armv7m
->examine_debug_reason(target
);
296 if (retval
!= ERROR_OK
)
299 stm32_stlink_load_context(target
);
301 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
302 xPSR
= buf_get_u32(r
->value
, 0, 32);
304 /* Are we in an exception handler */
306 armv7m
->core_mode
= ARMV7M_MODE_HANDLER
;
307 armv7m
->exception_number
= (xPSR
& 0x1FF);
309 arm
->core_mode
= ARM_MODE_HANDLER
;
310 arm
->map
= armv7m_msp_reg_map
;
312 unsigned control
= buf_get_u32(armv7m
->core_cache
313 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 2);
315 /* is this thread privileged? */
316 armv7m
->core_mode
= control
& 1;
317 arm
->core_mode
= armv7m
->core_mode
318 ? ARM_MODE_USER_THREAD
321 /* which stack is it using? */
323 arm
->map
= armv7m_psp_reg_map
;
325 arm
->map
= armv7m_msp_reg_map
;
327 armv7m
->exception_number
= 0;
330 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32
", target->state: %s",
331 armv7m_mode_strings
[armv7m
->core_mode
],
332 *(uint32_t *)(arm
->pc
->value
),
333 target_state_name(target
));
338 static int stm32_stlink_poll(struct target
*target
)
340 enum target_state state
;
341 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
342 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
344 state
= stlink_if
->layout
->api
->state(stlink_if
->fd
);
346 if (state
== TARGET_UNKNOWN
) {
347 LOG_ERROR("jtag status contains invalid mode value - communication failure");
348 return ERROR_TARGET_FAILURE
;
351 if (target
->state
== state
)
354 if (state
== TARGET_HALTED
) {
355 target
->state
= state
;
357 int retval
= stlink_debug_entry(target
);
358 if (retval
!= ERROR_OK
)
361 if (arm_semihosting(target
, &retval
) != 0)
364 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
365 LOG_DEBUG("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
371 static int stm32_stlink_assert_reset(struct target
*target
)
374 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
375 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
377 LOG_DEBUG("%s", __func__
);
379 res
= stlink_if
->layout
->api
->reset(stlink_if
->fd
);
384 /* virtual assert reset, we need it for the internal
387 jtag_add_reset(1, 1);
389 /* registers are now invalid */
390 register_cache_invalidate(armv7m
->core_cache
);
392 if (target
->reset_halt
) {
393 target
->state
= TARGET_RESET
;
394 target
->debug_reason
= DBG_REASON_DBGRQ
;
396 target
->state
= TARGET_HALTED
;
402 static int stm32_stlink_deassert_reset(struct target
*target
)
406 LOG_DEBUG("%s", __func__
);
408 /* virtual deassert reset, we need it for the internal
411 jtag_add_reset(0, 0);
413 if (!target
->reset_halt
) {
414 res
= target_resume(target
, 1, 0, 0, 0);
423 static int stm32_stlink_soft_reset_halt(struct target
*target
)
425 LOG_DEBUG("%s", __func__
);
429 static int stm32_stlink_halt(struct target
*target
)
432 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
434 LOG_DEBUG("%s", __func__
);
436 if (target
->state
== TARGET_HALTED
) {
437 LOG_DEBUG("target was already halted");
441 if (target
->state
== TARGET_UNKNOWN
)
442 LOG_WARNING("target was in unknown state when halt was requested");
444 res
= stlink_if
->layout
->api
->halt(stlink_if
->fd
);
449 target
->debug_reason
= DBG_REASON_DBGRQ
;
454 static int stm32_stlink_resume(struct target
*target
, int current
,
455 uint32_t address
, int handle_breakpoints
,
459 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
460 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
462 struct breakpoint
*breakpoint
= NULL
;
465 LOG_DEBUG("%s %d %x %d %d", __func__
, current
, address
,
466 handle_breakpoints
, debug_execution
);
468 if (target
->state
!= TARGET_HALTED
) {
469 LOG_WARNING("target not halted");
470 return ERROR_TARGET_NOT_HALTED
;
475 buf_set_u32(pc
->value
, 0, 32, address
);
480 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
481 && !debug_execution
) {
482 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
485 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
487 armv7m_restore_context(target
);
489 /* registers are now invalid */
490 register_cache_invalidate(armv7m
->core_cache
);
492 /* the front-end may request us not to handle breakpoints */
493 if (handle_breakpoints
) {
494 /* Single step past breakpoint at current address */
495 breakpoint
= breakpoint_find(target
, resume_pc
);
497 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
499 breakpoint
->unique_id
);
500 cortex_m3_unset_breakpoint(target
, breakpoint
);
502 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
507 cortex_m3_set_breakpoint(target
, breakpoint
);
511 res
= stlink_if
->layout
->api
->run(stlink_if
->fd
);
516 target
->state
= TARGET_RUNNING
;
518 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
523 static int stm32_stlink_step(struct target
*target
, int current
,
524 uint32_t address
, int handle_breakpoints
)
527 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
528 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
529 struct breakpoint
*breakpoint
= NULL
;
530 struct reg
*pc
= armv7m
->arm
.pc
;
531 bool bkpt_inst_found
= false;
533 LOG_DEBUG("%s", __func__
);
535 if (target
->state
!= TARGET_HALTED
) {
536 LOG_WARNING("target not halted");
537 return ERROR_TARGET_NOT_HALTED
;
541 buf_set_u32(pc
->value
, 0, 32, address
);
546 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
548 /* the front-end may request us not to handle breakpoints */
549 if (handle_breakpoints
) {
550 breakpoint
= breakpoint_find(target
, pc_value
);
552 cortex_m3_unset_breakpoint(target
, breakpoint
);
555 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
557 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
559 armv7m_restore_context(target
);
561 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
563 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
568 /* registers are now invalid */
569 register_cache_invalidate(armv7m
->core_cache
);
572 cortex_m3_set_breakpoint(target
, breakpoint
);
574 stlink_debug_entry(target
);
575 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
577 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
582 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
583 uint32_t size
, uint32_t count
,
587 uint32_t buffer_threshold
= 128;
588 uint32_t addr_increment
= 4;
590 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
592 if (!count
|| !buffer
)
593 return ERROR_COMMAND_SYNTAX_ERROR
;
595 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
597 /* prepare byte count, buffer threshold
598 * and address increment for none 32bit access
602 buffer_threshold
= 64;
607 if (count
> buffer_threshold
)
608 c
= buffer_threshold
;
613 res
= stlink_if
->layout
->api
->read_mem8(stlink_if
->fd
,
616 res
= stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
,
622 address
+= (c
* addr_increment
);
623 buffer
+= (c
* addr_increment
);
630 static int stm32_stlink_write_memory(struct target
*target
, uint32_t address
,
631 uint32_t size
, uint32_t count
,
632 const uint8_t *buffer
)
635 uint32_t buffer_threshold
= 128;
636 uint32_t addr_increment
= 4;
638 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
640 if (!count
|| !buffer
)
641 return ERROR_COMMAND_SYNTAX_ERROR
;
643 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
645 /* prepare byte count, buffer threshold
646 * and address increment for none 32bit access
650 buffer_threshold
= 64;
655 if (count
> buffer_threshold
)
656 c
= buffer_threshold
;
661 res
= stlink_if
->layout
->api
->write_mem8(stlink_if
->fd
,
664 res
= stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
,
670 address
+= (c
* addr_increment
);
671 buffer
+= (c
* addr_increment
);
678 static int stm32_stlink_bulk_write_memory(struct target
*target
,
679 uint32_t address
, uint32_t count
,
680 const uint8_t *buffer
)
682 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
685 struct target_type stm32_stlink_target
= {
686 .name
= "stm32_stlink",
688 .init_target
= stm32_stlink_init_target
,
689 .target_create
= stm32_stlink_target_create
,
690 .examine
= cortex_m3_examine
,
692 .poll
= stm32_stlink_poll
,
693 .arch_state
= armv7m_arch_state
,
695 .assert_reset
= stm32_stlink_assert_reset
,
696 .deassert_reset
= stm32_stlink_deassert_reset
,
697 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
699 .halt
= stm32_stlink_halt
,
700 .resume
= stm32_stlink_resume
,
701 .step
= stm32_stlink_step
,
703 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
705 .read_memory
= stm32_stlink_read_memory
,
706 .write_memory
= stm32_stlink_write_memory
,
707 .bulk_write_memory
= stm32_stlink_bulk_write_memory
,
708 .checksum_memory
= armv7m_checksum_memory
,
709 .blank_check_memory
= armv7m_blank_check_memory
,
711 .run_algorithm
= armv7m_run_algorithm
,
712 .start_algorithm
= armv7m_start_algorithm
,
713 .wait_algorithm
= armv7m_wait_algorithm
,
715 .add_breakpoint
= cortex_m3_add_breakpoint
,
716 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
717 .add_watchpoint
= cortex_m3_add_watchpoint
,
718 .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)