openocd: src/target: replace the GPL-2.0-or-later license tag
[openocd.git] / src / target / hla_target.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4 * Copyright (C) 2011 by Mathias Kuester *
5 * Mathias Kuester <kesmtp@freenet.de> *
6 * *
7 * Copyright (C) 2011 by Spencer Oliver *
8 * spen@spen-soft.co.uk *
9 * *
10 * revised: 4/25/13 by brent@mbari.org [DCC target request support] *
11 ***************************************************************************/
12
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16
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"
22 #include "register.h"
23 #include "algorithm.h"
24 #include "target.h"
25 #include "breakpoints.h"
26 #include "target_type.h"
27 #include "armv7m.h"
28 #include "cortex_m.h"
29 #include "arm_adi_v5.h"
30 #include "arm_semihosting.h"
31 #include "target_request.h"
32 #include <rtt/rtt.h>
33
34 #define SAVED_DCRDR dbgbase /* FIXME: using target->dbgbase to preserve DCRDR */
35
36 #define ARMV7M_SCS_DCRSR DCB_DCRSR
37 #define ARMV7M_SCS_DCRDR DCB_DCRDR
38
39 static inline struct hl_interface_s *target_to_adapter(struct target *target)
40 {
41 return target->tap->priv;
42 }
43
44 static int adapter_load_core_reg_u32(struct target *target,
45 uint32_t regsel, uint32_t *value)
46 {
47 struct hl_interface_s *adapter = target_to_adapter(target);
48 return adapter->layout->api->read_reg(adapter->handle, regsel, value);
49 }
50
51 static int adapter_store_core_reg_u32(struct target *target,
52 uint32_t regsel, uint32_t value)
53 {
54 struct hl_interface_s *adapter = target_to_adapter(target);
55 return adapter->layout->api->write_reg(adapter->handle, regsel, value);
56 }
57
58 static int adapter_examine_debug_reason(struct target *target)
59 {
60 if ((target->debug_reason != DBG_REASON_DBGRQ)
61 && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
62 target->debug_reason = DBG_REASON_BREAKPOINT;
63 }
64
65 return ERROR_OK;
66 }
67
68 static int hl_dcc_read(struct hl_interface_s *hl_if, uint8_t *value, uint8_t *ctrl)
69 {
70 uint16_t dcrdr;
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);
76
77 LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
78
79 if (dcrdr & 1) {
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);
85 }
86 }
87 return retval;
88 }
89
90 static int hl_target_request_data(struct target *target,
91 uint32_t size, uint8_t *buffer)
92 {
93 struct hl_interface_s *hl_if = target_to_adapter(target);
94 uint8_t data;
95 uint8_t ctrl;
96 uint32_t i;
97
98 for (i = 0; i < (size * 4); i++) {
99 int err = hl_dcc_read(hl_if, &data, &ctrl);
100 if (err != ERROR_OK)
101 return err;
102
103 buffer[i] = data;
104 }
105
106 return ERROR_OK;
107 }
108
109 static int hl_handle_target_request(void *priv)
110 {
111 struct target *target = priv;
112 int err;
113
114 if (!target_was_examined(target))
115 return ERROR_OK;
116 struct hl_interface_s *hl_if = target_to_adapter(target);
117
118 if (!target->dbg_msg_enabled)
119 return ERROR_OK;
120
121 if (target->state == TARGET_RUNNING) {
122 uint8_t data;
123 uint8_t ctrl;
124
125 err = hl_dcc_read(hl_if, &data, &ctrl);
126 if (err != ERROR_OK)
127 return err;
128
129 /* check if we have data */
130 if (ctrl & (1 << 0)) {
131 uint32_t request;
132
133 /* we assume target is quick enough */
134 request = data;
135 err = hl_dcc_read(hl_if, &data, &ctrl);
136 if (err != ERROR_OK)
137 return err;
138
139 request |= (data << 8);
140 err = hl_dcc_read(hl_if, &data, &ctrl);
141 if (err != ERROR_OK)
142 return err;
143
144 request |= (data << 16);
145 err = hl_dcc_read(hl_if, &data, &ctrl);
146 if (err != ERROR_OK)
147 return err;
148
149 request |= (data << 24);
150 target_request(target, request);
151 }
152 }
153
154 return ERROR_OK;
155 }
156
157 static int adapter_init_arch_info(struct target *target,
158 struct cortex_m_common *cortex_m,
159 struct jtag_tap *tap)
160 {
161 struct armv7m_common *armv7m;
162
163 LOG_DEBUG("%s", __func__);
164
165 armv7m = &cortex_m->armv7m;
166 armv7m_init_arch_info(target, armv7m);
167
168 armv7m->load_core_reg_u32 = adapter_load_core_reg_u32;
169 armv7m->store_core_reg_u32 = adapter_store_core_reg_u32;
170
171 armv7m->examine_debug_reason = adapter_examine_debug_reason;
172 armv7m->is_hla_target = true;
173
174 target_register_timer_callback(hl_handle_target_request, 1,
175 TARGET_TIMER_TYPE_PERIODIC, target);
176
177 return ERROR_OK;
178 }
179
180 static int adapter_init_target(struct command_context *cmd_ctx,
181 struct target *target)
182 {
183 LOG_DEBUG("%s", __func__);
184
185 armv7m_build_reg_cache(target);
186 arm_semihosting_init(target);
187 return ERROR_OK;
188 }
189
190 static int adapter_target_create(struct target *target,
191 Jim_Interp *interp)
192 {
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;
198 }
199
200 struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
201 if (!cortex_m) {
202 LOG_ERROR("No memory creating target");
203 return ERROR_FAIL;
204 }
205
206 cortex_m->common_magic = CORTEX_M_COMMON_MAGIC;
207
208 adapter_init_arch_info(target, cortex_m, target->tap);
209
210 return ERROR_OK;
211 }
212
213 static int adapter_load_context(struct target *target)
214 {
215 struct armv7m_common *armv7m = target_to_armv7m(target);
216 int num_regs = armv7m->arm.core_cache->num_regs;
217
218 for (int i = 0; i < num_regs; i++) {
219
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);
223 }
224
225 return ERROR_OK;
226 }
227
228 static int adapter_debug_entry(struct target *target)
229 {
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;
233 struct reg *r;
234 uint32_t xPSR;
235 int retval;
236
237 /* preserve the DCRDR across halts */
238 retval = target_read_u32(target, DCB_DCRDR, &target->SAVED_DCRDR);
239 if (retval != ERROR_OK)
240 return retval;
241
242 retval = armv7m->examine_debug_reason(target);
243 if (retval != ERROR_OK)
244 return retval;
245
246 adapter_load_context(target);
247
248 /* make sure we clear the vector catch bit */
249 adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA);
250
251 r = arm->cpsr;
252 xPSR = buf_get_u32(r->value, 0, 32);
253
254 /* Are we in an exception handler */
255 if (xPSR & 0x1FF) {
256 armv7m->exception_number = (xPSR & 0x1FF);
257
258 arm->core_mode = ARM_MODE_HANDLER;
259 arm->map = armv7m_msp_reg_map;
260 } else {
261 unsigned control = buf_get_u32(arm->core_cache
262 ->reg_list[ARMV7M_CONTROL].value, 0, 3);
263
264 /* is this thread privileged? */
265 arm->core_mode = control & 1
266 ? ARM_MODE_USER_THREAD
267 : ARM_MODE_THREAD;
268
269 /* which stack is it using? */
270 if (control & 2)
271 arm->map = armv7m_psp_reg_map;
272 else
273 arm->map = armv7m_msp_reg_map;
274
275 armv7m->exception_number = 0;
276 }
277
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));
282
283 return retval;
284 }
285
286 static int adapter_poll(struct target *target)
287 {
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;
292
293 state = adapter->layout->api->state(adapter->handle);
294
295 if (state == TARGET_UNKNOWN) {
296 LOG_ERROR("jtag status contains invalid mode value - communication failure");
297 return ERROR_TARGET_FAILURE;
298 }
299
300 if (prev_target_state == state)
301 return ERROR_OK;
302
303 if (prev_target_state == TARGET_DEBUG_RUNNING && state == TARGET_RUNNING)
304 return ERROR_OK;
305
306 target->state = state;
307
308 if (state == TARGET_HALTED) {
309
310 int retval = adapter_debug_entry(target);
311 if (retval != ERROR_OK)
312 return retval;
313
314 if (prev_target_state == TARGET_DEBUG_RUNNING) {
315 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
316 } else {
317 if (arm_semihosting(target, &retval) != 0)
318 return retval;
319
320 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
321 }
322
323 LOG_DEBUG("halted: PC: 0x%08" PRIx32, buf_get_u32(armv7m->arm.pc->value, 0, 32));
324 }
325
326 return ERROR_OK;
327 }
328
329 static int hl_assert_reset(struct target *target)
330 {
331 int res = ERROR_OK;
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;
335
336 LOG_DEBUG("%s", __func__);
337
338 enum reset_types jtag_reset_config = jtag_get_reset_config();
339
340 bool srst_asserted = false;
341
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;
346 }
347
348 adapter->layout->api->write_debug_reg(adapter->handle, DCB_DHCSR, DBGKEY|C_DEBUGEN);
349
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);
353 else
354 adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA);
355
356 if (jtag_reset_config & RESET_HAS_SRST) {
357 if (!srst_asserted) {
358 res = adapter_assert_reset();
359 }
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;
365 }
366 }
367
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);
371 }
372
373 res = adapter->layout->api->reset(adapter->handle);
374
375 if (res != ERROR_OK)
376 return res;
377
378 /* registers are now invalid */
379 register_cache_invalidate(armv7m->arm.core_cache);
380
381 if (target->reset_halt) {
382 target->state = TARGET_RESET;
383 target->debug_reason = DBG_REASON_DBGRQ;
384 } else {
385 target->state = TARGET_HALTED;
386 }
387
388 return ERROR_OK;
389 }
390
391 static int hl_deassert_reset(struct target *target)
392 {
393 enum reset_types jtag_reset_config = jtag_get_reset_config();
394
395 LOG_DEBUG("%s", __func__);
396
397 if (jtag_reset_config & RESET_HAS_SRST)
398 adapter_deassert_reset();
399
400 target->SAVED_DCRDR = 0; /* clear both DCC busy bits on initial resume */
401
402 return target->reset_halt ? ERROR_OK : target_resume(target, 1, 0, 0, 0);
403 }
404
405 static int adapter_halt(struct target *target)
406 {
407 int res;
408 struct hl_interface_s *adapter = target_to_adapter(target);
409
410 LOG_DEBUG("%s", __func__);
411
412 if (target->state == TARGET_HALTED) {
413 LOG_DEBUG("target was already halted");
414 return ERROR_OK;
415 }
416
417 if (target->state == TARGET_UNKNOWN)
418 LOG_WARNING("target was in unknown state when halt was requested");
419
420 res = adapter->layout->api->halt(adapter->handle);
421
422 if (res != ERROR_OK)
423 return res;
424
425 target->debug_reason = DBG_REASON_DBGRQ;
426
427 return ERROR_OK;
428 }
429
430 static int adapter_resume(struct target *target, int current,
431 target_addr_t address, int handle_breakpoints,
432 int debug_execution)
433 {
434 int res;
435 struct hl_interface_s *adapter = target_to_adapter(target);
436 struct armv7m_common *armv7m = target_to_armv7m(target);
437 uint32_t resume_pc;
438 struct breakpoint *breakpoint = NULL;
439 struct reg *pc;
440
441 LOG_DEBUG("%s %d " TARGET_ADDR_FMT " %d %d", __func__, current,
442 address, handle_breakpoints, debug_execution);
443
444 if (target->state != TARGET_HALTED) {
445 LOG_WARNING("target not halted");
446 return ERROR_TARGET_NOT_HALTED;
447 }
448
449 if (!debug_execution) {
450 target_free_all_working_areas(target);
451 cortex_m_enable_breakpoints(target);
452 cortex_m_enable_watchpoints(target);
453 }
454
455 pc = armv7m->arm.pc;
456 if (!current) {
457 buf_set_u32(pc->value, 0, 32, address);
458 pc->dirty = true;
459 pc->valid = true;
460 }
461
462 if (!breakpoint_find(target, buf_get_u32(pc->value, 0, 32))
463 && !debug_execution) {
464 armv7m_maybe_skip_bkpt_inst(target, NULL);
465 }
466
467 resume_pc = buf_get_u32(pc->value, 0, 32);
468
469 /* write any user vector flags */
470 res = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr);
471 if (res != ERROR_OK)
472 return res;
473
474 armv7m_restore_context(target);
475
476 /* restore SAVED_DCRDR */
477 res = target_write_u32(target, DCB_DCRDR, target->SAVED_DCRDR);
478 if (res != ERROR_OK)
479 return res;
480
481 /* registers are now invalid */
482 register_cache_invalidate(armv7m->arm.core_cache);
483
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);
488 if (breakpoint) {
489 LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")",
490 breakpoint->address,
491 breakpoint->unique_id);
492 cortex_m_unset_breakpoint(target, breakpoint);
493
494 res = adapter->layout->api->step(adapter->handle);
495
496 if (res != ERROR_OK)
497 return res;
498
499 cortex_m_set_breakpoint(target, breakpoint);
500 }
501 }
502
503 res = adapter->layout->api->run(adapter->handle);
504
505 if (res != ERROR_OK)
506 return res;
507
508 target->debug_reason = DBG_REASON_NOTHALTED;
509
510 if (!debug_execution) {
511 target->state = TARGET_RUNNING;
512 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
513 } else {
514 target->state = TARGET_DEBUG_RUNNING;
515 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
516 }
517
518 return ERROR_OK;
519 }
520
521 static int adapter_step(struct target *target, int current,
522 target_addr_t address, int handle_breakpoints)
523 {
524 int res;
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;
530
531 LOG_DEBUG("%s", __func__);
532
533 if (target->state != TARGET_HALTED) {
534 LOG_WARNING("target not halted");
535 return ERROR_TARGET_NOT_HALTED;
536 }
537
538 if (!current) {
539 buf_set_u32(pc->value, 0, 32, address);
540 pc->dirty = true;
541 pc->valid = true;
542 }
543
544 uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
545
546 /* the front-end may request us not to handle breakpoints */
547 if (handle_breakpoints) {
548 breakpoint = breakpoint_find(target, pc_value);
549 if (breakpoint)
550 cortex_m_unset_breakpoint(target, breakpoint);
551 }
552
553 armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
554
555 target->debug_reason = DBG_REASON_SINGLESTEP;
556
557 armv7m_restore_context(target);
558
559 /* restore SAVED_DCRDR */
560 res = target_write_u32(target, DCB_DCRDR, target->SAVED_DCRDR);
561 if (res != ERROR_OK)
562 return res;
563
564 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
565
566 res = adapter->layout->api->step(adapter->handle);
567
568 if (res != ERROR_OK)
569 return res;
570
571 /* registers are now invalid */
572 register_cache_invalidate(armv7m->arm.core_cache);
573
574 if (breakpoint)
575 cortex_m_set_breakpoint(target, breakpoint);
576
577 adapter_debug_entry(target);
578 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
579
580 LOG_INFO("halted: PC: 0x%08" PRIx32, buf_get_u32(armv7m->arm.pc->value, 0, 32));
581
582 return ERROR_OK;
583 }
584
585 static int adapter_read_memory(struct target *target, target_addr_t address,
586 uint32_t size, uint32_t count,
587 uint8_t *buffer)
588 {
589 struct hl_interface_s *adapter = target_to_adapter(target);
590
591 if (!count || !buffer)
592 return ERROR_COMMAND_SYNTAX_ERROR;
593
594 LOG_DEBUG("%s " TARGET_ADDR_FMT " %" PRIu32 " %" PRIu32,
595 __func__, address, size, count);
596
597 return adapter->layout->api->read_mem(adapter->handle, address, size, count, buffer);
598 }
599
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)
603 {
604 struct hl_interface_s *adapter = target_to_adapter(target);
605
606 if (!count || !buffer)
607 return ERROR_COMMAND_SYNTAX_ERROR;
608
609 LOG_DEBUG("%s " TARGET_ADDR_FMT " %" PRIu32 " %" PRIu32,
610 __func__, address, size, count);
611
612 return adapter->layout->api->write_mem(adapter->handle, address, size, count, buffer);
613 }
614
615 static const struct command_registration hla_command_handlers[] = {
616 {
617 .chain = arm_command_handlers,
618 },
619 {
620 .chain = armv7m_trace_command_handlers,
621 },
622 {
623 .chain = rtt_target_command_handlers,
624 },
625 /* START_DEPRECATED_TPIU */
626 {
627 .chain = arm_tpiu_deprecated_command_handlers,
628 },
629 /* END_DEPRECATED_TPIU */
630 COMMAND_REGISTRATION_DONE
631 };
632
633 struct target_type hla_target = {
634 .name = "hla_target",
635
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,
642
643 .poll = adapter_poll,
644 .arch_state = armv7m_arch_state,
645
646 .target_request_data = hl_target_request_data,
647 .assert_reset = hl_assert_reset,
648 .deassert_reset = hl_deassert_reset,
649
650 .halt = adapter_halt,
651 .resume = adapter_resume,
652 .step = adapter_step,
653
654 .get_gdb_arch = arm_get_gdb_arch,
655 .get_gdb_reg_list = armv7m_get_gdb_reg_list,
656
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,
661
662 .run_algorithm = armv7m_run_algorithm,
663 .start_algorithm = armv7m_start_algorithm,
664 .wait_algorithm = armv7m_wait_algorithm,
665
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,
671 };

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)