1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2011 by Mathias Kuester *
5 * Mathias Kuester <kesmtp@freenet.de> *
7 * Copyright (C) 2011 by Spencer Oliver *
8 * spen@spen-soft.co.uk *
10 * revised: 4/25/13 by brent@mbari.org [DCC target request support] *
11 ***************************************************************************/
17 #include "jtag/interface.h"
18 #include "jtag/jtag.h"
19 #include "jtag/hla/hla_transport.h"
20 #include "jtag/hla/hla_interface.h"
21 #include "jtag/hla/hla_layout.h"
23 #include "algorithm.h"
25 #include "breakpoints.h"
26 #include "target_type.h"
29 #include "arm_adi_v5.h"
30 #include "arm_semihosting.h"
31 #include "target_request.h"
34 #define SAVED_DCRDR dbgbase /* FIXME: using target->dbgbase to preserve DCRDR */
36 #define ARMV7M_SCS_DCRSR DCB_DCRSR
37 #define ARMV7M_SCS_DCRDR DCB_DCRDR
39 static inline struct hl_interface_s
*target_to_adapter(struct target
*target
)
41 return target
->tap
->priv
;
44 static int adapter_load_core_reg_u32(struct target
*target
,
45 uint32_t regsel
, uint32_t *value
)
47 struct hl_interface_s
*adapter
= target_to_adapter(target
);
48 return adapter
->layout
->api
->read_reg(adapter
->handle
, regsel
, value
);
51 static int adapter_store_core_reg_u32(struct target
*target
,
52 uint32_t regsel
, uint32_t value
)
54 struct hl_interface_s
*adapter
= target_to_adapter(target
);
55 return adapter
->layout
->api
->write_reg(adapter
->handle
, regsel
, value
);
58 static int adapter_examine_debug_reason(struct target
*target
)
60 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
61 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)) {
62 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
68 static int hl_dcc_read(struct hl_interface_s
*hl_if
, uint8_t *value
, uint8_t *ctrl
)
71 int retval
= hl_if
->layout
->api
->read_mem(hl_if
->handle
,
72 DCB_DCRDR
, 1, sizeof(dcrdr
), (uint8_t *)&dcrdr
);
73 if (retval
== ERROR_OK
) {
74 *ctrl
= (uint8_t)dcrdr
;
75 *value
= (uint8_t)(dcrdr
>> 8);
77 LOG_DEBUG("data 0x%x ctrl 0x%x", *value
, *ctrl
);
80 /* write ack back to software dcc register
81 * to signify we have read data */
82 /* atomically clear just the byte containing the busy bit */
83 static const uint8_t zero
;
84 retval
= hl_if
->layout
->api
->write_mem(hl_if
->handle
, DCB_DCRDR
, 1, 1, &zero
);
90 static int hl_target_request_data(struct target
*target
,
91 uint32_t size
, uint8_t *buffer
)
93 struct hl_interface_s
*hl_if
= target_to_adapter(target
);
98 for (i
= 0; i
< (size
* 4); i
++) {
99 int err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
109 static int hl_handle_target_request(void *priv
)
111 struct target
*target
= priv
;
114 if (!target_was_examined(target
))
116 struct hl_interface_s
*hl_if
= target_to_adapter(target
);
118 if (!target
->dbg_msg_enabled
)
121 if (target
->state
== TARGET_RUNNING
) {
125 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
129 /* check if we have data */
130 if (ctrl
& (1 << 0)) {
133 /* we assume target is quick enough */
135 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
139 request
|= (data
<< 8);
140 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
144 request
|= (data
<< 16);
145 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
149 request
|= (data
<< 24);
150 target_request(target
, request
);
157 static int adapter_init_arch_info(struct target
*target
,
158 struct cortex_m_common
*cortex_m
,
159 struct jtag_tap
*tap
)
161 struct armv7m_common
*armv7m
;
163 LOG_DEBUG("%s", __func__
);
165 armv7m
= &cortex_m
->armv7m
;
166 armv7m_init_arch_info(target
, armv7m
);
168 armv7m
->load_core_reg_u32
= adapter_load_core_reg_u32
;
169 armv7m
->store_core_reg_u32
= adapter_store_core_reg_u32
;
171 armv7m
->examine_debug_reason
= adapter_examine_debug_reason
;
172 armv7m
->is_hla_target
= true;
174 target_register_timer_callback(hl_handle_target_request
, 1,
175 TARGET_TIMER_TYPE_PERIODIC
, target
);
180 static int adapter_init_target(struct command_context
*cmd_ctx
,
181 struct target
*target
)
183 LOG_DEBUG("%s", __func__
);
185 armv7m_build_reg_cache(target
);
186 arm_semihosting_init(target
);
190 static int adapter_target_create(struct target
*target
,
193 LOG_DEBUG("%s", __func__
);
194 struct adiv5_private_config
*pc
= target
->private_config
;
195 if (pc
&& pc
->ap_num
!= DP_APSEL_INVALID
&& pc
->ap_num
!= 0) {
196 LOG_ERROR("hla_target: invalid parameter -ap-num (> 0)");
197 return ERROR_COMMAND_SYNTAX_ERROR
;
200 struct cortex_m_common
*cortex_m
= calloc(1, sizeof(struct cortex_m_common
));
202 LOG_ERROR("No memory creating target");
206 cortex_m
->common_magic
= CORTEX_M_COMMON_MAGIC
;
208 adapter_init_arch_info(target
, cortex_m
, target
->tap
);
213 static int adapter_load_context(struct target
*target
)
215 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
216 int num_regs
= armv7m
->arm
.core_cache
->num_regs
;
218 for (int i
= 0; i
< num_regs
; i
++) {
220 struct reg
*r
= &armv7m
->arm
.core_cache
->reg_list
[i
];
221 if (r
->exist
&& !r
->valid
)
222 armv7m
->arm
.read_core_reg(target
, r
, i
, ARM_MODE_ANY
);
228 static int adapter_debug_entry(struct target
*target
)
230 struct hl_interface_s
*adapter
= target_to_adapter(target
);
231 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
232 struct arm
*arm
= &armv7m
->arm
;
237 /* preserve the DCRDR across halts */
238 retval
= target_read_u32(target
, DCB_DCRDR
, &target
->SAVED_DCRDR
);
239 if (retval
!= ERROR_OK
)
242 retval
= armv7m
->examine_debug_reason(target
);
243 if (retval
!= ERROR_OK
)
246 adapter_load_context(target
);
248 /* make sure we clear the vector catch bit */
249 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
);
252 xpsr
= buf_get_u32(r
->value
, 0, 32);
254 /* Are we in an exception handler */
256 armv7m
->exception_number
= (xpsr
& 0x1FF);
258 arm
->core_mode
= ARM_MODE_HANDLER
;
259 arm
->map
= armv7m_msp_reg_map
;
261 unsigned control
= buf_get_u32(arm
->core_cache
262 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 3);
264 /* is this thread privileged? */
265 arm
->core_mode
= control
& 1
266 ? ARM_MODE_USER_THREAD
269 /* which stack is it using? */
271 arm
->map
= armv7m_psp_reg_map
;
273 arm
->map
= armv7m_msp_reg_map
;
275 armv7m
->exception_number
= 0;
278 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32
", target->state: %s",
279 arm_mode_name(arm
->core_mode
),
280 buf_get_u32(arm
->pc
->value
, 0, 32),
281 target_state_name(target
));
286 static int adapter_poll(struct target
*target
)
288 enum target_state state
;
289 struct hl_interface_s
*adapter
= target_to_adapter(target
);
290 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
291 enum target_state prev_target_state
= target
->state
;
293 state
= adapter
->layout
->api
->state(adapter
->handle
);
295 if (state
== TARGET_UNKNOWN
) {
296 LOG_ERROR("jtag status contains invalid mode value - communication failure");
297 return ERROR_TARGET_FAILURE
;
300 if (prev_target_state
== state
)
303 if (prev_target_state
== TARGET_DEBUG_RUNNING
&& state
== TARGET_RUNNING
)
306 target
->state
= state
;
308 if (state
== TARGET_HALTED
) {
310 int retval
= adapter_debug_entry(target
);
311 if (retval
!= ERROR_OK
)
314 if (prev_target_state
== TARGET_DEBUG_RUNNING
) {
315 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
317 if (arm_semihosting(target
, &retval
) != 0)
320 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
323 LOG_DEBUG("halted: PC: 0x%08" PRIx32
, buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
329 static int hl_assert_reset(struct target
*target
)
332 struct hl_interface_s
*adapter
= target_to_adapter(target
);
333 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
334 bool use_srst_fallback
= true;
336 LOG_DEBUG("%s", __func__
);
338 enum reset_types jtag_reset_config
= jtag_get_reset_config();
340 bool srst_asserted
= false;
342 if ((jtag_reset_config
& RESET_HAS_SRST
) &&
343 (jtag_reset_config
& RESET_SRST_NO_GATING
)) {
344 res
= adapter_assert_reset();
345 srst_asserted
= true;
348 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DHCSR
, DBGKEY
|C_DEBUGEN
);
350 if (!target_was_examined(target
) && !target
->defer_examine
351 && srst_asserted
&& res
== ERROR_OK
) {
352 /* If the target is not examined, now under reset it is good time to retry examination */
353 LOG_TARGET_DEBUG(target
, "Trying to re-examine under reset");
354 target_examine_one(target
);
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
->SAVED_DCRDR
= 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 SAVED_DCRDR */
484 res
= target_write_u32(target
, DCB_DCRDR
, target
->SAVED_DCRDR
);
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 SAVED_DCRDR */
567 res
= target_write_u32(target
, DCB_DCRDR
, target
->SAVED_DCRDR
);
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 hla_command_handlers
[] = {
624 .chain
= arm_command_handlers
,
627 .chain
= armv7m_trace_command_handlers
,
630 .chain
= rtt_target_command_handlers
,
632 /* START_DEPRECATED_TPIU */
634 .chain
= arm_tpiu_deprecated_command_handlers
,
636 /* END_DEPRECATED_TPIU */
637 COMMAND_REGISTRATION_DONE
640 struct target_type hla_target
= {
641 .name
= "hla_target",
643 .init_target
= adapter_init_target
,
644 .deinit_target
= cortex_m_deinit_target
,
645 .target_create
= adapter_target_create
,
646 .target_jim_configure
= adiv5_jim_configure
,
647 .examine
= cortex_m_examine
,
648 .commands
= hla_command_handlers
,
650 .poll
= adapter_poll
,
651 .arch_state
= armv7m_arch_state
,
653 .target_request_data
= hl_target_request_data
,
654 .assert_reset
= hl_assert_reset
,
655 .deassert_reset
= hl_deassert_reset
,
657 .halt
= adapter_halt
,
658 .resume
= adapter_resume
,
659 .step
= adapter_step
,
661 .get_gdb_arch
= arm_get_gdb_arch
,
662 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
664 .read_memory
= adapter_read_memory
,
665 .write_memory
= adapter_write_memory
,
666 .checksum_memory
= armv7m_checksum_memory
,
667 .blank_check_memory
= armv7m_blank_check_memory
,
669 .run_algorithm
= armv7m_run_algorithm
,
670 .start_algorithm
= armv7m_start_algorithm
,
671 .wait_algorithm
= armv7m_wait_algorithm
,
673 .add_breakpoint
= cortex_m_add_breakpoint
,
674 .remove_breakpoint
= cortex_m_remove_breakpoint
,
675 .add_watchpoint
= cortex_m_add_watchpoint
,
676 .remove_watchpoint
= cortex_m_remove_watchpoint
,
677 .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)