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