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 * revised: 4/25/13 by brent@mbari.org [DCC target request support] *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
22 ***************************************************************************/
28 #include "jtag/interface.h"
29 #include "jtag/jtag.h"
30 #include "jtag/hla/hla_transport.h"
31 #include "jtag/hla/hla_interface.h"
32 #include "jtag/hla/hla_layout.h"
34 #include "algorithm.h"
36 #include "breakpoints.h"
37 #include "target_type.h"
40 #include "arm_semihosting.h"
41 #include "target_request.h"
43 #define savedDCRDR dbgbase /* FIXME: using target->dbgbase to preserve DCRDR */
45 #define ARMV7M_SCS_DCRSR DCB_DCRSR
46 #define ARMV7M_SCS_DCRDR DCB_DCRDR
48 static inline struct hl_interface_s
*target_to_adapter(struct target
*target
)
50 return target
->tap
->priv
;
53 static int adapter_load_core_reg_u32(struct target
*target
,
54 uint32_t regsel
, uint32_t *value
)
56 struct hl_interface_s
*adapter
= target_to_adapter(target
);
57 return adapter
->layout
->api
->read_reg(adapter
->handle
, regsel
, value
);
60 static int adapter_store_core_reg_u32(struct target
*target
,
61 uint32_t regsel
, uint32_t value
)
63 struct hl_interface_s
*adapter
= target_to_adapter(target
);
64 return adapter
->layout
->api
->write_reg(adapter
->handle
, regsel
, value
);
67 static int adapter_examine_debug_reason(struct target
*target
)
69 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
70 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)) {
71 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
77 static int hl_dcc_read(struct hl_interface_s
*hl_if
, uint8_t *value
, uint8_t *ctrl
)
80 int retval
= hl_if
->layout
->api
->read_mem(hl_if
->handle
,
81 DCB_DCRDR
, 1, sizeof(dcrdr
), (uint8_t *)&dcrdr
);
82 if (retval
== ERROR_OK
) {
83 *ctrl
= (uint8_t)dcrdr
;
84 *value
= (uint8_t)(dcrdr
>> 8);
86 LOG_DEBUG("data 0x%x ctrl 0x%x", *value
, *ctrl
);
89 /* write ack back to software dcc register
90 * to signify we have read data */
91 /* atomically clear just the byte containing the busy bit */
92 static const uint8_t zero
;
93 retval
= hl_if
->layout
->api
->write_mem(hl_if
->handle
, DCB_DCRDR
, 1, 1, &zero
);
99 static int hl_target_request_data(struct target
*target
,
100 uint32_t size
, uint8_t *buffer
)
102 struct hl_interface_s
*hl_if
= target_to_adapter(target
);
107 for (i
= 0; i
< (size
* 4); i
++) {
108 int err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
118 static int hl_handle_target_request(void *priv
)
120 struct target
*target
= priv
;
123 if (!target_was_examined(target
))
125 struct hl_interface_s
*hl_if
= target_to_adapter(target
);
127 if (!target
->dbg_msg_enabled
)
130 if (target
->state
== TARGET_RUNNING
) {
134 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
138 /* check if we have data */
139 if (ctrl
& (1 << 0)) {
142 /* we assume target is quick enough */
144 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
148 request
|= (data
<< 8);
149 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
153 request
|= (data
<< 16);
154 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
158 request
|= (data
<< 24);
159 target_request(target
, request
);
166 static int adapter_init_arch_info(struct target
*target
,
167 struct cortex_m_common
*cortex_m
,
168 struct jtag_tap
*tap
)
170 struct armv7m_common
*armv7m
;
172 LOG_DEBUG("%s", __func__
);
174 armv7m
= &cortex_m
->armv7m
;
175 armv7m_init_arch_info(target
, armv7m
);
177 armv7m
->load_core_reg_u32
= adapter_load_core_reg_u32
;
178 armv7m
->store_core_reg_u32
= adapter_store_core_reg_u32
;
180 armv7m
->examine_debug_reason
= adapter_examine_debug_reason
;
181 armv7m
->stlink
= true;
183 target_register_timer_callback(hl_handle_target_request
, 1,
184 TARGET_TIMER_TYPE_PERIODIC
, target
);
189 static int adapter_init_target(struct command_context
*cmd_ctx
,
190 struct target
*target
)
192 LOG_DEBUG("%s", __func__
);
194 armv7m_build_reg_cache(target
);
195 arm_semihosting_init(target
);
199 static int adapter_target_create(struct target
*target
,
202 LOG_DEBUG("%s", __func__
);
203 struct adiv5_private_config
*pc
= target
->private_config
;
204 if (pc
!= NULL
&& pc
->ap_num
> 0) {
205 LOG_ERROR("hla_target: invalid parameter -ap-num (> 0)");
206 return ERROR_COMMAND_SYNTAX_ERROR
;
209 struct cortex_m_common
*cortex_m
= calloc(1, sizeof(struct cortex_m_common
));
210 if (cortex_m
== NULL
) {
211 LOG_ERROR("No memory creating target");
215 adapter_init_arch_info(target
, cortex_m
, target
->tap
);
220 static int adapter_load_context(struct target
*target
)
222 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
223 int num_regs
= armv7m
->arm
.core_cache
->num_regs
;
225 for (int i
= 0; i
< num_regs
; i
++) {
227 struct reg
*r
= &armv7m
->arm
.core_cache
->reg_list
[i
];
229 armv7m
->arm
.read_core_reg(target
, r
, i
, ARM_MODE_ANY
);
235 static int adapter_debug_entry(struct target
*target
)
237 struct hl_interface_s
*adapter
= target_to_adapter(target
);
238 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
239 struct arm
*arm
= &armv7m
->arm
;
244 /* preserve the DCRDR across halts */
245 retval
= target_read_u32(target
, DCB_DCRDR
, &target
->savedDCRDR
);
246 if (retval
!= ERROR_OK
)
249 retval
= armv7m
->examine_debug_reason(target
);
250 if (retval
!= ERROR_OK
)
253 adapter_load_context(target
);
255 /* make sure we clear the vector catch bit */
256 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
);
259 xPSR
= buf_get_u32(r
->value
, 0, 32);
261 /* Are we in an exception handler */
263 armv7m
->exception_number
= (xPSR
& 0x1FF);
265 arm
->core_mode
= ARM_MODE_HANDLER
;
266 arm
->map
= armv7m_msp_reg_map
;
268 unsigned control
= buf_get_u32(arm
->core_cache
269 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 3);
271 /* is this thread privileged? */
272 arm
->core_mode
= control
& 1
273 ? ARM_MODE_USER_THREAD
276 /* which stack is it using? */
278 arm
->map
= armv7m_psp_reg_map
;
280 arm
->map
= armv7m_msp_reg_map
;
282 armv7m
->exception_number
= 0;
285 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32
", target->state: %s",
286 arm_mode_name(arm
->core_mode
),
287 buf_get_u32(arm
->pc
->value
, 0, 32),
288 target_state_name(target
));
293 static int adapter_poll(struct target
*target
)
295 enum target_state state
;
296 struct hl_interface_s
*adapter
= target_to_adapter(target
);
297 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
298 enum target_state prev_target_state
= target
->state
;
300 state
= adapter
->layout
->api
->state(adapter
->handle
);
302 if (state
== TARGET_UNKNOWN
) {
303 LOG_ERROR("jtag status contains invalid mode value - communication failure");
304 return ERROR_TARGET_FAILURE
;
307 if (prev_target_state
== state
)
310 if (prev_target_state
== TARGET_DEBUG_RUNNING
&& state
== TARGET_RUNNING
)
313 target
->state
= state
;
315 if (state
== TARGET_HALTED
) {
317 int retval
= adapter_debug_entry(target
);
318 if (retval
!= ERROR_OK
)
321 if (prev_target_state
== TARGET_DEBUG_RUNNING
) {
322 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
324 if (arm_semihosting(target
, &retval
) != 0)
327 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
330 LOG_DEBUG("halted: PC: 0x%08" PRIx32
, buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
336 static int hl_assert_reset(struct target
*target
)
339 struct hl_interface_s
*adapter
= target_to_adapter(target
);
340 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
341 bool use_srst_fallback
= true;
343 LOG_DEBUG("%s", __func__
);
345 enum reset_types jtag_reset_config
= jtag_get_reset_config();
347 bool srst_asserted
= false;
349 if ((jtag_reset_config
& RESET_HAS_SRST
) &&
350 (jtag_reset_config
& RESET_SRST_NO_GATING
)) {
351 res
= adapter_assert_reset();
352 srst_asserted
= true;
355 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DHCSR
, DBGKEY
|C_DEBUGEN
);
357 /* only set vector catch if halt is requested */
358 if (target
->reset_halt
)
359 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
|VC_CORERESET
);
361 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
);
363 if (jtag_reset_config
& RESET_HAS_SRST
) {
364 if (!srst_asserted
) {
365 res
= adapter_assert_reset();
367 if (res
== ERROR_COMMAND_NOTFOUND
)
368 LOG_ERROR("Hardware srst not supported, falling back to software reset");
369 else if (res
== ERROR_OK
) {
370 /* hardware srst supported */
371 use_srst_fallback
= false;
375 if (use_srst_fallback
) {
376 /* stlink v1 api does not support hardware srst, so we use a software reset fallback */
377 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, NVIC_AIRCR
, AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
380 res
= adapter
->layout
->api
->reset(adapter
->handle
);
385 /* registers are now invalid */
386 register_cache_invalidate(armv7m
->arm
.core_cache
);
388 if (target
->reset_halt
) {
389 target
->state
= TARGET_RESET
;
390 target
->debug_reason
= DBG_REASON_DBGRQ
;
392 target
->state
= TARGET_HALTED
;
398 static int hl_deassert_reset(struct target
*target
)
400 enum reset_types jtag_reset_config
= jtag_get_reset_config();
402 LOG_DEBUG("%s", __func__
);
404 if (jtag_reset_config
& RESET_HAS_SRST
)
405 adapter_deassert_reset();
407 target
->savedDCRDR
= 0; /* clear both DCC busy bits on initial resume */
409 return target
->reset_halt
? ERROR_OK
: target_resume(target
, 1, 0, 0, 0);
412 static int adapter_halt(struct target
*target
)
415 struct hl_interface_s
*adapter
= target_to_adapter(target
);
417 LOG_DEBUG("%s", __func__
);
419 if (target
->state
== TARGET_HALTED
) {
420 LOG_DEBUG("target was already halted");
424 if (target
->state
== TARGET_UNKNOWN
)
425 LOG_WARNING("target was in unknown state when halt was requested");
427 res
= adapter
->layout
->api
->halt(adapter
->handle
);
432 target
->debug_reason
= DBG_REASON_DBGRQ
;
437 static int adapter_resume(struct target
*target
, int current
,
438 target_addr_t address
, int handle_breakpoints
,
442 struct hl_interface_s
*adapter
= target_to_adapter(target
);
443 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
445 struct breakpoint
*breakpoint
= NULL
;
448 LOG_DEBUG("%s %d " TARGET_ADDR_FMT
" %d %d", __func__
, current
,
449 address
, handle_breakpoints
, debug_execution
);
451 if (target
->state
!= TARGET_HALTED
) {
452 LOG_WARNING("target not halted");
453 return ERROR_TARGET_NOT_HALTED
;
456 if (!debug_execution
) {
457 target_free_all_working_areas(target
);
458 cortex_m_enable_breakpoints(target
);
459 cortex_m_enable_watchpoints(target
);
464 buf_set_u32(pc
->value
, 0, 32, address
);
469 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
470 && !debug_execution
) {
471 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
474 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
476 /* write any user vector flags */
477 res
= target_write_u32(target
, DCB_DEMCR
, TRCENA
| armv7m
->demcr
);
481 armv7m_restore_context(target
);
483 /* restore savedDCRDR */
484 res
= target_write_u32(target
, DCB_DCRDR
, target
->savedDCRDR
);
488 /* registers are now invalid */
489 register_cache_invalidate(armv7m
->arm
.core_cache
);
491 /* the front-end may request us not to handle breakpoints */
492 if (handle_breakpoints
) {
493 /* Single step past breakpoint at current address */
494 breakpoint
= breakpoint_find(target
, resume_pc
);
496 LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT
" (ID: %" PRIu32
")",
498 breakpoint
->unique_id
);
499 cortex_m_unset_breakpoint(target
, breakpoint
);
501 res
= adapter
->layout
->api
->step(adapter
->handle
);
506 cortex_m_set_breakpoint(target
, breakpoint
);
510 res
= adapter
->layout
->api
->run(adapter
->handle
);
515 target
->debug_reason
= DBG_REASON_NOTHALTED
;
517 if (!debug_execution
) {
518 target
->state
= TARGET_RUNNING
;
519 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
521 target
->state
= TARGET_DEBUG_RUNNING
;
522 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
528 static int adapter_step(struct target
*target
, int current
,
529 target_addr_t address
, int handle_breakpoints
)
532 struct hl_interface_s
*adapter
= target_to_adapter(target
);
533 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
534 struct breakpoint
*breakpoint
= NULL
;
535 struct reg
*pc
= armv7m
->arm
.pc
;
536 bool bkpt_inst_found
= false;
538 LOG_DEBUG("%s", __func__
);
540 if (target
->state
!= TARGET_HALTED
) {
541 LOG_WARNING("target not halted");
542 return ERROR_TARGET_NOT_HALTED
;
546 buf_set_u32(pc
->value
, 0, 32, address
);
551 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
553 /* the front-end may request us not to handle breakpoints */
554 if (handle_breakpoints
) {
555 breakpoint
= breakpoint_find(target
, pc_value
);
557 cortex_m_unset_breakpoint(target
, breakpoint
);
560 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
562 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
564 armv7m_restore_context(target
);
566 /* restore savedDCRDR */
567 res
= target_write_u32(target
, DCB_DCRDR
, target
->savedDCRDR
);
571 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
573 res
= adapter
->layout
->api
->step(adapter
->handle
);
578 /* registers are now invalid */
579 register_cache_invalidate(armv7m
->arm
.core_cache
);
582 cortex_m_set_breakpoint(target
, breakpoint
);
584 adapter_debug_entry(target
);
585 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
587 LOG_INFO("halted: PC: 0x%08" PRIx32
, buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
592 static int adapter_read_memory(struct target
*target
, target_addr_t address
,
593 uint32_t size
, uint32_t count
,
596 struct hl_interface_s
*adapter
= target_to_adapter(target
);
598 if (!count
|| !buffer
)
599 return ERROR_COMMAND_SYNTAX_ERROR
;
601 LOG_DEBUG("%s " TARGET_ADDR_FMT
" %" PRIu32
" %" PRIu32
,
602 __func__
, address
, size
, count
);
604 return adapter
->layout
->api
->read_mem(adapter
->handle
, address
, size
, count
, buffer
);
607 static int adapter_write_memory(struct target
*target
, target_addr_t address
,
608 uint32_t size
, uint32_t count
,
609 const uint8_t *buffer
)
611 struct hl_interface_s
*adapter
= target_to_adapter(target
);
613 if (!count
|| !buffer
)
614 return ERROR_COMMAND_SYNTAX_ERROR
;
616 LOG_DEBUG("%s " TARGET_ADDR_FMT
" %" PRIu32
" %" PRIu32
,
617 __func__
, address
, size
, count
);
619 return adapter
->layout
->api
->write_mem(adapter
->handle
, address
, size
, count
, buffer
);
622 static const struct command_registration adapter_command_handlers
[] = {
624 .chain
= arm_command_handlers
,
627 .chain
= armv7m_trace_command_handlers
,
629 COMMAND_REGISTRATION_DONE
632 struct target_type hla_target
= {
633 .name
= "hla_target",
634 .deprecated_name
= "stm32_stlink",
636 .init_target
= adapter_init_target
,
637 .deinit_target
= cortex_m_deinit_target
,
638 .target_create
= adapter_target_create
,
639 .target_jim_configure
= adiv5_jim_configure
,
640 .examine
= cortex_m_examine
,
641 .commands
= adapter_command_handlers
,
643 .poll
= adapter_poll
,
644 .arch_state
= armv7m_arch_state
,
646 .target_request_data
= hl_target_request_data
,
647 .assert_reset
= hl_assert_reset
,
648 .deassert_reset
= hl_deassert_reset
,
650 .halt
= adapter_halt
,
651 .resume
= adapter_resume
,
652 .step
= adapter_step
,
654 .get_gdb_arch
= arm_get_gdb_arch
,
655 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
657 .read_memory
= adapter_read_memory
,
658 .write_memory
= adapter_write_memory
,
659 .checksum_memory
= armv7m_checksum_memory
,
660 .blank_check_memory
= armv7m_blank_check_memory
,
662 .run_algorithm
= armv7m_run_algorithm
,
663 .start_algorithm
= armv7m_start_algorithm
,
664 .wait_algorithm
= armv7m_wait_algorithm
,
666 .add_breakpoint
= cortex_m_add_breakpoint
,
667 .remove_breakpoint
= cortex_m_remove_breakpoint
,
668 .add_watchpoint
= cortex_m_add_watchpoint
,
669 .remove_watchpoint
= cortex_m_remove_watchpoint
,
670 .profiling
= cortex_m_profiling
,
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)