1 /***************************************************************************
2 * Copyright (C) 2011 by Mathias Kuester *
3 * Mathias Kuester <kesmtp@freenet.de> *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
24 #include "jtag/jtag.h"
25 #include "jtag/stlink/stlink_interface.h"
26 #include "jtag/stlink/stlink_layout.h"
28 #include "algorithm.h"
30 #include "breakpoints.h"
31 #include "target_type.h"
35 static inline struct stlink_interface_s
*target_to_stlink(struct target
*target
)
37 return target
->tap
->priv
;
40 static int stm32_stlink_load_core_reg_u32(struct target
*target
,
41 enum armv7m_regtype type
,
42 uint32_t num
, uint32_t *value
)
45 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
47 LOG_DEBUG("%s", __func__
);
49 /* NOTE: we "know" here that the register identifiers used
50 * in the v7m header match the Cortex-M3 Debug Core Register
51 * Selector values for R0..R15, xPSR, MSP, and PSP.
55 /* read a normal core register */
57 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, num
, value
);
59 if (retval
!= ERROR_OK
) {
60 LOG_ERROR("JTAG failure %i", retval
);
61 return ERROR_JTAG_DEVICE_ERROR
;
63 LOG_DEBUG("load from core reg %i value 0x%" PRIx32
"",
69 case ARMV7M_FAULTMASK
:
71 /* Cortex-M3 packages these four registers as bitfields
72 * in one Debug Core register. So say r0 and r2 docs;
73 * it was removed from r1 docs, but still works.
76 stlink_if
->layout
->api
->read_reg(stlink_if
->fd
, 20, value
);
80 *value
= buf_get_u32((uint8_t *) value
, 0, 1);
84 *value
= buf_get_u32((uint8_t *) value
, 8, 8);
87 case ARMV7M_FAULTMASK
:
88 *value
= buf_get_u32((uint8_t *) value
, 16, 1);
92 *value
= buf_get_u32((uint8_t *) value
, 24, 2);
96 LOG_DEBUG("load from special reg %i value 0x%" PRIx32
"",
101 return ERROR_COMMAND_SYNTAX_ERROR
;
107 static int stm32_stlink_store_core_reg_u32(struct target
*target
,
108 enum armv7m_regtype type
,
109 uint32_t num
, uint32_t value
)
113 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
114 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
116 LOG_DEBUG("%s", __func__
);
118 #ifdef ARMV7_GDB_HACKS
119 /* If the LR register is being modified, make sure it will put us
120 * in "thumb" mode, or an INVSTATE exception will occur. This is a
121 * hack to deal with the fact that gdb will sometimes "forge"
122 * return addresses, and doesn't set the LSB correctly (i.e., when
123 * printing expressions containing function calls, it sets LR = 0.)
124 * Valid exception return codes have bit 0 set too.
126 if (num
== ARMV7M_R14
)
130 /* NOTE: we "know" here that the register identifiers used
131 * in the v7m header match the Cortex-M3 Debug Core Register
132 * Selector values for R0..R15, xPSR, MSP, and PSP.
137 stlink_if
->layout
->api
->write_reg(stlink_if
->fd
, num
,
140 if (retval
!= ERROR_OK
) {
143 LOG_ERROR("JTAG failure");
144 r
= armv7m
->core_cache
->reg_list
+ num
;
146 return ERROR_JTAG_DEVICE_ERROR
;
148 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", (int)num
,
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.
160 /* cortexm3_dap_read_coreregister_u32(swjdp, ®, 20); */
164 buf_set_u32((uint8_t *) ®
, 0, 1, value
);
168 buf_set_u32((uint8_t *) ®
, 8, 8, value
);
171 case ARMV7M_FAULTMASK
:
172 buf_set_u32((uint8_t *) ®
, 16, 1, value
);
176 buf_set_u32((uint8_t *) ®
, 24, 2, value
);
180 /* cortexm3_dap_write_coreregister_u32(swjdp, reg, 20); */
182 LOG_DEBUG("write special reg %i value 0x%" PRIx32
" ", (int)num
,
187 return ERROR_COMMAND_SYNTAX_ERROR
;
193 static int stm32_stlink_init_arch_info(struct target
*target
,
194 struct cortex_m3_common
*cortex_m3
,
195 struct jtag_tap
*tap
)
197 struct armv7m_common
*armv7m
;
199 LOG_DEBUG("%s", __func__
);
201 armv7m
= &cortex_m3
->armv7m
;
202 armv7m_init_arch_info(target
, armv7m
);
204 armv7m
->load_core_reg_u32
= stm32_stlink_load_core_reg_u32
;
205 armv7m
->store_core_reg_u32
= stm32_stlink_store_core_reg_u32
;
210 static int stm32_stlink_init_target(struct command_context
*cmd_ctx
,
211 struct target
*target
)
213 LOG_DEBUG("%s", __func__
);
215 armv7m_build_reg_cache(target
);
220 static int stm32_stlink_target_create(struct target
*target
,
223 LOG_DEBUG("%s", __func__
);
225 struct cortex_m3_common
*cortex_m3
= calloc(1, sizeof(struct cortex_m3_common
));
228 return ERROR_COMMAND_SYNTAX_ERROR
;
230 stm32_stlink_init_arch_info(target
, cortex_m3
, target
->tap
);
235 static int stm32_stlink_poll(struct target
*target
);
237 static int stm32_stlink_examine(struct target
*target
)
240 uint32_t cpuid
, fpcr
;
241 struct cortex_m3_common
*cortex_m3
= target_to_cm3(target
);
243 LOG_DEBUG("%s", __func__
);
245 if (target
->tap
->hasidcode
== false) {
246 LOG_ERROR("no IDCODE present on device");
248 return ERROR_COMMAND_SYNTAX_ERROR
;
251 if (!target_was_examined(target
)) {
252 target_set_examined(target
);
254 stm32_stlink_poll(target
);
256 LOG_INFO("IDCODE %x", target
->tap
->idcode
);
258 /* Read from Device Identification Registers */
259 retval
= target_read_u32(target
, CPUID
, &cpuid
);
260 if (retval
!= ERROR_OK
)
263 if (((cpuid
>> 4) & 0xc3f) == 0xc23)
264 LOG_DEBUG("Cortex-M3 r%" PRId8
"p%" PRId8
" processor detected",
265 (uint8_t)((cpuid
>> 20) & 0xf), (uint8_t)((cpuid
>> 0) & 0xf));
266 LOG_DEBUG("cpuid: 0x%8.8" PRIx32
"", cpuid
);
269 target_read_u32(target
, FP_CTRL
, &fpcr
);
270 cortex_m3
->auto_bp_type
= 1;
271 cortex_m3
->fp_num_code
= ((fpcr
>> 8) & 0x70) |
272 ((fpcr
>> 4) & 0xF); /* bits [14:12] and [7:4] */
273 cortex_m3
->fp_num_lit
= (fpcr
>> 8) & 0xF;
274 cortex_m3
->fp_code_available
= cortex_m3
->fp_num_code
;
275 cortex_m3
->fp_comparator_list
= calloc(cortex_m3
->fp_num_code
+
276 cortex_m3
->fp_num_lit
, sizeof(struct cortex_m3_fp_comparator
));
277 cortex_m3
->fpb_enabled
= fpcr
& 1;
278 for (i
= 0; i
< cortex_m3
->fp_num_code
+ cortex_m3
->fp_num_lit
; i
++) {
279 cortex_m3
->fp_comparator_list
[i
].type
=
280 (i
< cortex_m3
->fp_num_code
) ? FPCR_CODE
: FPCR_LITERAL
;
281 cortex_m3
->fp_comparator_list
[i
].fpcr_address
= FP_COMP0
+ 4 * i
;
283 LOG_DEBUG("FPB fpcr 0x%" PRIx32
", numcode %i, numlit %i", fpcr
,
284 cortex_m3
->fp_num_code
, cortex_m3
->fp_num_lit
);
287 cortex_m3_dwt_setup(cortex_m3
, target
);
289 /* These hardware breakpoints only work for code in flash! */
290 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
292 cortex_m3
->fp_num_code
,
293 cortex_m3
->dwt_num_comp
);
299 static int stm32_stlink_load_context(struct target
*target
)
301 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
303 for (unsigned i
= 0; i
< 23; i
++) {
304 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
305 armv7m
->read_core_reg(target
, i
);
311 static int stm32_stlink_poll(struct target
*target
)
313 enum target_state state
;
314 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
315 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
317 state
= stlink_if
->layout
->api
->state(stlink_if
->fd
);
319 if (state
== TARGET_UNKNOWN
) {
321 ("jtag status contains invalid mode value - communication failure");
322 return ERROR_TARGET_FAILURE
;
325 if (target
->state
== state
)
328 if (state
== TARGET_HALTED
) {
329 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
330 target
->state
= state
;
332 stm32_stlink_load_context(target
);
334 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
340 static int stm32_stlink_arch_state(struct target
*target
)
342 LOG_DEBUG("%s", __func__
);
346 static int stm32_stlink_assert_reset(struct target
*target
)
349 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
350 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
352 LOG_DEBUG("%s", __func__
);
354 res
= stlink_if
->layout
->api
->reset(stlink_if
->fd
);
359 /* virtual assert reset, we need it for the internal
362 jtag_add_reset(1, 1);
364 /* registers are now invalid */
365 register_cache_invalidate(armv7m
->core_cache
);
367 stm32_stlink_load_context(target
);
369 target
->state
= TARGET_HALTED
;
374 static int stm32_stlink_deassert_reset(struct target
*target
)
378 LOG_DEBUG("%s", __func__
);
380 /* virtual deassert reset, we need it for the internal
383 jtag_add_reset(0, 0);
385 if (!target
->reset_halt
) {
386 res
= target_resume(target
, 1, 0, 0, 0);
395 static int stm32_stlink_soft_reset_halt(struct target
*target
)
397 LOG_DEBUG("%s", __func__
);
401 static int stm32_stlink_halt(struct target
*target
)
404 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
406 LOG_DEBUG("%s", __func__
);
408 if (target
->state
== TARGET_HALTED
) {
409 LOG_DEBUG("target was already halted");
413 if (target
->state
== TARGET_UNKNOWN
) {
415 ("target was in unknown state when halt was requested");
418 res
= stlink_if
->layout
->api
->halt(stlink_if
->fd
);
423 target
->debug_reason
= DBG_REASON_DBGRQ
;
428 static int stm32_stlink_resume(struct target
*target
, int current
,
429 uint32_t address
, int handle_breakpoints
,
433 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
434 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
436 struct breakpoint
*breakpoint
= NULL
;
439 LOG_DEBUG("%s %d %x %d %d", __func__
, current
, address
,
440 handle_breakpoints
, debug_execution
);
442 if (target
->state
!= TARGET_HALTED
) {
443 LOG_WARNING("target not halted");
444 return ERROR_TARGET_NOT_HALTED
;
449 buf_set_u32(pc
->value
, 0, 32, address
);
454 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
455 && !debug_execution
) {
456 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
459 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
461 armv7m_restore_context(target
);
463 /* registers are now invalid */
464 register_cache_invalidate(armv7m
->core_cache
);
466 /* the front-end may request us not to handle breakpoints */
467 if (handle_breakpoints
) {
468 /* Single step past breakpoint at current address */
469 breakpoint
= breakpoint_find(target
, resume_pc
);
471 LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32
" (ID: %d)",
473 breakpoint
->unique_id
);
474 cortex_m3_unset_breakpoint(target
, breakpoint
);
476 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
481 cortex_m3_set_breakpoint(target
, breakpoint
);
485 res
= stlink_if
->layout
->api
->run(stlink_if
->fd
);
490 target
->state
= TARGET_RUNNING
;
492 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
497 static int stm32_stlink_step(struct target
*target
, int current
,
498 uint32_t address
, int handle_breakpoints
)
501 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
502 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
503 struct breakpoint
*breakpoint
= NULL
;
504 struct reg
*pc
= armv7m
->arm
.pc
;
505 bool bkpt_inst_found
= false;
507 LOG_DEBUG("%s", __func__
);
509 if (target
->state
!= TARGET_HALTED
) {
510 LOG_WARNING("target not halted");
511 return ERROR_TARGET_NOT_HALTED
;
515 buf_set_u32(pc
->value
, 0, 32, address
);
520 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
522 /* the front-end may request us not to handle breakpoints */
523 if (handle_breakpoints
) {
524 breakpoint
= breakpoint_find(target
, pc_value
);
526 cortex_m3_unset_breakpoint(target
, breakpoint
);
529 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
531 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
533 armv7m_restore_context(target
);
535 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
537 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
542 /* registers are now invalid */
543 register_cache_invalidate(armv7m
->core_cache
);
546 cortex_m3_set_breakpoint(target
, breakpoint
);
548 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
549 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
551 stm32_stlink_load_context(target
);
553 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
558 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
559 uint32_t size
, uint32_t count
,
563 uint32_t buffer_threshold
= 128;
564 uint32_t addr_increment
= 4;
565 uint8_t *dst
= buffer
;
567 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
569 if (!count
|| !buffer
)
570 return ERROR_COMMAND_SYNTAX_ERROR
;
572 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
574 /* prepare byte count, buffer threshold
575 * and address increment for none 32bit access
579 buffer_threshold
= 64;
584 if (count
> buffer_threshold
)
585 c
= buffer_threshold
;
591 stlink_if
->layout
->api
->read_mem8(stlink_if
->fd
, address
,
595 stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
, address
,
601 address
+= (c
* addr_increment
);
602 dst
+= (c
* addr_increment
);
609 static int stm32_stlink_write_memory(struct target
*target
, uint32_t address
,
610 uint32_t size
, uint32_t count
,
611 const uint8_t *buffer
)
614 uint32_t buffer_threshold
= 128;
615 uint32_t addr_increment
= 4;
616 const uint8_t *dst
= buffer
;
618 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
620 if (!count
|| !buffer
)
621 return ERROR_COMMAND_SYNTAX_ERROR
;
623 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
625 /* prepare byte count, buffer threshold
626 * and address increment for none 32bit access
630 buffer_threshold
= 64;
635 if (count
> buffer_threshold
)
636 c
= buffer_threshold
;
642 stlink_if
->layout
->api
->write_mem8(stlink_if
->fd
, address
,
646 stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
, address
,
652 address
+= (c
* addr_increment
);
653 dst
+= (c
* addr_increment
);
660 static int stm32_stlink_bulk_write_memory(struct target
*target
,
661 uint32_t address
, uint32_t count
,
662 const uint8_t *buffer
)
664 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
667 struct target_type stm32_stlink_target
= {
668 .name
= "stm32_stlink",
670 .init_target
= stm32_stlink_init_target
,
671 .target_create
= stm32_stlink_target_create
,
672 .examine
= stm32_stlink_examine
,
674 .poll
= stm32_stlink_poll
,
675 .arch_state
= stm32_stlink_arch_state
,
677 .assert_reset
= stm32_stlink_assert_reset
,
678 .deassert_reset
= stm32_stlink_deassert_reset
,
679 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
681 .halt
= stm32_stlink_halt
,
682 .resume
= stm32_stlink_resume
,
683 .step
= stm32_stlink_step
,
685 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
687 .read_memory
= stm32_stlink_read_memory
,
688 .write_memory
= stm32_stlink_write_memory
,
689 .bulk_write_memory
= stm32_stlink_bulk_write_memory
,
691 .run_algorithm
= armv7m_run_algorithm
,
692 .start_algorithm
= armv7m_start_algorithm
,
693 .wait_algorithm
= armv7m_wait_algorithm
,
695 .add_breakpoint
= cortex_m3_add_breakpoint
,
696 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
697 .add_watchpoint
= cortex_m3_add_watchpoint
,
698 .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)