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_interface.h"
29 #include "jtag/stlink/stlink_layout.h"
31 #include "algorithm.h"
33 #include "breakpoints.h"
34 #include "target_type.h"
38 static inline struct stlink_interface_s
*target_to_stlink(struct target
*target
)
40 return target
->tap
->priv
;
43 static int stm32_stlink_load_core_reg_u32(struct target
*target
,
44 enum armv7m_regtype type
,
45 uint32_t num
, uint32_t *value
)
48 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
50 LOG_DEBUG("%s", __func__
);
52 /* NOTE: we "know" here that the register identifiers used
53 * in the v7m header match the Cortex-M3 Debug Core Register
54 * Selector values for R0..R15, xPSR, MSP, and PSP.
58 /* read a normal core register */
60 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, num
, value
);
62 if (retval
!= ERROR_OK
) {
63 LOG_ERROR("JTAG failure %i", retval
);
64 return ERROR_JTAG_DEVICE_ERROR
;
66 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"",
72 case ARMV7M_FAULTMASK
:
74 /* Cortex-M3 packages these four registers as bitfields
75 * in one Debug Core register. So say r0 and r2 docs;
76 * it was removed from r1 docs, but still works.
79 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, value
);
83 *value
= buf_get_u32((uint8_t *) value
, 0, 1);
87 *value
= buf_get_u32((uint8_t *) value
, 8, 8);
90 case ARMV7M_FAULTMASK
:
91 *value
= buf_get_u32((uint8_t *) value
, 16, 1);
95 *value
= buf_get_u32((uint8_t *) value
, 24, 2);
99 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"",
104 return ERROR_COMMAND_SYNTAX_ERROR
;
110 static int stm32_stlink_store_core_reg_u32(struct target
*target
,
111 enum armv7m_regtype type
,
112 uint32_t num
, uint32_t value
)
116 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
117 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
119 LOG_DEBUG("%s", __func__
);
121 #ifdef ARMV7_GDB_HACKS
122 /* If the LR register is being modified, make sure it will put us
123 * in "thumb" mode, or an INVSTATE exception will occur. This is a
124 * hack to deal with the fact that gdb will sometimes "forge"
125 * return addresses, and doesn't set the LSB correctly (i.e., when
126 * printing expressions containing function calls, it sets LR = 0.)
127 * Valid exception return codes have bit 0 set too.
129 if (num
== ARMV7M_R14
)
133 /* NOTE: we "know" here that the register identifiers used
134 * in the v7m header match the Cortex-M3 Debug Core Register
135 * Selector values for R0..R15, xPSR, MSP, and PSP.
139 retval
= stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, num
, value
);
141 if (retval
!= ERROR_OK
) {
144 LOG_ERROR("JTAG failure");
145 r
= armv7m
->core_cache
->reg_list
+ num
;
147 return ERROR_JTAG_DEVICE_ERROR
;
149 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
, value
);
154 case ARMV7M_FAULTMASK
:
156 /* Cortex-M3 packages these four registers as bitfields
157 * in one Debug Core register. So say r0 and r2 docs;
158 * it was removed from r1 docs, but still works.
161 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, ®
);
165 buf_set_u32((uint8_t *) ®
, 0, 1, value
);
169 buf_set_u32((uint8_t *) ®
, 8, 8, value
);
172 case ARMV7M_FAULTMASK
:
173 buf_set_u32((uint8_t *) ®
, 16, 1, value
);
177 buf_set_u32((uint8_t *) ®
, 24, 2, value
);
181 stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, 20, reg
);
183 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
, value
);
187 return ERROR_COMMAND_SYNTAX_ERROR
;
193 static int stm32_stlink_examine_debug_reason(struct target
*target
)
195 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
196 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)) {
197 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
203 static int stm32_stlink_init_arch_info(struct target
*target
,
204 struct cortex_m3_common
*cortex_m3
,
205 struct jtag_tap
*tap
)
207 struct armv7m_common
*armv7m
;
209 LOG_DEBUG("%s", __func__
);
211 armv7m
= &cortex_m3
->armv7m
;
212 armv7m_init_arch_info(target
, armv7m
);
214 armv7m
->load_core_reg_u32
= stm32_stlink_load_core_reg_u32
;
215 armv7m
->store_core_reg_u32
= stm32_stlink_store_core_reg_u32
;
217 armv7m
->examine_debug_reason
= stm32_stlink_examine_debug_reason
;
222 static int stm32_stlink_init_target(struct command_context
*cmd_ctx
,
223 struct target
*target
)
225 LOG_DEBUG("%s", __func__
);
227 armv7m_build_reg_cache(target
);
232 static int stm32_stlink_target_create(struct target
*target
,
235 LOG_DEBUG("%s", __func__
);
237 struct cortex_m3_common
*cortex_m3
= calloc(1, sizeof(struct cortex_m3_common
));
240 return ERROR_COMMAND_SYNTAX_ERROR
;
242 stm32_stlink_init_arch_info(target
, cortex_m3
, target
->tap
);
247 static int stm32_stlink_examine(struct target
*target
)
250 uint32_t cpuid
, fpcr
;
251 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
253 LOG_DEBUG("%s", __func__
);
255 if (target
->tap
->hasidcode
== false) {
256 LOG_ERROR("no IDCODE present on device");
258 return ERROR_COMMAND_SYNTAX_ERROR
;
261 if (!target_was_examined(target
)) {
262 target_set_examined(target
);
264 LOG_INFO("IDCODE %x", target
->tap
->idcode
);
266 /* Read from Device Identification Registers */
267 retval
= target_read_u32(target
, CPUID
, &cpuid
);
268 if (retval
!= ERROR_OK
)
271 if (((cpuid
>> 4) & 0xc3f) == 0xc23)
272 LOG_DEBUG("Cortex-M3 r%" PRId8
"p%" PRId8
" processor detected",
273 (uint8_t)((cpuid
>> 20) & 0xf), (uint8_t)((cpuid
>> 0) & 0xf));
274 LOG_DEBUG("cpuid: 0x%8.8" PRIx32
"", cpuid
);
277 target_read_u32(target
, FP_CTRL
, &fpcr
);
278 cortex_m3
->auto_bp_type
= 1;
279 cortex_m3
->fp_num_code
= ((fpcr
>> 8) & 0x70) |
280 ((fpcr
>> 4) & 0xF); /* bits [14:12] and [7:4] */
281 cortex_m3
->fp_num_lit
= (fpcr
>> 8) & 0xF;
282 cortex_m3
->fp_code_available
= cortex_m3
->fp_num_code
;
283 cortex_m3
->fp_comparator_list
= calloc(cortex_m3
->fp_num_code
+
284 cortex_m3
->fp_num_lit
, sizeof(struct cortex_m3_fp_comparator
));
285 cortex_m3
->fpb_enabled
= fpcr
& 1;
286 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++) {
287 cortex_m3
->fp_comparator_list
[i
].type
=
288 (i
< cortex_m3
->fp_num_code
) ? FPCR_CODE
: FPCR_LITERAL
;
289 cortex_m3
->fp_comparator_list
[i
].fpcr_address
= FP_COMP0
+ 4 * i
;
291 LOG_DEBUG("FPB fpcr 0x%" PRIx32
", numcode %i, numlit %i", fpcr
,
292 cortex_m3
->fp_num_code
, cortex_m3
->fp_num_lit
);
295 cortex_m3_dwt_setup(cortex_m3
, target
);
297 /* These hardware breakpoints only work for code in flash! */
298 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
300 cortex_m3
->fp_num_code
,
301 cortex_m3
->dwt_num_comp
);
307 static int stm32_stlink_load_context(struct target
*target
)
309 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
310 int num_regs
= armv7m
->core_cache
->num_regs
;
312 for (int i
= 0; i
< num_regs
; i
++) {
313 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
314 armv7m
->read_core_reg(target
, i
);
320 static int stlink_debug_entry(struct target
*target
)
322 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
323 struct arm
*arm
= &armv7m
->arm
;
328 retval
= armv7m
->examine_debug_reason(target
);
329 if (retval
!= ERROR_OK
)
332 stm32_stlink_load_context(target
);
334 r
= armv7m
->core_cache
->reg_list
+ ARMV7M_xPSR
;
335 xPSR
= buf_get_u32(r
->value
, 0, 32);
337 /* Are we in an exception handler */
339 armv7m
->core_mode
= ARMV7M_MODE_HANDLER
;
340 armv7m
->exception_number
= (xPSR
& 0x1FF);
342 arm
->core_mode
= ARM_MODE_HANDLER
;
343 arm
->map
= armv7m_msp_reg_map
;
345 unsigned control
= buf_get_u32(armv7m
->core_cache
346 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 2);
348 /* is this thread privileged? */
349 armv7m
->core_mode
= control
& 1;
350 arm
->core_mode
= armv7m
->core_mode
351 ? ARM_MODE_USER_THREAD
354 /* which stack is it using? */
356 arm
->map
= armv7m_psp_reg_map
;
358 arm
->map
= armv7m_msp_reg_map
;
360 armv7m
->exception_number
= 0;
363 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32
", target->state: %s",
364 armv7m_mode_strings
[armv7m
->core_mode
],
365 *(uint32_t *)(arm
->pc
->value
),
366 target_state_name(target
));
371 static int stm32_stlink_poll(struct target
*target
)
373 enum target_state state
;
374 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
375 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
377 state
= stlink_if
->layout
->api
->state(stlink_if
->fd
);
379 if (state
== TARGET_UNKNOWN
) {
380 LOG_ERROR("jtag status contains invalid mode value - communication failure");
381 return ERROR_TARGET_FAILURE
;
384 if (target
->state
== state
)
387 if (state
== TARGET_HALTED
) {
388 target
->state
= state
;
390 stlink_debug_entry(target
);
392 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
393 LOG_DEBUG("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
399 static int stm32_stlink_assert_reset(struct target
*target
)
402 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
403 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
405 LOG_DEBUG("%s", __func__
);
407 res
= stlink_if
->layout
->api
->reset(stlink_if
->fd
);
412 /* virtual assert reset, we need it for the internal
415 jtag_add_reset(1, 1);
417 /* registers are now invalid */
418 register_cache_invalidate(armv7m
->core_cache
);
420 if (target
->reset_halt
) {
421 target
->state
= TARGET_RESET
;
422 target
->debug_reason
= DBG_REASON_DBGRQ
;
424 target
->state
= TARGET_HALTED
;
430 static int stm32_stlink_deassert_reset(struct target
*target
)
434 LOG_DEBUG("%s", __func__
);
436 /* virtual deassert reset, we need it for the internal
439 jtag_add_reset(0, 0);
441 if (!target
->reset_halt
) {
442 res
= target_resume(target
, 1, 0, 0, 0);
451 static int stm32_stlink_soft_reset_halt(struct target
*target
)
453 LOG_DEBUG("%s", __func__
);
457 static int stm32_stlink_halt(struct target
*target
)
460 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
462 LOG_DEBUG("%s", __func__
);
464 if (target
->state
== TARGET_HALTED
) {
465 LOG_DEBUG("target was already halted");
469 if (target
->state
== TARGET_UNKNOWN
) {
471 ("target was in unknown state when halt was requested");
474 res
= stlink_if
->layout
->api
->halt(stlink_if
->fd
);
479 target
->debug_reason
= DBG_REASON_DBGRQ
;
484 static int stm32_stlink_resume(struct target
*target
, int current
,
485 uint32_t address
, int handle_breakpoints
,
489 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
490 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
492 struct breakpoint
*breakpoint
= NULL
;
495 LOG_DEBUG("%s %d %x %d %d", __func__
, current
, address
,
496 handle_breakpoints
, debug_execution
);
498 if (target
->state
!= TARGET_HALTED
) {
499 LOG_WARNING("target not halted");
500 return ERROR_TARGET_NOT_HALTED
;
505 buf_set_u32(pc
->value
, 0, 32, address
);
510 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
511 && !debug_execution
) {
512 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
515 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
517 armv7m_restore_context(target
);
519 /* registers are now invalid */
520 register_cache_invalidate(armv7m
->core_cache
);
522 /* the front-end may request us not to handle breakpoints */
523 if (handle_breakpoints
) {
524 /* Single step past breakpoint at current address */
525 breakpoint
= breakpoint_find(target
, resume_pc
);
527 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
529 breakpoint
->unique_id
);
530 cortex_m3_unset_breakpoint(target
, breakpoint
);
532 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
537 cortex_m3_set_breakpoint(target
, breakpoint
);
541 res
= stlink_if
->layout
->api
->run(stlink_if
->fd
);
546 target
->state
= TARGET_RUNNING
;
548 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
553 static int stm32_stlink_step(struct target
*target
, int current
,
554 uint32_t address
, int handle_breakpoints
)
557 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
558 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
559 struct breakpoint
*breakpoint
= NULL
;
560 struct reg
*pc
= armv7m
->arm
.pc
;
561 bool bkpt_inst_found
= false;
563 LOG_DEBUG("%s", __func__
);
565 if (target
->state
!= TARGET_HALTED
) {
566 LOG_WARNING("target not halted");
567 return ERROR_TARGET_NOT_HALTED
;
571 buf_set_u32(pc
->value
, 0, 32, address
);
576 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
578 /* the front-end may request us not to handle breakpoints */
579 if (handle_breakpoints
) {
580 breakpoint
= breakpoint_find(target
, pc_value
);
582 cortex_m3_unset_breakpoint(target
, breakpoint
);
585 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
587 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
589 armv7m_restore_context(target
);
591 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
593 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
598 /* registers are now invalid */
599 register_cache_invalidate(armv7m
->core_cache
);
602 cortex_m3_set_breakpoint(target
, breakpoint
);
604 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
605 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
607 stlink_debug_entry(target
);
609 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
614 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
615 uint32_t size
, uint32_t count
,
619 uint32_t buffer_threshold
= 128;
620 uint32_t addr_increment
= 4;
621 uint8_t *dst
= buffer
;
623 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
625 if (!count
|| !buffer
)
626 return ERROR_COMMAND_SYNTAX_ERROR
;
628 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
630 /* prepare byte count, buffer threshold
631 * and address increment for none 32bit access
635 buffer_threshold
= 64;
640 if (count
> buffer_threshold
)
641 c
= buffer_threshold
;
647 stlink_if
->layout
->api
->read_mem8(stlink_if
->fd
, address
,
651 stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
, address
,
657 address
+= (c
* addr_increment
);
658 dst
+= (c
* addr_increment
);
665 static int stm32_stlink_write_memory(struct target
*target
, uint32_t address
,
666 uint32_t size
, uint32_t count
,
667 const uint8_t *buffer
)
670 uint32_t buffer_threshold
= 128;
671 uint32_t addr_increment
= 4;
672 const uint8_t *dst
= buffer
;
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 %x %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
;
698 stlink_if
->layout
->api
->write_mem8(stlink_if
->fd
, address
,
702 stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
, address
,
708 address
+= (c
* addr_increment
);
709 dst
+= (c
* addr_increment
);
716 static int stm32_stlink_bulk_write_memory(struct target
*target
,
717 uint32_t address
, uint32_t count
,
718 const uint8_t *buffer
)
720 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
723 struct target_type stm32_stlink_target
= {
724 .name
= "stm32_stlink",
726 .init_target
= stm32_stlink_init_target
,
727 .target_create
= stm32_stlink_target_create
,
728 .examine
= stm32_stlink_examine
,
730 .poll
= stm32_stlink_poll
,
731 .arch_state
= armv7m_arch_state
,
733 .assert_reset
= stm32_stlink_assert_reset
,
734 .deassert_reset
= stm32_stlink_deassert_reset
,
735 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
737 .halt
= stm32_stlink_halt
,
738 .resume
= stm32_stlink_resume
,
739 .step
= stm32_stlink_step
,
741 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
743 .read_memory
= stm32_stlink_read_memory
,
744 .write_memory
= stm32_stlink_write_memory
,
745 .bulk_write_memory
= stm32_stlink_bulk_write_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)