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
;
516 buf_set_u32(pc
->value
, 0, 32, address
);
521 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
523 /* the front-end may request us not to handle breakpoints */
524 if (handle_breakpoints
) {
525 breakpoint
= breakpoint_find(target
, pc_value
);
527 cortex_m3_unset_breakpoint(target
, breakpoint
);
530 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
532 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
534 armv7m_restore_context(target
);
536 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
538 res
= stlink_if
->layout
->api
->step(stlink_if
->fd
);
543 /* registers are now invalid */
544 register_cache_invalidate(armv7m
->core_cache
);
547 cortex_m3_set_breakpoint(target
, breakpoint
);
549 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
550 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
552 stm32_stlink_load_context(target
);
554 LOG_INFO("halted: PC: 0x%x", buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
559 static int stm32_stlink_read_memory(struct target
*target
, uint32_t address
,
560 uint32_t size
, uint32_t count
,
564 uint32_t *dst
= (uint32_t *) buffer
;
566 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
568 if (!count
|| !buffer
)
569 return ERROR_COMMAND_SYNTAX_ERROR
;
571 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
572 return ERROR_COMMAND_SYNTAX_ERROR
;
582 stlink_if
->layout
->api
->read_mem32(stlink_if
->fd
, address
,
595 static int stm32_stlink_write_memory(struct target
*target
, uint32_t address
,
596 uint32_t size
, uint32_t count
,
597 const uint8_t *buffer
)
600 uint32_t *dst
= (uint32_t *) buffer
;
602 struct stlink_interface_s
*stlink_if
= target_to_stlink(target
);
604 if (!count
|| !buffer
)
605 return ERROR_COMMAND_SYNTAX_ERROR
;
607 LOG_DEBUG("%s %x %d %d", __func__
, address
, size
, count
);
608 return ERROR_COMMAND_SYNTAX_ERROR
;
618 stlink_if
->layout
->api
->write_mem32(stlink_if
->fd
, address
,
631 static int stm32_stlink_bulk_write_memory(struct target
*target
,
632 uint32_t address
, uint32_t count
,
633 const uint8_t *buffer
)
635 return stm32_stlink_write_memory(target
, address
, 4, count
, buffer
);
638 struct target_type stm32_stlink_target
= {
639 .name
= "stm32_stlink",
641 .init_target
= stm32_stlink_init_target
,
642 .target_create
= stm32_stlink_target_create
,
643 .examine
= stm32_stlink_examine
,
645 .poll
= stm32_stlink_poll
,
646 .arch_state
= stm32_stlink_arch_state
,
648 .assert_reset
= stm32_stlink_assert_reset
,
649 .deassert_reset
= stm32_stlink_deassert_reset
,
650 .soft_reset_halt
= stm32_stlink_soft_reset_halt
,
652 .halt
= stm32_stlink_halt
,
653 .resume
= stm32_stlink_resume
,
654 .step
= stm32_stlink_step
,
656 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
658 .read_memory
= stm32_stlink_read_memory
,
659 .write_memory
= stm32_stlink_write_memory
,
660 .bulk_write_memory
= stm32_stlink_bulk_write_memory
,
662 .run_algorithm
= armv7m_run_algorithm
,
663 .start_algorithm
= armv7m_start_algorithm
,
664 .wait_algorithm
= armv7m_wait_algorithm
,
666 .add_breakpoint
= cortex_m3_add_breakpoint
,
667 .remove_breakpoint
= cortex_m3_remove_breakpoint
,
668 .add_watchpoint
= cortex_m3_add_watchpoint
,
669 .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)