openocd: remove CamelCase symbols *xPSR*
[fw/openocd] / 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 };