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 /* only set vector catch if halt is requested */
351 if (target
->reset_halt
)
352 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
|VC_CORERESET
);
354 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
);
356 if (jtag_reset_config
& RESET_HAS_SRST
) {
357 if (!srst_asserted
) {
358 res
= adapter_assert_reset();
360 if (res
== ERROR_COMMAND_NOTFOUND
)
361 LOG_ERROR("Hardware srst not supported, falling back to software reset");
362 else if (res
== ERROR_OK
) {
363 /* hardware srst supported */
364 use_srst_fallback
= false;
368 if (use_srst_fallback
) {
369 /* stlink v1 api does not support hardware srst, so we use a software reset fallback */
370 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, NVIC_AIRCR
, AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
373 res
= adapter
->layout
->api
->reset(adapter
->handle
);
378 /* registers are now invalid */
379 register_cache_invalidate(armv7m
->arm
.core_cache
);
381 if (target
->reset_halt
) {
382 target
->state
= TARGET_RESET
;
383 target
->debug_reason
= DBG_REASON_DBGRQ
;
385 target
->state
= TARGET_HALTED
;
391 static int hl_deassert_reset(struct target
*target
)
393 enum reset_types jtag_reset_config
= jtag_get_reset_config();
395 LOG_DEBUG("%s", __func__
);
397 if (jtag_reset_config
& RESET_HAS_SRST
)
398 adapter_deassert_reset();
400 target
->SAVED_DCRDR
= 0; /* clear both DCC busy bits on initial resume */
402 return target
->reset_halt
? ERROR_OK
: target_resume(target
, 1, 0, 0, 0);
405 static int adapter_halt(struct target
*target
)
408 struct hl_interface_s
*adapter
= target_to_adapter(target
);
410 LOG_DEBUG("%s", __func__
);
412 if (target
->state
== TARGET_HALTED
) {
413 LOG_DEBUG("target was already halted");
417 if (target
->state
== TARGET_UNKNOWN
)
418 LOG_WARNING("target was in unknown state when halt was requested");
420 res
= adapter
->layout
->api
->halt(adapter
->handle
);
425 target
->debug_reason
= DBG_REASON_DBGRQ
;
430 static int adapter_resume(struct target
*target
, int current
,
431 target_addr_t address
, int handle_breakpoints
,
435 struct hl_interface_s
*adapter
= target_to_adapter(target
);
436 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
438 struct breakpoint
*breakpoint
= NULL
;
441 LOG_DEBUG("%s %d " TARGET_ADDR_FMT
" %d %d", __func__
, current
,
442 address
, handle_breakpoints
, debug_execution
);
444 if (target
->state
!= TARGET_HALTED
) {
445 LOG_WARNING("target not halted");
446 return ERROR_TARGET_NOT_HALTED
;
449 if (!debug_execution
) {
450 target_free_all_working_areas(target
);
451 cortex_m_enable_breakpoints(target
);
452 cortex_m_enable_watchpoints(target
);
457 buf_set_u32(pc
->value
, 0, 32, address
);
462 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
463 && !debug_execution
) {
464 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
467 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
469 /* write any user vector flags */
470 res
= target_write_u32(target
, DCB_DEMCR
, TRCENA
| armv7m
->demcr
);
474 armv7m_restore_context(target
);
476 /* restore SAVED_DCRDR */
477 res
= target_write_u32(target
, DCB_DCRDR
, target
->SAVED_DCRDR
);
481 /* registers are now invalid */
482 register_cache_invalidate(armv7m
->arm
.core_cache
);
484 /* the front-end may request us not to handle breakpoints */
485 if (handle_breakpoints
) {
486 /* Single step past breakpoint at current address */
487 breakpoint
= breakpoint_find(target
, resume_pc
);
489 LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT
" (ID: %" PRIu32
")",
491 breakpoint
->unique_id
);
492 cortex_m_unset_breakpoint(target
, breakpoint
);
494 res
= adapter
->layout
->api
->step(adapter
->handle
);
499 cortex_m_set_breakpoint(target
, breakpoint
);
503 res
= adapter
->layout
->api
->run(adapter
->handle
);
508 target
->debug_reason
= DBG_REASON_NOTHALTED
;
510 if (!debug_execution
) {
511 target
->state
= TARGET_RUNNING
;
512 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
514 target
->state
= TARGET_DEBUG_RUNNING
;
515 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
521 static int adapter_step(struct target
*target
, int current
,
522 target_addr_t address
, int handle_breakpoints
)
525 struct hl_interface_s
*adapter
= target_to_adapter(target
);
526 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
527 struct breakpoint
*breakpoint
= NULL
;
528 struct reg
*pc
= armv7m
->arm
.pc
;
529 bool bkpt_inst_found
= false;
531 LOG_DEBUG("%s", __func__
);
533 if (target
->state
!= TARGET_HALTED
) {
534 LOG_WARNING("target not halted");
535 return ERROR_TARGET_NOT_HALTED
;
539 buf_set_u32(pc
->value
, 0, 32, address
);
544 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
546 /* the front-end may request us not to handle breakpoints */
547 if (handle_breakpoints
) {
548 breakpoint
= breakpoint_find(target
, pc_value
);
550 cortex_m_unset_breakpoint(target
, breakpoint
);
553 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
555 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
557 armv7m_restore_context(target
);
559 /* restore SAVED_DCRDR */
560 res
= target_write_u32(target
, DCB_DCRDR
, target
->SAVED_DCRDR
);
564 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
566 res
= adapter
->layout
->api
->step(adapter
->handle
);
571 /* registers are now invalid */
572 register_cache_invalidate(armv7m
->arm
.core_cache
);
575 cortex_m_set_breakpoint(target
, breakpoint
);
577 adapter_debug_entry(target
);
578 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
580 LOG_INFO("halted: PC: 0x%08" PRIx32
, buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
585 static int adapter_read_memory(struct target
*target
, target_addr_t address
,
586 uint32_t size
, uint32_t count
,
589 struct hl_interface_s
*adapter
= target_to_adapter(target
);
591 if (!count
|| !buffer
)
592 return ERROR_COMMAND_SYNTAX_ERROR
;
594 LOG_DEBUG("%s " TARGET_ADDR_FMT
" %" PRIu32
" %" PRIu32
,
595 __func__
, address
, size
, count
);
597 return adapter
->layout
->api
->read_mem(adapter
->handle
, address
, size
, count
, buffer
);
600 static int adapter_write_memory(struct target
*target
, target_addr_t address
,
601 uint32_t size
, uint32_t count
,
602 const uint8_t *buffer
)
604 struct hl_interface_s
*adapter
= target_to_adapter(target
);
606 if (!count
|| !buffer
)
607 return ERROR_COMMAND_SYNTAX_ERROR
;
609 LOG_DEBUG("%s " TARGET_ADDR_FMT
" %" PRIu32
" %" PRIu32
,
610 __func__
, address
, size
, count
);
612 return adapter
->layout
->api
->write_mem(adapter
->handle
, address
, size
, count
, buffer
);
615 static const struct command_registration hla_command_handlers
[] = {
617 .chain
= arm_command_handlers
,
620 .chain
= armv7m_trace_command_handlers
,
623 .chain
= rtt_target_command_handlers
,
625 /* START_DEPRECATED_TPIU */
627 .chain
= arm_tpiu_deprecated_command_handlers
,
629 /* END_DEPRECATED_TPIU */
630 COMMAND_REGISTRATION_DONE
633 struct target_type hla_target
= {
634 .name
= "hla_target",
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
= hla_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)