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 adapter_init_arch_info(target
, cortex_m
, target
->tap
);
222 static int adapter_load_context(struct target
*target
)
224 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
225 int num_regs
= armv7m
->arm
.core_cache
->num_regs
;
227 for (int i
= 0; i
< num_regs
; i
++) {
229 struct reg
*r
= &armv7m
->arm
.core_cache
->reg_list
[i
];
230 if (r
->exist
&& !r
->valid
)
231 armv7m
->arm
.read_core_reg(target
, r
, i
, ARM_MODE_ANY
);
237 static int adapter_debug_entry(struct target
*target
)
239 struct hl_interface_s
*adapter
= target_to_adapter(target
);
240 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
241 struct arm
*arm
= &armv7m
->arm
;
246 /* preserve the DCRDR across halts */
247 retval
= target_read_u32(target
, DCB_DCRDR
, &target
->SAVED_DCRDR
);
248 if (retval
!= ERROR_OK
)
251 retval
= armv7m
->examine_debug_reason(target
);
252 if (retval
!= ERROR_OK
)
255 adapter_load_context(target
);
257 /* make sure we clear the vector catch bit */
258 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
);
261 xPSR
= buf_get_u32(r
->value
, 0, 32);
263 /* Are we in an exception handler */
265 armv7m
->exception_number
= (xPSR
& 0x1FF);
267 arm
->core_mode
= ARM_MODE_HANDLER
;
268 arm
->map
= armv7m_msp_reg_map
;
270 unsigned control
= buf_get_u32(arm
->core_cache
271 ->reg_list
[ARMV7M_CONTROL
].value
, 0, 3);
273 /* is this thread privileged? */
274 arm
->core_mode
= control
& 1
275 ? ARM_MODE_USER_THREAD
278 /* which stack is it using? */
280 arm
->map
= armv7m_psp_reg_map
;
282 arm
->map
= armv7m_msp_reg_map
;
284 armv7m
->exception_number
= 0;
287 LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32
", target->state: %s",
288 arm_mode_name(arm
->core_mode
),
289 buf_get_u32(arm
->pc
->value
, 0, 32),
290 target_state_name(target
));
295 static int adapter_poll(struct target
*target
)
297 enum target_state state
;
298 struct hl_interface_s
*adapter
= target_to_adapter(target
);
299 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
300 enum target_state prev_target_state
= target
->state
;
302 state
= adapter
->layout
->api
->state(adapter
->handle
);
304 if (state
== TARGET_UNKNOWN
) {
305 LOG_ERROR("jtag status contains invalid mode value - communication failure");
306 return ERROR_TARGET_FAILURE
;
309 if (prev_target_state
== state
)
312 if (prev_target_state
== TARGET_DEBUG_RUNNING
&& state
== TARGET_RUNNING
)
315 target
->state
= state
;
317 if (state
== TARGET_HALTED
) {
319 int retval
= adapter_debug_entry(target
);
320 if (retval
!= ERROR_OK
)
323 if (prev_target_state
== TARGET_DEBUG_RUNNING
) {
324 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_HALTED
);
326 if (arm_semihosting(target
, &retval
) != 0)
329 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
332 LOG_DEBUG("halted: PC: 0x%08" PRIx32
, buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
338 static int hl_assert_reset(struct target
*target
)
341 struct hl_interface_s
*adapter
= target_to_adapter(target
);
342 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
343 bool use_srst_fallback
= true;
345 LOG_DEBUG("%s", __func__
);
347 enum reset_types jtag_reset_config
= jtag_get_reset_config();
349 bool srst_asserted
= false;
351 if ((jtag_reset_config
& RESET_HAS_SRST
) &&
352 (jtag_reset_config
& RESET_SRST_NO_GATING
)) {
353 res
= adapter_assert_reset();
354 srst_asserted
= true;
357 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DHCSR
, DBGKEY
|C_DEBUGEN
);
359 /* only set vector catch if halt is requested */
360 if (target
->reset_halt
)
361 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
|VC_CORERESET
);
363 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, DCB_DEMCR
, TRCENA
);
365 if (jtag_reset_config
& RESET_HAS_SRST
) {
366 if (!srst_asserted
) {
367 res
= adapter_assert_reset();
369 if (res
== ERROR_COMMAND_NOTFOUND
)
370 LOG_ERROR("Hardware srst not supported, falling back to software reset");
371 else if (res
== ERROR_OK
) {
372 /* hardware srst supported */
373 use_srst_fallback
= false;
377 if (use_srst_fallback
) {
378 /* stlink v1 api does not support hardware srst, so we use a software reset fallback */
379 adapter
->layout
->api
->write_debug_reg(adapter
->handle
, NVIC_AIRCR
, AIRCR_VECTKEY
| AIRCR_SYSRESETREQ
);
382 res
= adapter
->layout
->api
->reset(adapter
->handle
);
387 /* registers are now invalid */
388 register_cache_invalidate(armv7m
->arm
.core_cache
);
390 if (target
->reset_halt
) {
391 target
->state
= TARGET_RESET
;
392 target
->debug_reason
= DBG_REASON_DBGRQ
;
394 target
->state
= TARGET_HALTED
;
400 static int hl_deassert_reset(struct target
*target
)
402 enum reset_types jtag_reset_config
= jtag_get_reset_config();
404 LOG_DEBUG("%s", __func__
);
406 if (jtag_reset_config
& RESET_HAS_SRST
)
407 adapter_deassert_reset();
409 target
->SAVED_DCRDR
= 0; /* clear both DCC busy bits on initial resume */
411 return target
->reset_halt
? ERROR_OK
: target_resume(target
, 1, 0, 0, 0);
414 static int adapter_halt(struct target
*target
)
417 struct hl_interface_s
*adapter
= target_to_adapter(target
);
419 LOG_DEBUG("%s", __func__
);
421 if (target
->state
== TARGET_HALTED
) {
422 LOG_DEBUG("target was already halted");
426 if (target
->state
== TARGET_UNKNOWN
)
427 LOG_WARNING("target was in unknown state when halt was requested");
429 res
= adapter
->layout
->api
->halt(adapter
->handle
);
434 target
->debug_reason
= DBG_REASON_DBGRQ
;
439 static int adapter_resume(struct target
*target
, int current
,
440 target_addr_t address
, int handle_breakpoints
,
444 struct hl_interface_s
*adapter
= target_to_adapter(target
);
445 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
447 struct breakpoint
*breakpoint
= NULL
;
450 LOG_DEBUG("%s %d " TARGET_ADDR_FMT
" %d %d", __func__
, current
,
451 address
, handle_breakpoints
, debug_execution
);
453 if (target
->state
!= TARGET_HALTED
) {
454 LOG_WARNING("target not halted");
455 return ERROR_TARGET_NOT_HALTED
;
458 if (!debug_execution
) {
459 target_free_all_working_areas(target
);
460 cortex_m_enable_breakpoints(target
);
461 cortex_m_enable_watchpoints(target
);
466 buf_set_u32(pc
->value
, 0, 32, address
);
471 if (!breakpoint_find(target
, buf_get_u32(pc
->value
, 0, 32))
472 && !debug_execution
) {
473 armv7m_maybe_skip_bkpt_inst(target
, NULL
);
476 resume_pc
= buf_get_u32(pc
->value
, 0, 32);
478 /* write any user vector flags */
479 res
= target_write_u32(target
, DCB_DEMCR
, TRCENA
| armv7m
->demcr
);
483 armv7m_restore_context(target
);
485 /* restore SAVED_DCRDR */
486 res
= target_write_u32(target
, DCB_DCRDR
, target
->SAVED_DCRDR
);
490 /* registers are now invalid */
491 register_cache_invalidate(armv7m
->arm
.core_cache
);
493 /* the front-end may request us not to handle breakpoints */
494 if (handle_breakpoints
) {
495 /* Single step past breakpoint at current address */
496 breakpoint
= breakpoint_find(target
, resume_pc
);
498 LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT
" (ID: %" PRIu32
")",
500 breakpoint
->unique_id
);
501 cortex_m_unset_breakpoint(target
, breakpoint
);
503 res
= adapter
->layout
->api
->step(adapter
->handle
);
508 cortex_m_set_breakpoint(target
, breakpoint
);
512 res
= adapter
->layout
->api
->run(adapter
->handle
);
517 target
->debug_reason
= DBG_REASON_NOTHALTED
;
519 if (!debug_execution
) {
520 target
->state
= TARGET_RUNNING
;
521 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
523 target
->state
= TARGET_DEBUG_RUNNING
;
524 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
530 static int adapter_step(struct target
*target
, int current
,
531 target_addr_t address
, int handle_breakpoints
)
534 struct hl_interface_s
*adapter
= target_to_adapter(target
);
535 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
536 struct breakpoint
*breakpoint
= NULL
;
537 struct reg
*pc
= armv7m
->arm
.pc
;
538 bool bkpt_inst_found
= false;
540 LOG_DEBUG("%s", __func__
);
542 if (target
->state
!= TARGET_HALTED
) {
543 LOG_WARNING("target not halted");
544 return ERROR_TARGET_NOT_HALTED
;
548 buf_set_u32(pc
->value
, 0, 32, address
);
553 uint32_t pc_value
= buf_get_u32(pc
->value
, 0, 32);
555 /* the front-end may request us not to handle breakpoints */
556 if (handle_breakpoints
) {
557 breakpoint
= breakpoint_find(target
, pc_value
);
559 cortex_m_unset_breakpoint(target
, breakpoint
);
562 armv7m_maybe_skip_bkpt_inst(target
, &bkpt_inst_found
);
564 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
566 armv7m_restore_context(target
);
568 /* restore SAVED_DCRDR */
569 res
= target_write_u32(target
, DCB_DCRDR
, target
->SAVED_DCRDR
);
573 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
575 res
= adapter
->layout
->api
->step(adapter
->handle
);
580 /* registers are now invalid */
581 register_cache_invalidate(armv7m
->arm
.core_cache
);
584 cortex_m_set_breakpoint(target
, breakpoint
);
586 adapter_debug_entry(target
);
587 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
589 LOG_INFO("halted: PC: 0x%08" PRIx32
, buf_get_u32(armv7m
->arm
.pc
->value
, 0, 32));
594 static int adapter_read_memory(struct target
*target
, target_addr_t address
,
595 uint32_t size
, uint32_t count
,
598 struct hl_interface_s
*adapter
= target_to_adapter(target
);
600 if (!count
|| !buffer
)
601 return ERROR_COMMAND_SYNTAX_ERROR
;
603 LOG_DEBUG("%s " TARGET_ADDR_FMT
" %" PRIu32
" %" PRIu32
,
604 __func__
, address
, size
, count
);
606 return adapter
->layout
->api
->read_mem(adapter
->handle
, address
, size
, count
, buffer
);
609 static int adapter_write_memory(struct target
*target
, target_addr_t address
,
610 uint32_t size
, uint32_t count
,
611 const uint8_t *buffer
)
613 struct hl_interface_s
*adapter
= target_to_adapter(target
);
615 if (!count
|| !buffer
)
616 return ERROR_COMMAND_SYNTAX_ERROR
;
618 LOG_DEBUG("%s " TARGET_ADDR_FMT
" %" PRIu32
" %" PRIu32
,
619 __func__
, address
, size
, count
);
621 return adapter
->layout
->api
->write_mem(adapter
->handle
, address
, size
, count
, buffer
);
624 static const struct command_registration adapter_command_handlers
[] = {
626 .chain
= arm_command_handlers
,
629 .chain
= armv7m_trace_command_handlers
,
632 .chain
= rtt_target_command_handlers
,
634 /* START_DEPRECATED_TPIU */
636 .chain
= arm_tpiu_deprecated_command_handlers
,
638 /* END_DEPRECATED_TPIU */
639 COMMAND_REGISTRATION_DONE
642 struct target_type hla_target
= {
643 .name
= "hla_target",
645 .init_target
= adapter_init_target
,
646 .deinit_target
= cortex_m_deinit_target
,
647 .target_create
= adapter_target_create
,
648 .target_jim_configure
= adiv5_jim_configure
,
649 .examine
= cortex_m_examine
,
650 .commands
= adapter_command_handlers
,
652 .poll
= adapter_poll
,
653 .arch_state
= armv7m_arch_state
,
655 .target_request_data
= hl_target_request_data
,
656 .assert_reset
= hl_assert_reset
,
657 .deassert_reset
= hl_deassert_reset
,
659 .halt
= adapter_halt
,
660 .resume
= adapter_resume
,
661 .step
= adapter_step
,
663 .get_gdb_arch
= arm_get_gdb_arch
,
664 .get_gdb_reg_list
= armv7m_get_gdb_reg_list
,
666 .read_memory
= adapter_read_memory
,
667 .write_memory
= adapter_write_memory
,
668 .checksum_memory
= armv7m_checksum_memory
,
669 .blank_check_memory
= armv7m_blank_check_memory
,
671 .run_algorithm
= armv7m_run_algorithm
,
672 .start_algorithm
= armv7m_start_algorithm
,
673 .wait_algorithm
= armv7m_wait_algorithm
,
675 .add_breakpoint
= cortex_m_add_breakpoint
,
676 .remove_breakpoint
= cortex_m_remove_breakpoint
,
677 .add_watchpoint
= cortex_m_add_watchpoint
,
678 .remove_watchpoint
= cortex_m_remove_watchpoint
,
679 .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)