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 ***************************************************************************/
27 #include "jtag/jtag.h"
28 #include "jtag/stlink/stlink_transport.h"
29 #include "jtag/stlink/stlink_interface.h"
30 #include "jtag/stlink/stlink_layout.h"
32 #include "algorithm.h"
34 #include "breakpoints.h"
35 #include "target_type.h"
39 static inline struct stlink_interface_s
*target_to_stlink(struct target
*target
)
41 return target
->tap
->priv
;
44 static int stm32_stlink_load_core_reg_u32(struct target
*target
,
45 enum armv7m_regtype type
,
46 uint32_t num
, uint32_t *value
)
49 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
51 LOG_DEBUG("%s", __func__
);
53 /* NOTE: we "know" here that the register identifiers used
54 * in the v7m header match the Cortex-M3 Debug Core Register
55 * Selector values for R0..R15, xPSR, MSP, and PSP.
59 /* read a normal core register */
61 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, num
, value
);
63 if (retval
!= ERROR_OK
) {
64 LOG_ERROR("JTAG failure %i", retval
);
65 return ERROR_JTAG_DEVICE_ERROR
;
67 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"",
73 case ARMV7M_FAULTMASK
:
75 /* Cortex-M3 packages these four registers as bitfields
76 * in one Debug Core register. So say r0 and r2 docs;
77 * it was removed from r1 docs, but still works.
80 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, value
);
84 *value
= buf_get_u32((uint8_t *) value
, 0, 1);
88 *value
= buf_get_u32((uint8_t *) value
, 8, 8);
91 case ARMV7M_FAULTMASK
:
92 *value
= buf_get_u32((uint8_t *) value
, 16, 1);
96 *value
= buf_get_u32((uint8_t *) value
, 24, 2);
100 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"",
105 return ERROR_COMMAND_SYNTAX_ERROR
;
111 static int stm32_stlink_store_core_reg_u32(struct target
*target
,
112 enum armv7m_regtype type
,
113 uint32_t num
, uint32_t value
)
117 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
118 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
120 LOG_DEBUG("%s", __func__
);
122 #ifdef ARMV7_GDB_HACKS
123 /* If the LR register is being modified, make sure it will put us
124 * in "thumb" mode, or an INVSTATE exception will occur. This is a
125 * hack to deal with the fact that gdb will sometimes "forge"
126 * return addresses, and doesn't set the LSB correctly (i.e., when
127 * printing expressions containing function calls, it sets LR = 0.)
128 * Valid exception return codes have bit 0 set too.
130 if (num
== ARMV7M_R14
)
134 /* NOTE: we "know" here that the register identifiers used
135 * in the v7m header match the Cortex-M3 Debug Core Register
136 * Selector values for R0..R15, xPSR, MSP, and PSP.
140 retval
= stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, num
, value
);
142 if (retval
!= ERROR_OK
) {
145 LOG_ERROR("JTAG failure");
146 r
= armv7m
->core_cache
->reg_list
+ num
;
148 return ERROR_JTAG_DEVICE_ERROR
;
150 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
155 case ARMV7M_FAULTMASK
:
157 /* Cortex-M3 packages these four registers as bitfields
158 * in one Debug Core register. So say r0 and r2 docs;
159 * it was removed from r1 docs, but still works.
162 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, ®
);
166 buf_set_u32((uint8_t *) ®
, 0, 1, value
);
170 buf_set_u32((uint8_t *) ®
, 8, 8, value
);
173 case ARMV7M_FAULTMASK
:
174 buf_set_u32((uint8_t *) ®
, 16, 1, value
);
178 buf_set_u32((uint8_t *) ®
, 24, 2, value
);
182 stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, 20, reg
);
184 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
188 return ERROR_COMMAND_SYNTAX_ERROR
;
194 static int stm32_stlink_examine_debug_reason(struct target
*target
)
196 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
197 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)) {
198 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
204 static int stm32_stlink_init_arch_info(struct target
*target
,
205 struct cortex_m3_common
*cortex_m3
,
206 struct jtag_tap
*tap
)
208 struct armv7m_common
*armv7m
;
210 LOG_DEBUG("%s", __func__
);
212 armv7m
= &cortex_m3
->armv7m
;
213 armv7m_init_arch_info(target
, armv7m
);
215 armv7m
->load_core_reg_u32
= stm32_stlink_load_core_reg_u32
;
216 armv7m
->store_core_reg_u32
= stm32_stlink_store_core_reg_u32
;
218 armv7m
->examine_debug_reason
= stm32_stlink_examine_debug_reason
;
223 static int stm32_stlink_init_target(struct command_context
*cmd_ctx
,
224 struct target
*target
)
226 LOG_DEBUG("%s", __func__
);
228 armv7m_build_reg_cache(target
);
233 static int stm32_stlink_target_create(struct target
*target
,
236 LOG_DEBUG("%s", __func__
);
238 struct cortex_m3_common
*cortex_m3
= calloc(1, sizeof(struct cortex_m3_common
));
241 return ERROR_COMMAND_SYNTAX_ERROR
;
243 stm32_stlink_init_arch_info(target
, cortex_m3
, target
->tap
);
248 static int stm32_stlink_examine(struct target
*target
)
251 uint32_t cpuid
, fpcr
;
252 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
254 LOG_DEBUG("%s", __func__
);
256 if (target
->tap
->hasidcode
== false) {
257 LOG_ERROR("no IDCODE present on device");
259 return ERROR_COMMAND_SYNTAX_ERROR
;
262 if (!target_was_examined(target
)) {
263 target_set_examined(target
);
265 LOG_INFO("IDCODE %x", target
->tap
->idcode
);
267 /* Read from Device Identification Registers */
268 retval
= target_read_u32(target
, CPUID
, &cpuid
);
269 if (retval
!= ERROR_OK
)
272 if (((cpuid
>> 4) & 0xc3f) == 0xc23)
273 LOG_DEBUG("Cortex-M3 r%" PRId8
"p%" PRId8
" processor detected",
274 (uint8_t)((cpuid
>> 20) & 0xf), (uint8_t)((cpuid
>> 0) & 0xf));
275 LOG_DEBUG("cpuid: 0x%8.8" PRIx32
"", cpuid
);
278 target_read_u32(target
, FP_CTRL
, &fpcr
);
279 cortex_m3
->auto_bp_type
= 1;
280 cortex_m3
->fp_num_code
= ((fpcr
>> 8) & 0x70) |
281 ((fpcr
>> 4) & 0xF); /* bits [14:12] and [7:4] */
282 cortex_m3
->fp_num_lit
= (fpcr
>> 8) & 0xF;
283 cortex_m3
->fp_code_available
= cortex_m3
->fp_num_code
;
284 cortex_m3
->fp_comparator_list
= calloc(cortex_m3
->fp_num_code
+
285 cortex_m3
->fp_num_lit
, sizeof(struct cortex_m3_fp_comparator
));
286 cortex_m3
->fpb_enabled
= fpcr
& 1;
287 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++) {
288 cortex_m3
->fp_comparator_list
[i
].type
=
289 (i
< cortex_m3
->fp_num_code
) ? FPCR_CODE
: FPCR_LITERAL
;
290 cortex_m3
->fp_comparator_list
[i
].fpcr_address
= FP_COMP0
+ 4 * i
;
292 LOG_DEBUG("FPB fpcr 0x%" PRIx32
", numcode %i, numlit %i", fpcr
,
293 cortex_m3
->fp_num_code
, cortex_m3
->fp_num_lit
);
296 cortex_m3_dwt_setup(cortex_m3
, target
);
298 /* These hardware breakpoints only work for code in flash! */
299 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
301 cortex_m3
->fp_num_code
,
302 cortex_m3
->dwt_num_comp
);
308 static int stm32_stlink_load_context(struct target
*target
)
310 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
311 int num_regs
= armv7m
->core_cache
->num_regs
;
313 for (int i
= 0; i
< num_regs
; i
++) {
314 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
315 armv7m
->read_core_reg(target
, i
);
321 static int stlink_debug_entry(struct target
*target
)
323 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
324 struct arm
*arm
= &armv7m
->arm
;
329 retval
= armv7m
->examine_debug_reason(target
);
330 if (retval
!= ERROR_OK
)
333 stm32_stlink_load_context(target
);
335 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
336 xPSR
= buf_get_u32(r
->value
, 0, 32);
338 /* Are we in an exception handler */
340 armv7m
->core_mode
= ARMV7M_MODE_HANDLER
;
341 armv7m
->exception_number
= (xPSR
& 0x1FF);
343 arm
->core_mode
= ARM_MODE_HANDLER
;
344 arm
->map
= armv7m_msp_reg_map
;
346 unsigned control
= buf_get_u32(armv7m
->core_cache
347 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 2);
349 /* is this thread privileged? */
350 armv7m
->core_mode
= control
& 1;
351 arm
->core_mode
= armv7m
->core_mode
352 ? ARM_MODE_USER_THREAD
355 /* which stack is it using? */
357 arm
->map
= armv7m_psp_reg_map
;
359 arm
->map
= armv7m_msp_reg_map
;
361 armv7m
->exception_number
= 0;
364 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32
", target->state: %s",
365 armv7m_mode_strings
[armv7m
->core_mode
],
366 *(uint32_t *)(arm
->pc
->value
),
367 target_state_name(target
));
372 static int stm32_stlink_poll(struct target
*target
)
374 enum target_state state
;
375 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
376 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
378 state
= stlink_if
->layout
->api
->state(stlink_if
->fd
);
380 if (state
== TARGET_UNKNOWN
) {
381 LOG_ERROR("jtag status contains invalid mode value - communication failure");
382 return ERROR_TARGET_FAILURE
;
385 if (target
->state
== state
)
388 if (state
== TARGET_HALTED
) {
389 target
->state
= state
;
391 stlink_debug_entry(target
);
393 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
394 LOG_DEBUG("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
400 static int stm32_stlink_assert_reset(struct target
*target
)
403 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
404 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
406 LOG_DEBUG("%s", __func__
);
408 res
= stlink_if
->layout
->api
->reset(stlink_if
->fd
);
413 /* virtual assert reset, we need it for the internal
416 jtag_add_reset(1, 1);
418 /* registers are now invalid */
419 register_cache_invalidate(armv7m
->core_cache
);
421 if (target
->reset_halt
) {
422 target
->state
= TARGET_RESET
;
423 target
->debug_reason
= DBG_REASON_DBGRQ
;
425 target
->state
= TARGET_HALTED
;
431 static int stm32_stlink_deassert_reset(struct target
*target
)
435 LOG_DEBUG("%s", __func__
);
437 /* virtual deassert reset, we need it for the internal
440 jtag_add_reset(0, 0);
442 if (!target
->reset_halt
) {
443 res
= target_resume(target
, 1, 0, 0, 0);
452 static int stm32_stlink_soft_reset_halt(struct target
*target
)
454 LOG_DEBUG("%s", __func__
);
458 static int stm32_stlink_halt(struct target
*target
)
461 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
463 LOG_DEBUG("%s", __func__
);
465 if (target
->state
== TARGET_HALTED
) {
466 LOG_DEBUG("target was already halted");
470 if (target
->state
== TARGET_UNKNOWN
) {
472 ("target was in unknown state when halt was requested");
475 res
= stlink_if
->layout
->api
->halt(stlink_if
->fd
);
480 target
->debug_reason
= DBG_REASON_DBGRQ
;
485 static int stm32_stlink_resume(struct target
*target
, int current
,
486 uint32_t address
, int handle_breakpoints
,
490 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
491 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
493 struct breakpoint
*breakpoint
= NULL
;
496 LOG_DEBUG("%s %d %x %d %d", __func__
, current
, address
,
497 handle_breakpoints
, debug_execution
);
499 if (target
->state
!= TARGET_HALTED
) {
500 LOG_WARNING("target not halted");
501 return ERROR_TARGET_NOT_HALTED
;
506 buf_set_u32(pc
->value
, 0, 32, address
);
511 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
512 && !debug_execution
) {
513 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
516 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
518 armv7m_restore_context(target
);
520 /* registers are now invalid */
521 register_cache_invalidate(armv7m
->core_cache
);
523 /* the front-end may request us not to handle breakpoints */
524 if (handle_breakpoints
) {
525 /* Single step past breakpoint at current address */
526 breakpoint
= breakpoint_find(target
, resume_pc
);
528 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
530 breakpoint
->unique_id
);
531 cortex_m3_unset_breakpoint(target
, breakpoint
);
533 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
538 cortex_m3_set_breakpoint(target
, breakpoint
);
542 res
= stlink_if
->layout
->api
->run(stlink_if
->fd
);
547 target
->state
= TARGET_RUNNING
;
549 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
554 static int stm32_stlink_step(struct target
*target
, int current
,
555 uint32_t address
, int handle_breakpoints
)
558 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
559 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
560 struct breakpoint
*breakpoint
= NULL
;
561 struct reg
*pc
= armv7m
->arm
.pc
;
562 bool bkpt_inst_found
= false;
564 LOG_DEBUG("%s", __func__
);
566 if (target
->state
!= TARGET_HALTED
) {
567 LOG_WARNING("target not halted");
568 return ERROR_TARGET_NOT_HALTED
;
572 buf_set_u32(pc
->value
, 0, 32, address
);
577 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
579 /* the front-end may request us not to handle breakpoints */
580 if (handle_breakpoints
) {
581 breakpoint
= breakpoint_find(target
, pc_value
);
583 cortex_m3_unset_breakpoint(target
, breakpoint
);
586 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
588 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
590 armv7m_restore_context(target
);
592 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
594 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
599 /* registers are now invalid */
600 register_cache_invalidate(armv7m
->core_cache
);
603 cortex_m3_set_breakpoint(target
, breakpoint
);
605 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
606 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
608 stlink_debug_entry(target
);
610 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
615 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
616 uint32_t size
, uint32_t count
,
620 uint32_t buffer_threshold
= 128;
621 uint32_t addr_increment
= 4;
622 uint8_t *dst
= buffer
;
624 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
626 if (!count
|| !buffer
)
627 return ERROR_COMMAND_SYNTAX_ERROR
;
629 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
631 /* prepare byte count, buffer threshold
632 * and address increment for none 32bit access
636 buffer_threshold
= 64;
641 if (count
> buffer_threshold
)
642 c
= buffer_threshold
;
648 stlink_if
->layout
->api
->read_mem8(stlink_if
->fd
, address
,
652 stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
, address
,
658 address
+= (c
* addr_increment
);
659 dst
+= (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;
673 const uint8_t *dst
= buffer
;
675 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
677 if (!count
|| !buffer
)
678 return ERROR_COMMAND_SYNTAX_ERROR
;
680 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
682 /* prepare byte count, buffer threshold
683 * and address increment for none 32bit access
687 buffer_threshold
= 64;
692 if (count
> buffer_threshold
)
693 c
= buffer_threshold
;
699 stlink_if
->layout
->api
->write_mem8(stlink_if
->fd
, address
,
703 stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
, address
,
709 address
+= (c
* addr_increment
);
710 dst
+= (c
* addr_increment
);
717 static int stm32_stlink_bulk_write_memory(struct target
*target
,
718 uint32_t address
, uint32_t count
,
719 const uint8_t *buffer
)
721 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
724 struct target_type stm32_stlink_target
= {
725 .name
= "stm32_stlink",
727 .init_target
= stm32_stlink_init_target
,
728 .target_create
= stm32_stlink_target_create
,
729 .examine
= stm32_stlink_examine
,
731 .poll
= stm32_stlink_poll
,
732 .arch_state
= armv7m_arch_state
,
734 .assert_reset
= stm32_stlink_assert_reset
,
735 .deassert_reset
= stm32_stlink_deassert_reset
,
736 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
738 .halt
= stm32_stlink_halt
,
739 .resume
= stm32_stlink_resume
,
740 .step
= stm32_stlink_step
,
742 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
744 .read_memory
= stm32_stlink_read_memory
,
745 .write_memory
= stm32_stlink_write_memory
,
746 .bulk_write_memory
= stm32_stlink_bulk_write_memory
,
747 .checksum_memory
= armv7m_checksum_memory
,
748 .blank_check_memory
= armv7m_blank_check_memory
,
750 .run_algorithm
= armv7m_run_algorithm
,
751 .start_algorithm
= armv7m_start_algorithm
,
752 .wait_algorithm
= armv7m_wait_algorithm
,
754 .add_breakpoint
= cortex_m3_add_breakpoint
,
755 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
756 .add_watchpoint
= cortex_m3_add_watchpoint
,
757 .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)