target/cortex_m: workaround Cortex-M7 erratum 3092511
[openocd.git] / src / target / avr32_ap7k.c
blobbbbf236592c012c736c55ec250aac81bb8e1f3a1
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
5 * Based on mips_m4k code: *
6 * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
7 * Copyright (C) 2008 by David T.L. Wong *
8 ***************************************************************************/
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
14 #include "jtag/jtag.h"
15 #include "register.h"
16 #include "algorithm.h"
17 #include "target.h"
18 #include "breakpoints.h"
19 #include "target_type.h"
20 #include "avr32_jtag.h"
21 #include "avr32_mem.h"
22 #include "avr32_regs.h"
23 #include "avr32_ap7k.h"
25 static const char * const avr32_core_reg_list[] = {
26 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
27 "r9", "r10", "r11", "r12", "sp", "lr", "pc", "sr"
30 static const struct avr32_core_reg
31 avr32_core_reg_list_arch_info[AVR32NUMCOREREGS] = {
32 {0, NULL, NULL},
33 {1, NULL, NULL},
34 {2, NULL, NULL},
35 {3, NULL, NULL},
36 {4, NULL, NULL},
37 {5, NULL, NULL},
38 {6, NULL, NULL},
39 {7, NULL, NULL},
40 {8, NULL, NULL},
41 {9, NULL, NULL},
42 {10, NULL, NULL},
43 {11, NULL, NULL},
44 {12, NULL, NULL},
45 {13, NULL, NULL},
46 {14, NULL, NULL},
47 {15, NULL, NULL},
48 {16, NULL, NULL},
52 static int avr32_read_core_reg(struct target *target, int num);
53 static int avr32_write_core_reg(struct target *target, int num);
55 static int avr32_ap7k_save_context(struct target *target)
57 int retval, i;
58 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
60 retval = avr32_jtag_read_regs(&ap7k->jtag, ap7k->core_regs);
61 if (retval != ERROR_OK)
62 return retval;
64 for (i = 0; i < AVR32NUMCOREREGS; i++) {
65 if (!ap7k->core_cache->reg_list[i].valid)
66 avr32_read_core_reg(target, i);
69 return ERROR_OK;
72 static int avr32_ap7k_restore_context(struct target *target)
74 int i;
76 /* get pointers to arch-specific information */
77 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
79 for (i = 0; i < AVR32NUMCOREREGS; i++) {
80 if (ap7k->core_cache->reg_list[i].dirty)
81 avr32_write_core_reg(target, i);
84 /* write core regs */
85 avr32_jtag_write_regs(&ap7k->jtag, ap7k->core_regs);
87 return ERROR_OK;
90 static int avr32_read_core_reg(struct target *target, int num)
92 uint32_t reg_value;
94 /* get pointers to arch-specific information */
95 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
97 if ((num < 0) || (num >= AVR32NUMCOREREGS))
98 return ERROR_COMMAND_SYNTAX_ERROR;
100 reg_value = ap7k->core_regs[num];
101 buf_set_u32(ap7k->core_cache->reg_list[num].value, 0, 32, reg_value);
102 ap7k->core_cache->reg_list[num].valid = true;
103 ap7k->core_cache->reg_list[num].dirty = false;
105 return ERROR_OK;
108 static int avr32_write_core_reg(struct target *target, int num)
110 uint32_t reg_value;
112 /* get pointers to arch-specific information */
113 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
115 if ((num < 0) || (num >= AVR32NUMCOREREGS))
116 return ERROR_COMMAND_SYNTAX_ERROR;
118 reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32);
119 ap7k->core_regs[num] = reg_value;
120 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
121 ap7k->core_cache->reg_list[num].valid = true;
122 ap7k->core_cache->reg_list[num].dirty = false;
124 return ERROR_OK;
127 static int avr32_get_core_reg(struct reg *reg)
129 int retval;
130 struct avr32_core_reg *avr32_reg = reg->arch_info;
131 struct target *target = avr32_reg->target;
133 if (target->state != TARGET_HALTED)
134 return ERROR_TARGET_NOT_HALTED;
136 retval = avr32_read_core_reg(target, avr32_reg->num);
138 return retval;
141 static int avr32_set_core_reg(struct reg *reg, uint8_t *buf)
143 struct avr32_core_reg *avr32_reg = reg->arch_info;
144 struct target *target = avr32_reg->target;
145 uint32_t value = buf_get_u32(buf, 0, 32);
147 if (target->state != TARGET_HALTED)
148 return ERROR_TARGET_NOT_HALTED;
150 buf_set_u32(reg->value, 0, 32, value);
151 reg->dirty = true;
152 reg->valid = true;
154 return ERROR_OK;
157 static const struct reg_arch_type avr32_reg_type = {
158 .get = avr32_get_core_reg,
159 .set = avr32_set_core_reg,
162 static struct reg_cache *avr32_build_reg_cache(struct target *target)
164 int num_regs = AVR32NUMCOREREGS;
165 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
166 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
167 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
168 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
169 struct avr32_core_reg *arch_info =
170 malloc(sizeof(struct avr32_core_reg) * num_regs);
171 int i;
173 /* Build the process context cache */
174 cache->name = "avr32 registers";
175 cache->next = NULL;
176 cache->reg_list = reg_list;
177 cache->num_regs = num_regs;
178 (*cache_p) = cache;
179 ap7k->core_cache = cache;
181 for (i = 0; i < num_regs; i++) {
182 arch_info[i] = avr32_core_reg_list_arch_info[i];
183 arch_info[i].target = target;
184 arch_info[i].avr32_common = ap7k;
185 reg_list[i].name = avr32_core_reg_list[i];
186 reg_list[i].size = 32;
187 reg_list[i].value = calloc(1, 4);
188 reg_list[i].dirty = false;
189 reg_list[i].valid = false;
190 reg_list[i].type = &avr32_reg_type;
191 reg_list[i].arch_info = &arch_info[i];
194 return cache;
197 static int avr32_ap7k_debug_entry(struct target *target)
200 uint32_t dpc, dinst;
201 int retval;
202 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
204 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DPC, &dpc);
205 if (retval != ERROR_OK)
206 return retval;
208 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DINST, &dinst);
209 if (retval != ERROR_OK)
210 return retval;
212 ap7k->jtag.dpc = dpc;
214 avr32_ap7k_save_context(target);
216 return ERROR_OK;
220 static int avr32_ap7k_poll(struct target *target)
222 uint32_t ds;
223 int retval;
224 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
226 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
227 if (retval != ERROR_OK)
228 return retval;
230 /* check for processor halted */
231 if (ds & OCDREG_DS_DBA) {
232 if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) {
233 target->state = TARGET_HALTED;
235 retval = avr32_ap7k_debug_entry(target);
236 if (retval != ERROR_OK)
237 return retval;
239 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
240 } else if (target->state == TARGET_DEBUG_RUNNING) {
241 target->state = TARGET_HALTED;
243 retval = avr32_ap7k_debug_entry(target);
244 if (retval != ERROR_OK)
245 return retval;
247 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
249 } else
250 target->state = TARGET_RUNNING;
253 return ERROR_OK;
256 static int avr32_ap7k_halt(struct target *target)
258 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
260 LOG_DEBUG("target->state: %s",
261 target_state_name(target));
263 if (target->state == TARGET_HALTED) {
264 LOG_DEBUG("target was already halted");
265 return ERROR_OK;
268 if (target->state == TARGET_UNKNOWN)
269 LOG_WARNING("target was in unknown state when halt was requested");
271 if (target->state == TARGET_RESET) {
272 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
273 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
274 return ERROR_TARGET_FAILURE;
275 } else {
276 target->debug_reason = DBG_REASON_DBGRQ;
278 return ERROR_OK;
283 avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBR);
284 target->debug_reason = DBG_REASON_DBGRQ;
286 return ERROR_OK;
289 static int avr32_ap7k_assert_reset(struct target *target)
291 LOG_ERROR("%s: implement me", __func__);
293 return ERROR_OK;
296 static int avr32_ap7k_deassert_reset(struct target *target)
298 LOG_ERROR("%s: implement me", __func__);
300 return ERROR_OK;
303 static int avr32_ap7k_resume(struct target *target, int current,
304 target_addr_t address, int handle_breakpoints, int debug_execution)
306 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
307 struct breakpoint *breakpoint = NULL;
308 uint32_t resume_pc;
309 int retval;
311 if (target->state != TARGET_HALTED) {
312 LOG_TARGET_ERROR(target, "not halted");
313 return ERROR_TARGET_NOT_HALTED;
316 if (!debug_execution) {
317 target_free_all_working_areas(target);
319 avr32_ap7k_enable_breakpoints(target);
320 avr32_ap7k_enable_watchpoints(target);
324 /* current = 1: continue on current pc, otherwise continue at <address> */
325 if (!current) {
326 #if 0
327 if (retval != ERROR_OK)
328 return retval;
329 #endif
332 resume_pc = buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32);
333 avr32_ap7k_restore_context(target);
335 /* the front-end may request us not to handle breakpoints */
336 if (handle_breakpoints) {
337 /* Single step past breakpoint at current address */
338 breakpoint = breakpoint_find(target, resume_pc);
339 if (breakpoint) {
340 LOG_DEBUG("unset breakpoint at 0x%8.8" TARGET_PRIxADDR "", breakpoint->address);
341 #if 0
342 avr32_ap7k_unset_breakpoint(target, breakpoint);
343 avr32_ap7k_single_step_core(target);
344 avr32_ap7k_set_breakpoint(target, breakpoint);
345 #endif
349 #if 0
350 /* enable interrupts if we are running */
351 avr32_ap7k_enable_interrupts(target, !debug_execution);
353 /* exit debug mode */
354 mips_ejtag_exit_debug(ejtag_info);
355 #endif
358 retval = avr32_ocd_clearbits(&ap7k->jtag, AVR32_OCDREG_DC,
359 OCDREG_DC_DBR);
360 if (retval != ERROR_OK)
361 return retval;
363 retval = avr32_jtag_exec(&ap7k->jtag, RETD);
364 if (retval != ERROR_OK)
365 return retval;
367 target->debug_reason = DBG_REASON_NOTHALTED;
369 /* registers are now invalid */
370 register_cache_invalidate(ap7k->core_cache);
372 if (!debug_execution) {
373 target->state = TARGET_RUNNING;
374 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
375 LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
376 } else {
377 target->state = TARGET_DEBUG_RUNNING;
378 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
379 LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
382 return ERROR_OK;
385 static int avr32_ap7k_step(struct target *target, int current,
386 target_addr_t address, int handle_breakpoints)
388 LOG_ERROR("%s: implement me", __func__);
390 return ERROR_OK;
393 static int avr32_ap7k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
395 LOG_ERROR("%s: implement me", __func__);
397 return ERROR_OK;
400 static int avr32_ap7k_remove_breakpoint(struct target *target,
401 struct breakpoint *breakpoint)
403 LOG_ERROR("%s: implement me", __func__);
405 return ERROR_OK;
408 static int avr32_ap7k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
410 LOG_ERROR("%s: implement me", __func__);
412 return ERROR_OK;
415 static int avr32_ap7k_remove_watchpoint(struct target *target,
416 struct watchpoint *watchpoint)
418 LOG_ERROR("%s: implement me", __func__);
420 return ERROR_OK;
423 static int avr32_ap7k_read_memory(struct target *target, target_addr_t address,
424 uint32_t size, uint32_t count, uint8_t *buffer)
426 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
428 LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
429 address,
430 size,
431 count);
433 if (target->state != TARGET_HALTED) {
434 LOG_TARGET_ERROR(target, "not halted");
435 return ERROR_TARGET_NOT_HALTED;
438 /* sanitize arguments */
439 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
440 return ERROR_COMMAND_SYNTAX_ERROR;
442 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
443 return ERROR_TARGET_UNALIGNED_ACCESS;
445 switch (size) {
446 case 4:
447 return avr32_jtag_read_memory32(&ap7k->jtag, address, count,
448 (uint32_t *)(void *)buffer);
449 break;
450 case 2:
451 return avr32_jtag_read_memory16(&ap7k->jtag, address, count,
452 (uint16_t *)(void *)buffer);
453 break;
454 case 1:
455 return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
456 default:
457 break;
460 return ERROR_OK;
463 static int avr32_ap7k_write_memory(struct target *target, target_addr_t address,
464 uint32_t size, uint32_t count, const uint8_t *buffer)
466 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
468 LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
469 address,
470 size,
471 count);
473 if (target->state != TARGET_HALTED) {
474 LOG_TARGET_ERROR(target, "not halted");
475 return ERROR_TARGET_NOT_HALTED;
478 /* sanitize arguments */
479 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
480 return ERROR_COMMAND_SYNTAX_ERROR;
482 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
483 return ERROR_TARGET_UNALIGNED_ACCESS;
485 switch (size) {
486 case 4:
487 return avr32_jtag_write_memory32(&ap7k->jtag, address, count,
488 (uint32_t *)(void *)buffer);
489 break;
490 case 2:
491 return avr32_jtag_write_memory16(&ap7k->jtag, address, count,
492 (uint16_t *)(void *)buffer);
493 break;
494 case 1:
495 return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
496 default:
497 break;
500 return ERROR_OK;
503 static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
504 struct target *target)
506 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
508 ap7k->jtag.tap = target->tap;
509 avr32_build_reg_cache(target);
510 return ERROR_OK;
513 static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
515 struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
516 avr32_ap7k_common));
518 ap7k->common_magic = AP7K_COMMON_MAGIC;
519 target->arch_info = ap7k;
521 return ERROR_OK;
524 static int avr32_ap7k_examine(struct target *target)
526 uint32_t devid, ds;
527 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
529 if (!target_was_examined(target)) {
530 target_set_examined(target);
531 avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid);
532 LOG_INFO("device id: %08" PRIx32, devid);
533 avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBE);
534 avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
536 /* check for processor halted */
537 if (ds & OCDREG_DS_DBA) {
538 LOG_INFO("target is halted");
539 target->state = TARGET_HALTED;
540 } else
541 target->state = TARGET_RUNNING;
544 return ERROR_OK;
547 static int avr32_ap7k_arch_state(struct target *target)
549 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
551 LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
552 debug_reason_name(target), ap7k->jtag.dpc);
554 return ERROR_OK;
557 static int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
558 int *reg_list_size, enum target_register_class reg_class)
560 #if 0
561 /* get pointers to arch-specific information */
562 int i;
564 /* include floating point registers */
565 *reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS;
566 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
568 for (i = 0; i < AVR32NUMCOREREGS; i++)
569 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
571 /* add dummy floating points regs */
572 for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
573 (*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
575 #endif
577 LOG_ERROR("%s: implement me", __func__);
578 return ERROR_FAIL;
581 struct target_type avr32_ap7k_target = {
582 .name = "avr32_ap7k",
584 .poll = avr32_ap7k_poll,
585 .arch_state = avr32_ap7k_arch_state,
587 .halt = avr32_ap7k_halt,
588 .resume = avr32_ap7k_resume,
589 .step = avr32_ap7k_step,
591 .assert_reset = avr32_ap7k_assert_reset,
592 .deassert_reset = avr32_ap7k_deassert_reset,
594 .get_gdb_reg_list = avr32_ap7k_get_gdb_reg_list,
596 .read_memory = avr32_ap7k_read_memory,
597 .write_memory = avr32_ap7k_write_memory,
598 /* .checksum_memory = avr32_ap7k_checksum_memory, */
599 /* .blank_check_memory = avr32_ap7k_blank_check_memory, */
601 /* .run_algorithm = avr32_ap7k_run_algorithm, */
603 .add_breakpoint = avr32_ap7k_add_breakpoint,
604 .remove_breakpoint = avr32_ap7k_remove_breakpoint,
605 .add_watchpoint = avr32_ap7k_add_watchpoint,
606 .remove_watchpoint = avr32_ap7k_remove_watchpoint,
608 .target_create = avr32_ap7k_target_create,
609 .init_target = avr32_ap7k_init_target,
610 .examine = avr32_ap7k_examine,