target/cortex_m,hla_target: rework Cortex-M register handling part 4
[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_semihosting.h"
41 #include "target_request.h"
42
43 #define savedDCRDR  dbgbase  /* FIXME: using target->dbgbase to preserve DCRDR */
44
45 #define ARMV7M_SCS_DCRSR        DCB_DCRSR
46 #define ARMV7M_SCS_DCRDR        DCB_DCRDR
47
48 static inline struct hl_interface_s *target_to_adapter(struct target *target)
49 {
50         return target->tap->priv;
51 }
52
53 static int adapter_load_core_reg_u32(struct target *target,
54                 uint32_t regsel, uint32_t *value)
55 {
56         struct hl_interface_s *adapter = target_to_adapter(target);
57         return adapter->layout->api->read_reg(adapter->handle, regsel, value);
58 }
59
60 static int adapter_store_core_reg_u32(struct target *target,
61                 uint32_t regsel, uint32_t value)
62 {
63         struct hl_interface_s *adapter = target_to_adapter(target);
64         return adapter->layout->api->write_reg(adapter->handle, regsel, value);
65 }
66
67 static int adapter_examine_debug_reason(struct target *target)
68 {
69         if ((target->debug_reason != DBG_REASON_DBGRQ)
70                         && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
71                 target->debug_reason = DBG_REASON_BREAKPOINT;
72         }
73
74         return ERROR_OK;
75 }
76
77 static int hl_dcc_read(struct hl_interface_s *hl_if, uint8_t *value, uint8_t *ctrl)
78 {
79         uint16_t dcrdr;
80         int retval = hl_if->layout->api->read_mem(hl_if->handle,
81                         DCB_DCRDR, 1, sizeof(dcrdr), (uint8_t *)&dcrdr);
82         if (retval == ERROR_OK) {
83             *ctrl = (uint8_t)dcrdr;
84             *value = (uint8_t)(dcrdr >> 8);
85
86             LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
87
88             if (dcrdr & 1) {
89                         /* write ack back to software dcc register
90                          * to signify we have read data */
91                         /* atomically clear just the byte containing the busy bit */
92                         static const uint8_t zero;
93                         retval = hl_if->layout->api->write_mem(hl_if->handle, DCB_DCRDR, 1, 1, &zero);
94                 }
95         }
96         return retval;
97 }
98
99 static int hl_target_request_data(struct target *target,
100         uint32_t size, uint8_t *buffer)
101 {
102         struct hl_interface_s *hl_if = target_to_adapter(target);
103         uint8_t data;
104         uint8_t ctrl;
105         uint32_t i;
106
107         for (i = 0; i < (size * 4); i++) {
108                 int err = hl_dcc_read(hl_if, &data, &ctrl);
109                 if (err != ERROR_OK)
110                         return err;
111
112                 buffer[i] = data;
113         }
114
115         return ERROR_OK;
116 }
117
118 static int hl_handle_target_request(void *priv)
119 {
120         struct target *target = priv;
121         int err;
122
123         if (!target_was_examined(target))
124                 return ERROR_OK;
125         struct hl_interface_s *hl_if = target_to_adapter(target);
126
127         if (!target->dbg_msg_enabled)
128                 return ERROR_OK;
129
130         if (target->state == TARGET_RUNNING) {
131                 uint8_t data;
132                 uint8_t ctrl;
133
134                 err = hl_dcc_read(hl_if, &data, &ctrl);
135                 if (err != ERROR_OK)
136                         return err;
137
138                 /* check if we have data */
139                 if (ctrl & (1 << 0)) {
140                         uint32_t request;
141
142                         /* we assume target is quick enough */
143                         request = data;
144                         err = hl_dcc_read(hl_if, &data, &ctrl);
145                         if (err != ERROR_OK)
146                                 return err;
147
148                         request |= (data << 8);
149                         err = hl_dcc_read(hl_if, &data, &ctrl);
150                         if (err != ERROR_OK)
151                                 return err;
152
153                         request |= (data << 16);
154                         err = hl_dcc_read(hl_if, &data, &ctrl);
155                         if (err != ERROR_OK)
156                                 return err;
157
158                         request |= (data << 24);
159                         target_request(target, request);
160                 }
161         }
162
163         return ERROR_OK;
164 }
165
166 static int adapter_init_arch_info(struct target *target,
167                                        struct cortex_m_common *cortex_m,
168                                        struct jtag_tap *tap)
169 {
170         struct armv7m_common *armv7m;
171
172         LOG_DEBUG("%s", __func__);
173
174         armv7m = &cortex_m->armv7m;
175         armv7m_init_arch_info(target, armv7m);
176
177         armv7m->load_core_reg_u32 = adapter_load_core_reg_u32;
178         armv7m->store_core_reg_u32 = adapter_store_core_reg_u32;
179
180         armv7m->examine_debug_reason = adapter_examine_debug_reason;
181         armv7m->stlink = true;
182
183         target_register_timer_callback(hl_handle_target_request, 1,
184                 TARGET_TIMER_TYPE_PERIODIC, target);
185
186         return ERROR_OK;
187 }
188
189 static int adapter_init_target(struct command_context *cmd_ctx,
190                                     struct target *target)
191 {
192         LOG_DEBUG("%s", __func__);
193
194         armv7m_build_reg_cache(target);
195         arm_semihosting_init(target);
196         return ERROR_OK;
197 }
198
199 static int adapter_target_create(struct target *target,
200                 Jim_Interp *interp)
201 {
202         LOG_DEBUG("%s", __func__);
203         struct adiv5_private_config *pc = target->private_config;
204         if (pc != NULL && pc->ap_num > 0) {
205                 LOG_ERROR("hla_target: invalid parameter -ap-num (> 0)");
206                 return ERROR_COMMAND_SYNTAX_ERROR;
207         }
208
209         struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
210         if (cortex_m == NULL) {
211                 LOG_ERROR("No memory creating target");
212                 return ERROR_FAIL;
213         }
214
215         adapter_init_arch_info(target, cortex_m, target->tap);
216
217         return ERROR_OK;
218 }
219
220 static int adapter_load_context(struct target *target)
221 {
222         struct armv7m_common *armv7m = target_to_armv7m(target);
223         int num_regs = armv7m->arm.core_cache->num_regs;
224
225         for (int i = 0; i < num_regs; i++) {
226
227                 struct reg *r = &armv7m->arm.core_cache->reg_list[i];
228                 if (!r->valid)
229                         armv7m->arm.read_core_reg(target, r, i, ARM_MODE_ANY);
230         }
231
232         return ERROR_OK;
233 }
234
235 static int adapter_debug_entry(struct target *target)
236 {
237         struct hl_interface_s *adapter = target_to_adapter(target);
238         struct armv7m_common *armv7m = target_to_armv7m(target);
239         struct arm *arm = &armv7m->arm;
240         struct reg *r;
241         uint32_t xPSR;
242         int retval;
243
244         /* preserve the DCRDR across halts */
245         retval = target_read_u32(target, DCB_DCRDR, &target->savedDCRDR);
246         if (retval != ERROR_OK)
247                 return retval;
248
249         retval = armv7m->examine_debug_reason(target);
250         if (retval != ERROR_OK)
251                 return retval;
252
253         adapter_load_context(target);
254
255         /* make sure we clear the vector catch bit */
256         adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA);
257
258         r = arm->cpsr;
259         xPSR = buf_get_u32(r->value, 0, 32);
260
261         /* Are we in an exception handler */
262         if (xPSR & 0x1FF) {
263                 armv7m->exception_number = (xPSR & 0x1FF);
264
265                 arm->core_mode = ARM_MODE_HANDLER;
266                 arm->map = armv7m_msp_reg_map;
267         } else {
268                 unsigned control = buf_get_u32(arm->core_cache
269                                 ->reg_list[ARMV7M_CONTROL].value, 0, 3);
270
271                 /* is this thread privileged? */
272                 arm->core_mode = control & 1
273                                 ? ARM_MODE_USER_THREAD
274                                 : ARM_MODE_THREAD;
275
276                 /* which stack is it using? */
277                 if (control & 2)
278                         arm->map = armv7m_psp_reg_map;
279                 else
280                         arm->map = armv7m_msp_reg_map;
281
282                 armv7m->exception_number = 0;
283         }
284
285         LOG_DEBUG("entered debug state in core mode: %s at PC 0x%08" PRIx32 ", target->state: %s",
286                 arm_mode_name(arm->core_mode),
287                 buf_get_u32(arm->pc->value, 0, 32),
288                 target_state_name(target));
289
290         return retval;
291 }
292
293 static int adapter_poll(struct target *target)
294 {
295         enum target_state state;
296         struct hl_interface_s *adapter = target_to_adapter(target);
297         struct armv7m_common *armv7m = target_to_armv7m(target);
298         enum target_state prev_target_state = target->state;
299
300         state = adapter->layout->api->state(adapter->handle);
301
302         if (state == TARGET_UNKNOWN) {
303                 LOG_ERROR("jtag status contains invalid mode value - communication failure");
304                 return ERROR_TARGET_FAILURE;
305         }
306
307         if (prev_target_state == state)
308                 return ERROR_OK;
309
310         if (prev_target_state == TARGET_DEBUG_RUNNING && state == TARGET_RUNNING)
311                 return ERROR_OK;
312
313         target->state = state;
314
315         if (state == TARGET_HALTED) {
316
317                 int retval = adapter_debug_entry(target);
318                 if (retval != ERROR_OK)
319                         return retval;
320
321                 if (prev_target_state == TARGET_DEBUG_RUNNING) {
322                         target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
323                 } else {
324                         if (arm_semihosting(target, &retval) != 0)
325                                 return retval;
326
327                         target_call_event_callbacks(target, TARGET_EVENT_HALTED);
328                 }
329
330                 LOG_DEBUG("halted: PC: 0x%08" PRIx32, buf_get_u32(armv7m->arm.pc->value, 0, 32));
331         }
332
333         return ERROR_OK;
334 }
335
336 static int hl_assert_reset(struct target *target)
337 {
338         int res = ERROR_OK;
339         struct hl_interface_s *adapter = target_to_adapter(target);
340         struct armv7m_common *armv7m = target_to_armv7m(target);
341         bool use_srst_fallback = true;
342
343         LOG_DEBUG("%s", __func__);
344
345         enum reset_types jtag_reset_config = jtag_get_reset_config();
346
347         bool srst_asserted = false;
348
349         if ((jtag_reset_config & RESET_HAS_SRST) &&
350             (jtag_reset_config & RESET_SRST_NO_GATING)) {
351                 res = adapter_assert_reset();
352                 srst_asserted = true;
353         }
354
355         adapter->layout->api->write_debug_reg(adapter->handle, DCB_DHCSR, DBGKEY|C_DEBUGEN);
356
357         /* only set vector catch if halt is requested */
358         if (target->reset_halt)
359                 adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA|VC_CORERESET);
360         else
361                 adapter->layout->api->write_debug_reg(adapter->handle, DCB_DEMCR, TRCENA);
362
363         if (jtag_reset_config & RESET_HAS_SRST) {
364                 if (!srst_asserted) {
365                         res = adapter_assert_reset();
366                 }
367                 if (res == ERROR_COMMAND_NOTFOUND)
368                         LOG_ERROR("Hardware srst not supported, falling back to software reset");
369                 else if (res == ERROR_OK) {
370                         /* hardware srst supported */
371                         use_srst_fallback = false;
372                 }
373         }
374
375         if (use_srst_fallback) {
376                 /* stlink v1 api does not support hardware srst, so we use a software reset fallback */
377                 adapter->layout->api->write_debug_reg(adapter->handle, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
378         }
379
380         res = adapter->layout->api->reset(adapter->handle);
381
382         if (res != ERROR_OK)
383                 return res;
384
385         /* registers are now invalid */
386         register_cache_invalidate(armv7m->arm.core_cache);
387
388         if (target->reset_halt) {
389                 target->state = TARGET_RESET;
390                 target->debug_reason = DBG_REASON_DBGRQ;
391         } else {
392                 target->state = TARGET_HALTED;
393         }
394
395         return ERROR_OK;
396 }
397
398 static int hl_deassert_reset(struct target *target)
399 {
400         enum reset_types jtag_reset_config = jtag_get_reset_config();
401
402         LOG_DEBUG("%s", __func__);
403
404         if (jtag_reset_config & RESET_HAS_SRST)
405                 adapter_deassert_reset();
406
407         target->savedDCRDR = 0;  /* clear both DCC busy bits on initial resume */
408
409         return target->reset_halt ? ERROR_OK : target_resume(target, 1, 0, 0, 0);
410 }
411
412 static int adapter_halt(struct target *target)
413 {
414         int res;
415         struct hl_interface_s *adapter = target_to_adapter(target);
416
417         LOG_DEBUG("%s", __func__);
418
419         if (target->state == TARGET_HALTED) {
420                 LOG_DEBUG("target was already halted");
421                 return ERROR_OK;
422         }
423
424         if (target->state == TARGET_UNKNOWN)
425                 LOG_WARNING("target was in unknown state when halt was requested");
426
427         res = adapter->layout->api->halt(adapter->handle);
428
429         if (res != ERROR_OK)
430                 return res;
431
432         target->debug_reason = DBG_REASON_DBGRQ;
433
434         return ERROR_OK;
435 }
436
437 static int adapter_resume(struct target *target, int current,
438                 target_addr_t address, int handle_breakpoints,
439                 int debug_execution)
440 {
441         int res;
442         struct hl_interface_s *adapter = target_to_adapter(target);
443         struct armv7m_common *armv7m = target_to_armv7m(target);
444         uint32_t resume_pc;
445         struct breakpoint *breakpoint = NULL;
446         struct reg *pc;
447
448         LOG_DEBUG("%s %d " TARGET_ADDR_FMT " %d %d", __func__, current,
449                         address, handle_breakpoints, debug_execution);
450
451         if (target->state != TARGET_HALTED) {
452                 LOG_WARNING("target not halted");
453                 return ERROR_TARGET_NOT_HALTED;
454         }
455
456         if (!debug_execution) {
457                 target_free_all_working_areas(target);
458                 cortex_m_enable_breakpoints(target);
459                 cortex_m_enable_watchpoints(target);
460         }
461
462         pc = armv7m->arm.pc;
463         if (!current) {
464                 buf_set_u32(pc->value, 0, 32, address);
465                 pc->dirty = true;
466                 pc->valid = true;
467         }
468
469         if (!breakpoint_find(target, buf_get_u32(pc->value, 0, 32))
470                         && !debug_execution) {
471                 armv7m_maybe_skip_bkpt_inst(target, NULL);
472         }
473
474         resume_pc = buf_get_u32(pc->value, 0, 32);
475
476         /* write any user vector flags */
477         res = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr);
478         if (res != ERROR_OK)
479                 return res;
480
481         armv7m_restore_context(target);
482
483         /* restore savedDCRDR */
484         res = target_write_u32(target, DCB_DCRDR, target->savedDCRDR);
485         if (res != ERROR_OK)
486                 return res;
487
488         /* registers are now invalid */
489         register_cache_invalidate(armv7m->arm.core_cache);
490
491         /* the front-end may request us not to handle breakpoints */
492         if (handle_breakpoints) {
493                 /* Single step past breakpoint at current address */
494                 breakpoint = breakpoint_find(target, resume_pc);
495                 if (breakpoint) {
496                         LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")",
497                                         breakpoint->address,
498                                         breakpoint->unique_id);
499                         cortex_m_unset_breakpoint(target, breakpoint);
500
501                         res = adapter->layout->api->step(adapter->handle);
502
503                         if (res != ERROR_OK)
504                                 return res;
505
506                         cortex_m_set_breakpoint(target, breakpoint);
507                 }
508         }
509
510         res = adapter->layout->api->run(adapter->handle);
511
512         if (res != ERROR_OK)
513                 return res;
514
515         target->debug_reason = DBG_REASON_NOTHALTED;
516
517         if (!debug_execution) {
518                 target->state = TARGET_RUNNING;
519                 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
520         } else {
521                 target->state = TARGET_DEBUG_RUNNING;
522                 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
523         }
524
525         return ERROR_OK;
526 }
527
528 static int adapter_step(struct target *target, int current,
529                 target_addr_t address, int handle_breakpoints)
530 {
531         int res;
532         struct hl_interface_s *adapter = target_to_adapter(target);
533         struct armv7m_common *armv7m = target_to_armv7m(target);
534         struct breakpoint *breakpoint = NULL;
535         struct reg *pc = armv7m->arm.pc;
536         bool bkpt_inst_found = false;
537
538         LOG_DEBUG("%s", __func__);
539
540         if (target->state != TARGET_HALTED) {
541                 LOG_WARNING("target not halted");
542                 return ERROR_TARGET_NOT_HALTED;
543         }
544
545         if (!current) {
546                 buf_set_u32(pc->value, 0, 32, address);
547                 pc->dirty = true;
548                 pc->valid = true;
549         }
550
551         uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
552
553         /* the front-end may request us not to handle breakpoints */
554         if (handle_breakpoints) {
555                 breakpoint = breakpoint_find(target, pc_value);
556                 if (breakpoint)
557                         cortex_m_unset_breakpoint(target, breakpoint);
558         }
559
560         armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
561
562         target->debug_reason = DBG_REASON_SINGLESTEP;
563
564         armv7m_restore_context(target);
565
566         /* restore savedDCRDR */
567         res = target_write_u32(target, DCB_DCRDR, target->savedDCRDR);
568         if (res != ERROR_OK)
569                 return res;
570
571         target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
572
573         res = adapter->layout->api->step(adapter->handle);
574
575         if (res != ERROR_OK)
576                 return res;
577
578         /* registers are now invalid */
579         register_cache_invalidate(armv7m->arm.core_cache);
580
581         if (breakpoint)
582                 cortex_m_set_breakpoint(target, breakpoint);
583
584         adapter_debug_entry(target);
585         target_call_event_callbacks(target, TARGET_EVENT_HALTED);
586
587         LOG_INFO("halted: PC: 0x%08" PRIx32, buf_get_u32(armv7m->arm.pc->value, 0, 32));
588
589         return ERROR_OK;
590 }
591
592 static int adapter_read_memory(struct target *target, target_addr_t address,
593                 uint32_t size, uint32_t count,
594                 uint8_t *buffer)
595 {
596         struct hl_interface_s *adapter = target_to_adapter(target);
597
598         if (!count || !buffer)
599                 return ERROR_COMMAND_SYNTAX_ERROR;
600
601         LOG_DEBUG("%s " TARGET_ADDR_FMT " %" PRIu32 " %" PRIu32,
602                           __func__, address, size, count);
603
604         return adapter->layout->api->read_mem(adapter->handle, address, size, count, buffer);
605 }
606
607 static int adapter_write_memory(struct target *target, target_addr_t address,
608                 uint32_t size, uint32_t count,
609                 const uint8_t *buffer)
610 {
611         struct hl_interface_s *adapter = target_to_adapter(target);
612
613         if (!count || !buffer)
614                 return ERROR_COMMAND_SYNTAX_ERROR;
615
616         LOG_DEBUG("%s " TARGET_ADDR_FMT " %" PRIu32 " %" PRIu32,
617                           __func__, address, size, count);
618
619         return adapter->layout->api->write_mem(adapter->handle, address, size, count, buffer);
620 }
621
622 static const struct command_registration adapter_command_handlers[] = {
623         {
624                 .chain = arm_command_handlers,
625         },
626         {
627                 .chain = armv7m_trace_command_handlers,
628         },
629         COMMAND_REGISTRATION_DONE
630 };
631
632 struct target_type hla_target = {
633         .name = "hla_target",
634         .deprecated_name = "stm32_stlink",
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 = adapter_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 };