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"
40 static inline struct stlink_interface_s
*target_to_stlink(struct target
*target
)
42 return target
->tap
->priv
;
45 static int stm32_stlink_load_core_reg_u32(struct target
*target
,
46 enum armv7m_regtype type
,
47 uint32_t num
, uint32_t *value
)
50 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
52 LOG_DEBUG("%s", __func__
);
54 /* NOTE: we "know" here that the register identifiers used
55 * in the v7m header match the Cortex-M3 Debug Core Register
56 * Selector values for R0..R15, xPSR, MSP, and PSP.
60 /* read a normal core register */
61 retval
= 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.
79 retval
= 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
)
470 LOG_WARNING("target was in unknown state when halt was requested");
472 res
= stlink_if
->layout
->api
->halt(stlink_if
->fd
);
477 target
->debug_reason
= DBG_REASON_DBGRQ
;
482 static int stm32_stlink_resume(struct target
*target
, int current
,
483 uint32_t address
, int handle_breakpoints
,
487 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
488 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
490 struct breakpoint
*breakpoint
= NULL
;
493 LOG_DEBUG("%s %d %x %d %d", __func__
, current
, address
,
494 handle_breakpoints
, debug_execution
);
496 if (target
->state
!= TARGET_HALTED
) {
497 LOG_WARNING("target not halted");
498 return ERROR_TARGET_NOT_HALTED
;
503 buf_set_u32(pc
->value
, 0, 32, address
);
508 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
509 && !debug_execution
) {
510 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
513 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
515 armv7m_restore_context(target
);
517 /* registers are now invalid */
518 register_cache_invalidate(armv7m
->core_cache
);
520 /* the front-end may request us not to handle breakpoints */
521 if (handle_breakpoints
) {
522 /* Single step past breakpoint at current address */
523 breakpoint
= breakpoint_find(target
, resume_pc
);
525 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
527 breakpoint
->unique_id
);
528 cortex_m3_unset_breakpoint(target
, breakpoint
);
530 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
535 cortex_m3_set_breakpoint(target
, breakpoint
);
539 res
= stlink_if
->layout
->api
->run(stlink_if
->fd
);
544 target
->state
= TARGET_RUNNING
;
546 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
551 static int stm32_stlink_step(struct target
*target
, int current
,
552 uint32_t address
, int handle_breakpoints
)
555 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
556 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
557 struct breakpoint
*breakpoint
= NULL
;
558 struct reg
*pc
= armv7m
->arm
.pc
;
559 bool bkpt_inst_found
= false;
561 LOG_DEBUG("%s", __func__
);
563 if (target
->state
!= TARGET_HALTED
) {
564 LOG_WARNING("target not halted");
565 return ERROR_TARGET_NOT_HALTED
;
569 buf_set_u32(pc
->value
, 0, 32, address
);
574 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
576 /* the front-end may request us not to handle breakpoints */
577 if (handle_breakpoints
) {
578 breakpoint
= breakpoint_find(target
, pc_value
);
580 cortex_m3_unset_breakpoint(target
, breakpoint
);
583 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
585 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
587 armv7m_restore_context(target
);
589 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
591 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
596 /* registers are now invalid */
597 register_cache_invalidate(armv7m
->core_cache
);
600 cortex_m3_set_breakpoint(target
, breakpoint
);
602 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
603 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
605 stlink_debug_entry(target
);
607 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
612 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
613 uint32_t size
, uint32_t count
,
617 uint32_t buffer_threshold
= 128;
618 uint32_t addr_increment
= 4;
619 uint8_t *dst
= buffer
;
621 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
623 if (!count
|| !buffer
)
624 return ERROR_COMMAND_SYNTAX_ERROR
;
626 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
628 /* prepare byte count, buffer threshold
629 * and address increment for none 32bit access
633 buffer_threshold
= 64;
638 if (count
> buffer_threshold
)
639 c
= buffer_threshold
;
644 res
= stlink_if
->layout
->api
->read_mem8(stlink_if
->fd
,
647 res
= stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
,
648 address
, c
, (uint32_t *)dst
);
653 address
+= (c
* addr_increment
);
654 dst
+= (c
* addr_increment
);
661 static int stm32_stlink_write_memory(struct target
*target
, uint32_t address
,
662 uint32_t size
, uint32_t count
,
663 const uint8_t *buffer
)
666 uint32_t buffer_threshold
= 128;
667 uint32_t addr_increment
= 4;
668 const uint8_t *dst
= buffer
;
670 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
672 if (!count
|| !buffer
)
673 return ERROR_COMMAND_SYNTAX_ERROR
;
675 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
677 /* prepare byte count, buffer threshold
678 * and address increment for none 32bit access
682 buffer_threshold
= 64;
687 if (count
> buffer_threshold
)
688 c
= buffer_threshold
;
693 res
= stlink_if
->layout
->api
->write_mem8(stlink_if
->fd
,
696 res
= stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
,
697 address
, c
, (uint32_t *)dst
);
702 address
+= (c
* addr_increment
);
703 dst
+= (c
* addr_increment
);
710 static int stm32_stlink_bulk_write_memory(struct target
*target
,
711 uint32_t address
, uint32_t count
,
712 const uint8_t *buffer
)
714 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
717 struct target_type stm32_stlink_target
= {
718 .name
= "stm32_stlink",
720 .init_target
= stm32_stlink_init_target
,
721 .target_create
= stm32_stlink_target_create
,
722 .examine
= stm32_stlink_examine
,
724 .poll
= stm32_stlink_poll
,
725 .arch_state
= armv7m_arch_state
,
727 .assert_reset
= stm32_stlink_assert_reset
,
728 .deassert_reset
= stm32_stlink_deassert_reset
,
729 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
731 .halt
= stm32_stlink_halt
,
732 .resume
= stm32_stlink_resume
,
733 .step
= stm32_stlink_step
,
735 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
737 .read_memory
= stm32_stlink_read_memory
,
738 .write_memory
= stm32_stlink_write_memory
,
739 .bulk_write_memory
= stm32_stlink_bulk_write_memory
,
740 .checksum_memory
= armv7m_checksum_memory
,
741 .blank_check_memory
= armv7m_blank_check_memory
,
743 .run_algorithm
= armv7m_run_algorithm
,
744 .start_algorithm
= armv7m_start_algorithm
,
745 .wait_algorithm
= armv7m_wait_algorithm
,
747 .add_breakpoint
= cortex_m3_add_breakpoint
,
748 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
749 .add_watchpoint
= cortex_m3_add_watchpoint
,
750 .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)