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_adi_v5.h"
41 #include "arm_semihosting.h"
42 #include "target_request.h"
45 #define SAVED_DCRDR dbgbase /* FIXME: using target->dbgbase to preserve DCRDR */
47 #define ARMV7M_SCS_DCRSR DCB_DCRSR
48 #define ARMV7M_SCS_DCRDR DCB_DCRDR
50 static inline struct hl_interface_s
*target_to_adapter(struct target
*target
)
52 return target
->tap
->priv
;
55 static int adapter_load_core_reg_u32(struct target
*target
,
56 uint32_t regsel
, uint32_t *value
)
58 struct hl_interface_s
*adapter
= target_to_adapter(target
);
59 return adapter
->layout
->api
->read_reg(adapter
->handle
, regsel
, value
);
62 static int adapter_store_core_reg_u32(struct target
*target
,
63 uint32_t regsel
, uint32_t value
)
65 struct hl_interface_s
*adapter
= target_to_adapter(target
);
66 return adapter
->layout
->api
->write_reg(adapter
->handle
, regsel
, value
);
69 static int adapter_examine_debug_reason(struct target
*target
)
71 if ((target
->debug_reason
!= DBG_REASON_DBGRQ
)
72 && (target
->debug_reason
!= DBG_REASON_SINGLESTEP
)) {
73 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
79 static int hl_dcc_read(struct hl_interface_s
*hl_if
, uint8_t *value
, uint8_t *ctrl
)
82 int retval
= hl_if
->layout
->api
->read_mem(hl_if
->handle
,
83 DCB_DCRDR
, 1, sizeof(dcrdr
), (uint8_t *)&dcrdr
);
84 if (retval
== ERROR_OK
) {
85 *ctrl
= (uint8_t)dcrdr
;
86 *value
= (uint8_t)(dcrdr
>> 8);
88 LOG_DEBUG("data 0x%x ctrl 0x%x", *value
, *ctrl
);
91 /* write ack back to software dcc register
92 * to signify we have read data */
93 /* atomically clear just the byte containing the busy bit */
94 static const uint8_t zero
;
95 retval
= hl_if
->layout
->api
->write_mem(hl_if
->handle
, DCB_DCRDR
, 1, 1, &zero
);
101 static int hl_target_request_data(struct target
*target
,
102 uint32_t size
, uint8_t *buffer
)
104 struct hl_interface_s
*hl_if
= target_to_adapter(target
);
109 for (i
= 0; i
< (size
* 4); i
++) {
110 int err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
120 static int hl_handle_target_request(void *priv
)
122 struct target
*target
= priv
;
125 if (!target_was_examined(target
))
127 struct hl_interface_s
*hl_if
= target_to_adapter(target
);
129 if (!target
->dbg_msg_enabled
)
132 if (target
->state
== TARGET_RUNNING
) {
136 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
140 /* check if we have data */
141 if (ctrl
& (1 << 0)) {
144 /* we assume target is quick enough */
146 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
150 request
|= (data
<< 8);
151 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
155 request
|= (data
<< 16);
156 err
= hl_dcc_read(hl_if
, &data
, &ctrl
);
160 request
|= (data
<< 24);
161 target_request(target
, request
);
168 static int adapter_init_arch_info(struct target
*target
,
169 struct cortex_m_common
*cortex_m
,
170 struct jtag_tap
*tap
)
172 struct armv7m_common
*armv7m
;
174 LOG_DEBUG("%s", __func__
);
176 armv7m
= &cortex_m
->armv7m
;
177 armv7m_init_arch_info(target
, armv7m
);
179 armv7m
->load_core_reg_u32
= adapter_load_core_reg_u32
;
180 armv7m
->store_core_reg_u32
= adapter_store_core_reg_u32
;
182 armv7m
->examine_debug_reason
= adapter_examine_debug_reason
;
183 armv7m
->is_hla_target
= true;
185 target_register_timer_callback(hl_handle_target_request
, 1,
186 TARGET_TIMER_TYPE_PERIODIC
, target
);
191 static int adapter_init_target(struct command_context
*cmd_ctx
,
192 struct target
*target
)
194 LOG_DEBUG("%s", __func__
);
196 armv7m_build_reg_cache(target
);
197 arm_semihosting_init(target
);
201 static int adapter_target_create(struct target
*target
,
204 LOG_DEBUG("%s", __func__
);
205 struct adiv5_private_config
*pc
= target
->private_config
;
206 if (pc
&& pc
->ap_num
> 0) {
207 LOG_ERROR("hla_target: invalid parameter -ap-num (> 0)");
208 return ERROR_COMMAND_SYNTAX_ERROR
;
211 struct cortex_m_common
*cortex_m
= calloc(1, sizeof(struct cortex_m_common
));
213 LOG_ERROR("No memory creating target");
217 cortex_m
->common_magic
= CORTEX_M_COMMON_MAGIC
;
219 adapter_init_arch_info(target
, cortex_m
, target
->tap
);
224 static int adapter_load_context(struct target
*target
)
226 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
227 int num_regs
= armv7m
->arm
.core_cache
->num_regs
;
229 for (int i
= 0; i
< num_regs
; i
++) {
231 struct reg
*r
= &armv7m
->arm
.core_cache
->reg_list
[i
];
232 if (r
->exist
&& !r
->valid
)
233 armv7m
->arm
.read_core_reg(target
, r
, i
, ARM_MODE_ANY
);
239 static int adapter_debug_entry(struct target
*target
)
241 struct hl_interface_s
*adapter
= target_to_adapter(target
);
242 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
243 struct arm
*arm
= &armv7m
->arm
;
248 /* preserve the DCRDR across halts */
249 retval
= target_read_u32(target
, DCB_DCRDR
, &target
->SAVED_DCRDR
);
250 if (retval
!= ERROR_OK
)
253 retval
= armv7m
->examine_debug_reason(target
);
254 if (retval
!= ERROR_OK
)
257 adapter_load_context(target
);
259 /* make sure we clear the vector catch bit */
260 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
);
263 xPSR
= buf_get_u32(r
->value
, 0, 32);
265 /* Are we in an exception handler */
267 armv7m
->exception_number
= (xPSR
& 0x1FF);
269 arm
->core_mode
= ARM_MODE_HANDLER
;
270 arm
->map
= armv7m_msp_reg_map
;
272 unsigned control
= buf_get_u32(arm
->core_cache
273 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 3);
275 /* is this thread privileged? */
276 arm
->core_mode
= control
& 1
277 ? ARM_MODE_USER_THREAD
280 /* which stack is it using? */
282 arm
->map
= armv7m_psp_reg_map
;
284 arm
->map
= armv7m_msp_reg_map
;
286 armv7m
->exception_number
= 0;
289 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32
", target->state: %s",
290 arm_mode_name(arm
->core_mode
),
291 buf_get_u32(arm
->pc
->value
, 0, 32),
292 target_state_name(target
));
297 static int adapter_poll(struct target
*target
)
299 enum target_state state
;
300 struct hl_interface_s
*adapter
= target_to_adapter(target
);
301 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
302 enum target_state prev_target_state
= target
->state
;
304 state
= adapter
->layout
->api
->state(adapter
->handle
);
306 if (state
== TARGET_UNKNOWN
) {
307 LOG_ERROR("jtag status contains invalid mode value - communication failure");
308 return ERROR_TARGET_FAILURE
;
311 if (prev_target_state
== state
)
314 if (prev_target_state
== TARGET_DEBUG_RUNNING
&& state
== TARGET_RUNNING
)
317 target
->state
= state
;
319 if (state
== TARGET_HALTED
) {
321 int retval
= adapter_debug_entry(target
);
322 if (retval
!= ERROR_OK
)
325 if (prev_target_state
== TARGET_DEBUG_RUNNING
) {
326 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
328 if (arm_semihosting(target
, &retval
) != 0)
331 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
334 LOG_DEBUG("halted: PC: 0x%08" PRIx32
, buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
340 static int hl_assert_reset(struct target
*target
)
343 struct hl_interface_s
*adapter
= target_to_adapter(target
);
344 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
345 bool use_srst_fallback
= true;
347 LOG_DEBUG("%s", __func__
);
349 enum reset_types jtag_reset_config
= jtag_get_reset_config();
351 bool srst_asserted
= false;
353 if ((jtag_reset_config
& RESET_HAS_SRST
) &&
354 (jtag_reset_config
& RESET_SRST_NO_GATING
)) {
355 res
= adapter_assert_reset();
356 srst_asserted
= true;
359 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DHCSR
, DBGKEY
|C_DEBUGEN
);
361 /* only set vector catch if halt is requested */
362 if (target
->reset_halt
)
363 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
|VC_CORERESET
);
365 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
);
367 if (jtag_reset_config
& RESET_HAS_SRST
) {
368 if (!srst_asserted
) {
369 res
= adapter_assert_reset();
371 if (res
== ERROR_COMMAND_NOTFOUND
)
372 LOG_ERROR("Hardware srst not supported, falling back to software reset");
373 else if (res
== ERROR_OK
) {
374 /* hardware srst supported */
375 use_srst_fallback
= false;
379 if (use_srst_fallback
) {
380 /* stlink v1 api does not support hardware srst, so we use a software reset fallback */
381 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, NVIC_AIRCR
, AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
384 res
= adapter
->layout
->api
->reset(adapter
->handle
);
389 /* registers are now invalid */
390 register_cache_invalidate(armv7m
->arm
.core_cache
);
392 if (target
->reset_halt
) {
393 target
->state
= TARGET_RESET
;
394 target
->debug_reason
= DBG_REASON_DBGRQ
;
396 target
->state
= TARGET_HALTED
;
402 static int hl_deassert_reset(struct target
*target
)
404 enum reset_types jtag_reset_config
= jtag_get_reset_config();
406 LOG_DEBUG("%s", __func__
);
408 if (jtag_reset_config
& RESET_HAS_SRST
)
409 adapter_deassert_reset();
411 target
->SAVED_DCRDR
= 0; /* clear both DCC busy bits on initial resume */
413 return target
->reset_halt
? ERROR_OK
: target_resume(target
, 1, 0, 0, 0);
416 static int adapter_halt(struct target
*target
)
419 struct hl_interface_s
*adapter
= target_to_adapter(target
);
421 LOG_DEBUG("%s", __func__
);
423 if (target
->state
== TARGET_HALTED
) {
424 LOG_DEBUG("target was already halted");
428 if (target
->state
== TARGET_UNKNOWN
)
429 LOG_WARNING("target was in unknown state when halt was requested");
431 res
= adapter
->layout
->api
->halt(adapter
->handle
);
436 target
->debug_reason
= DBG_REASON_DBGRQ
;
441 static int adapter_resume(struct target
*target
, int current
,
442 target_addr_t address
, int handle_breakpoints
,
446 struct hl_interface_s
*adapter
= target_to_adapter(target
);
447 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
449 struct breakpoint
*breakpoint
= NULL
;
452 LOG_DEBUG("%s %d " TARGET_ADDR_FMT
" %d %d", __func__
, current
,
453 address
, handle_breakpoints
, debug_execution
);
455 if (target
->state
!= TARGET_HALTED
) {
456 LOG_WARNING("target not halted");
457 return ERROR_TARGET_NOT_HALTED
;
460 if (!debug_execution
) {
461 target_free_all_working_areas(target
);
462 cortex_m_enable_breakpoints(target
);
463 cortex_m_enable_watchpoints(target
);
468 buf_set_u32(pc
->value
, 0, 32, address
);
473 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
474 && !debug_execution
) {
475 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
478 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
480 /* write any user vector flags */
481 res
= target_write_u32(target
, DCB_DEMCR
, TRCENA
| armv7m
->demcr
);
485 armv7m_restore_context(target
);
487 /* restore SAVED_DCRDR */
488 res
= target_write_u32(target
, DCB_DCRDR
, target
->SAVED_DCRDR
);
492 /* registers are now invalid */
493 register_cache_invalidate(armv7m
->arm
.core_cache
);
495 /* the front-end may request us not to handle breakpoints */
496 if (handle_breakpoints
) {
497 /* Single step past breakpoint at current address */
498 breakpoint
= breakpoint_find(target
, resume_pc
);
500 LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT
" (ID: %" PRIu32
")",
502 breakpoint
->unique_id
);
503 cortex_m_unset_breakpoint(target
, breakpoint
);
505 res
= adapter
->layout
->api
->step(adapter
->handle
);
510 cortex_m_set_breakpoint(target
, breakpoint
);
514 res
= adapter
->layout
->api
->run(adapter
->handle
);
519 target
->debug_reason
= DBG_REASON_NOTHALTED
;
521 if (!debug_execution
) {
522 target
->state
= TARGET_RUNNING
;
523 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
525 target
->state
= TARGET_DEBUG_RUNNING
;
526 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
532 static int adapter_step(struct target
*target
, int current
,
533 target_addr_t address
, int handle_breakpoints
)
536 struct hl_interface_s
*adapter
= target_to_adapter(target
);
537 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
538 struct breakpoint
*breakpoint
= NULL
;
539 struct reg
*pc
= armv7m
->arm
.pc
;
540 bool bkpt_inst_found
= false;
542 LOG_DEBUG("%s", __func__
);
544 if (target
->state
!= TARGET_HALTED
) {
545 LOG_WARNING("target not halted");
546 return ERROR_TARGET_NOT_HALTED
;
550 buf_set_u32(pc
->value
, 0, 32, address
);
555 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
557 /* the front-end may request us not to handle breakpoints */
558 if (handle_breakpoints
) {
559 breakpoint
= breakpoint_find(target
, pc_value
);
561 cortex_m_unset_breakpoint(target
, breakpoint
);
564 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
566 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
568 armv7m_restore_context(target
);
570 /* restore SAVED_DCRDR */
571 res
= target_write_u32(target
, DCB_DCRDR
, target
->SAVED_DCRDR
);
575 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
577 res
= adapter
->layout
->api
->step(adapter
->handle
);
582 /* registers are now invalid */
583 register_cache_invalidate(armv7m
->arm
.core_cache
);
586 cortex_m_set_breakpoint(target
, breakpoint
);
588 adapter_debug_entry(target
);
589 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
591 LOG_INFO("halted: PC: 0x%08" PRIx32
, buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
596 static int adapter_read_memory(struct target
*target
, target_addr_t address
,
597 uint32_t size
, uint32_t count
,
600 struct hl_interface_s
*adapter
= target_to_adapter(target
);
602 if (!count
|| !buffer
)
603 return ERROR_COMMAND_SYNTAX_ERROR
;
605 LOG_DEBUG("%s " TARGET_ADDR_FMT
" %" PRIu32
" %" PRIu32
,
606 __func__
, address
, size
, count
);
608 return adapter
->layout
->api
->read_mem(adapter
->handle
, address
, size
, count
, buffer
);
611 static int adapter_write_memory(struct target
*target
, target_addr_t address
,
612 uint32_t size
, uint32_t count
,
613 const uint8_t *buffer
)
615 struct hl_interface_s
*adapter
= target_to_adapter(target
);
617 if (!count
|| !buffer
)
618 return ERROR_COMMAND_SYNTAX_ERROR
;
620 LOG_DEBUG("%s " TARGET_ADDR_FMT
" %" PRIu32
" %" PRIu32
,
621 __func__
, address
, size
, count
);
623 return adapter
->layout
->api
->write_mem(adapter
->handle
, address
, size
, count
, buffer
);
626 static const struct command_registration hla_command_handlers
[] = {
628 .chain
= arm_command_handlers
,
631 .chain
= armv7m_trace_command_handlers
,
634 .chain
= rtt_target_command_handlers
,
636 /* START_DEPRECATED_TPIU */
638 .chain
= arm_tpiu_deprecated_command_handlers
,
640 /* END_DEPRECATED_TPIU */
641 COMMAND_REGISTRATION_DONE
644 struct target_type hla_target
= {
645 .name
= "hla_target",
647 .init_target
= adapter_init_target
,
648 .deinit_target
= cortex_m_deinit_target
,
649 .target_create
= adapter_target_create
,
650 .target_jim_configure
= adiv5_jim_configure
,
651 .examine
= cortex_m_examine
,
652 .commands
= hla_command_handlers
,
654 .poll
= adapter_poll
,
655 .arch_state
= armv7m_arch_state
,
657 .target_request_data
= hl_target_request_data
,
658 .assert_reset
= hl_assert_reset
,
659 .deassert_reset
= hl_deassert_reset
,
661 .halt
= adapter_halt
,
662 .resume
= adapter_resume
,
663 .step
= adapter_step
,
665 .get_gdb_arch
= arm_get_gdb_arch
,
666 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
668 .read_memory
= adapter_read_memory
,
669 .write_memory
= adapter_write_memory
,
670 .checksum_memory
= armv7m_checksum_memory
,
671 .blank_check_memory
= armv7m_blank_check_memory
,
673 .run_algorithm
= armv7m_run_algorithm
,
674 .start_algorithm
= armv7m_start_algorithm
,
675 .wait_algorithm
= armv7m_wait_algorithm
,
677 .add_breakpoint
= cortex_m_add_breakpoint
,
678 .remove_breakpoint
= cortex_m_remove_breakpoint
,
679 .add_watchpoint
= cortex_m_add_watchpoint
,
680 .remove_watchpoint
= cortex_m_remove_watchpoint
,
681 .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)