target/riscv-011: Fix memory leak in handle_halt_routine()
[openocd.git] / src / target / avr32_ap7k.c
1 /***************************************************************************
2 * Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com> *
3 * Based on mips_m4k code: *
4 * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "jtag/jtag.h"
26 #include "register.h"
27 #include "algorithm.h"
28 #include "target.h"
29 #include "breakpoints.h"
30 #include "target_type.h"
31 #include "avr32_jtag.h"
32 #include "avr32_mem.h"
33 #include "avr32_regs.h"
34 #include "avr32_ap7k.h"
35
36 static const char * const avr32_core_reg_list[] = {
37 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
38 "r9", "r10", "r11", "r12", "sp", "lr", "pc", "sr"
39 };
40
41 static const struct avr32_core_reg
42 avr32_core_reg_list_arch_info[AVR32NUMCOREREGS] = {
43 {0, NULL, NULL},
44 {1, NULL, NULL},
45 {2, NULL, NULL},
46 {3, NULL, NULL},
47 {4, NULL, NULL},
48 {5, NULL, NULL},
49 {6, NULL, NULL},
50 {7, NULL, NULL},
51 {8, NULL, NULL},
52 {9, NULL, NULL},
53 {10, NULL, NULL},
54 {11, NULL, NULL},
55 {12, NULL, NULL},
56 {13, NULL, NULL},
57 {14, NULL, NULL},
58 {15, NULL, NULL},
59 {16, NULL, NULL},
60 };
61
62
63 static int avr32_read_core_reg(struct target *target, int num);
64 static int avr32_write_core_reg(struct target *target, int num);
65
66 int avr32_ap7k_save_context(struct target *target)
67 {
68 int retval, i;
69 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
70
71 retval = avr32_jtag_read_regs(&ap7k->jtag, ap7k->core_regs);
72 if (retval != ERROR_OK)
73 return retval;
74
75 for (i = 0; i < AVR32NUMCOREREGS; i++) {
76 if (!ap7k->core_cache->reg_list[i].valid)
77 avr32_read_core_reg(target, i);
78 }
79
80 return ERROR_OK;
81 }
82
83 int avr32_ap7k_restore_context(struct target *target)
84 {
85 int i;
86
87 /* get pointers to arch-specific information */
88 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
89
90 for (i = 0; i < AVR32NUMCOREREGS; i++) {
91 if (ap7k->core_cache->reg_list[i].dirty)
92 avr32_write_core_reg(target, i);
93 }
94
95 /* write core regs */
96 avr32_jtag_write_regs(&ap7k->jtag, ap7k->core_regs);
97
98 return ERROR_OK;
99 }
100
101 static int avr32_read_core_reg(struct target *target, int num)
102 {
103 uint32_t reg_value;
104
105 /* get pointers to arch-specific information */
106 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
107
108 if ((num < 0) || (num >= AVR32NUMCOREREGS))
109 return ERROR_COMMAND_SYNTAX_ERROR;
110
111 reg_value = ap7k->core_regs[num];
112 buf_set_u32(ap7k->core_cache->reg_list[num].value, 0, 32, reg_value);
113 ap7k->core_cache->reg_list[num].valid = 1;
114 ap7k->core_cache->reg_list[num].dirty = 0;
115
116 return ERROR_OK;
117 }
118
119 static int avr32_write_core_reg(struct target *target, int num)
120 {
121 uint32_t reg_value;
122
123 /* get pointers to arch-specific information */
124 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
125
126 if ((num < 0) || (num >= AVR32NUMCOREREGS))
127 return ERROR_COMMAND_SYNTAX_ERROR;
128
129 reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32);
130 ap7k->core_regs[num] = reg_value;
131 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
132 ap7k->core_cache->reg_list[num].valid = 1;
133 ap7k->core_cache->reg_list[num].dirty = 0;
134
135 return ERROR_OK;
136 }
137
138 static int avr32_get_core_reg(struct reg *reg)
139 {
140 int retval;
141 struct avr32_core_reg *avr32_reg = reg->arch_info;
142 struct target *target = avr32_reg->target;
143
144 if (target->state != TARGET_HALTED)
145 return ERROR_TARGET_NOT_HALTED;
146
147 retval = avr32_read_core_reg(target, avr32_reg->num);
148
149 return retval;
150 }
151
152 static int avr32_set_core_reg(struct reg *reg, uint8_t *buf)
153 {
154 struct avr32_core_reg *avr32_reg = reg->arch_info;
155 struct target *target = avr32_reg->target;
156 uint32_t value = buf_get_u32(buf, 0, 32);
157
158 if (target->state != TARGET_HALTED)
159 return ERROR_TARGET_NOT_HALTED;
160
161 buf_set_u32(reg->value, 0, 32, value);
162 reg->dirty = 1;
163 reg->valid = 1;
164
165 return ERROR_OK;
166 }
167
168 static const struct reg_arch_type avr32_reg_type = {
169 .get = avr32_get_core_reg,
170 .set = avr32_set_core_reg,
171 };
172
173 static struct reg_cache *avr32_build_reg_cache(struct target *target)
174 {
175 int num_regs = AVR32NUMCOREREGS;
176 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
177 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
178 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
179 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
180 struct avr32_core_reg *arch_info =
181 malloc(sizeof(struct avr32_core_reg) * num_regs);
182 int i;
183
184 /* Build the process context cache */
185 cache->name = "avr32 registers";
186 cache->next = NULL;
187 cache->reg_list = reg_list;
188 cache->num_regs = num_regs;
189 (*cache_p) = cache;
190 ap7k->core_cache = cache;
191
192 for (i = 0; i < num_regs; i++) {
193 arch_info[i] = avr32_core_reg_list_arch_info[i];
194 arch_info[i].target = target;
195 arch_info[i].avr32_common = ap7k;
196 reg_list[i].name = avr32_core_reg_list[i];
197 reg_list[i].size = 32;
198 reg_list[i].value = calloc(1, 4);
199 reg_list[i].dirty = 0;
200 reg_list[i].valid = 0;
201 reg_list[i].type = &avr32_reg_type;
202 reg_list[i].arch_info = &arch_info[i];
203 }
204
205 return cache;
206 }
207
208 static int avr32_ap7k_debug_entry(struct target *target)
209 {
210
211 uint32_t dpc, dinst;
212 int retval;
213 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
214
215 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DPC, &dpc);
216 if (retval != ERROR_OK)
217 return retval;
218
219 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DINST, &dinst);
220 if (retval != ERROR_OK)
221 return retval;
222
223 ap7k->jtag.dpc = dpc;
224
225 avr32_ap7k_save_context(target);
226
227 return ERROR_OK;
228 }
229
230
231 static int avr32_ap7k_poll(struct target *target)
232 {
233 uint32_t ds;
234 int retval;
235 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
236
237 retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
238 if (retval != ERROR_OK)
239 return retval;
240
241 /* check for processor halted */
242 if (ds & OCDREG_DS_DBA) {
243 if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET)) {
244 target->state = TARGET_HALTED;
245
246 retval = avr32_ap7k_debug_entry(target);
247 if (retval != ERROR_OK)
248 return retval;
249
250 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
251 } else if (target->state == TARGET_DEBUG_RUNNING) {
252 target->state = TARGET_HALTED;
253
254 retval = avr32_ap7k_debug_entry(target);
255 if (retval != ERROR_OK)
256 return retval;
257
258 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
259 }
260 } else
261 target->state = TARGET_RUNNING;
262
263
264 return ERROR_OK;
265 }
266
267 static int avr32_ap7k_halt(struct target *target)
268 {
269 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
270
271 LOG_DEBUG("target->state: %s",
272 target_state_name(target));
273
274 if (target->state == TARGET_HALTED) {
275 LOG_DEBUG("target was already halted");
276 return ERROR_OK;
277 }
278
279 if (target->state == TARGET_UNKNOWN)
280 LOG_WARNING("target was in unknown state when halt was requested");
281
282 if (target->state == TARGET_RESET) {
283 if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
284 LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
285 return ERROR_TARGET_FAILURE;
286 } else {
287 target->debug_reason = DBG_REASON_DBGRQ;
288
289 return ERROR_OK;
290 }
291 }
292
293
294 avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBR);
295 target->debug_reason = DBG_REASON_DBGRQ;
296
297 return ERROR_OK;
298 }
299
300 static int avr32_ap7k_assert_reset(struct target *target)
301 {
302 LOG_ERROR("%s: implement me", __func__);
303
304 return ERROR_OK;
305 }
306
307 static int avr32_ap7k_deassert_reset(struct target *target)
308 {
309 LOG_ERROR("%s: implement me", __func__);
310
311 return ERROR_OK;
312 }
313
314 static int avr32_ap7k_resume(struct target *target, int current,
315 target_addr_t address, int handle_breakpoints, int debug_execution)
316 {
317 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
318 struct breakpoint *breakpoint = NULL;
319 uint32_t resume_pc;
320 int retval;
321
322 if (target->state != TARGET_HALTED) {
323 LOG_WARNING("target not halted");
324 return ERROR_TARGET_NOT_HALTED;
325 }
326
327 if (!debug_execution) {
328 target_free_all_working_areas(target);
329 /*
330 avr32_ap7k_enable_breakpoints(target);
331 avr32_ap7k_enable_watchpoints(target);
332 */
333 }
334
335 /* current = 1: continue on current pc, otherwise continue at <address> */
336 if (!current) {
337 #if 0
338 if (retval != ERROR_OK)
339 return retval;
340 #endif
341 }
342
343 resume_pc = buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32);
344 avr32_ap7k_restore_context(target);
345
346 /* the front-end may request us not to handle breakpoints */
347 if (handle_breakpoints) {
348 /* Single step past breakpoint at current address */
349 breakpoint = breakpoint_find(target, resume_pc);
350 if (breakpoint) {
351 LOG_DEBUG("unset breakpoint at 0x%8.8" TARGET_PRIxADDR "", breakpoint->address);
352 #if 0
353 avr32_ap7k_unset_breakpoint(target, breakpoint);
354 avr32_ap7k_single_step_core(target);
355 avr32_ap7k_set_breakpoint(target, breakpoint);
356 #endif
357 }
358 }
359
360 #if 0
361 /* enable interrupts if we are running */
362 avr32_ap7k_enable_interrupts(target, !debug_execution);
363
364 /* exit debug mode */
365 mips_ejtag_exit_debug(ejtag_info);
366 #endif
367
368
369 retval = avr32_ocd_clearbits(&ap7k->jtag, AVR32_OCDREG_DC,
370 OCDREG_DC_DBR);
371 if (retval != ERROR_OK)
372 return retval;
373
374 retval = avr32_jtag_exec(&ap7k->jtag, RETD);
375 if (retval != ERROR_OK)
376 return retval;
377
378 target->debug_reason = DBG_REASON_NOTHALTED;
379
380 /* registers are now invalid */
381 register_cache_invalidate(ap7k->core_cache);
382
383 if (!debug_execution) {
384 target->state = TARGET_RUNNING;
385 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
386 LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
387 } else {
388 target->state = TARGET_DEBUG_RUNNING;
389 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
390 LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
391 }
392
393 return ERROR_OK;
394 }
395
396 static int avr32_ap7k_step(struct target *target, int current,
397 target_addr_t address, int handle_breakpoints)
398 {
399 LOG_ERROR("%s: implement me", __func__);
400
401 return ERROR_OK;
402 }
403
404 static int avr32_ap7k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
405 {
406 LOG_ERROR("%s: implement me", __func__);
407
408 return ERROR_OK;
409 }
410
411 static int avr32_ap7k_remove_breakpoint(struct target *target,
412 struct breakpoint *breakpoint)
413 {
414 LOG_ERROR("%s: implement me", __func__);
415
416 return ERROR_OK;
417 }
418
419 static int avr32_ap7k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
420 {
421 LOG_ERROR("%s: implement me", __func__);
422
423 return ERROR_OK;
424 }
425
426 static int avr32_ap7k_remove_watchpoint(struct target *target,
427 struct watchpoint *watchpoint)
428 {
429 LOG_ERROR("%s: implement me", __func__);
430
431 return ERROR_OK;
432 }
433
434 static int avr32_ap7k_read_memory(struct target *target, target_addr_t address,
435 uint32_t size, uint32_t count, uint8_t *buffer)
436 {
437 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
438
439 LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
440 address,
441 size,
442 count);
443
444 if (target->state != TARGET_HALTED) {
445 LOG_WARNING("target not halted");
446 return ERROR_TARGET_NOT_HALTED;
447 }
448
449 /* sanitize arguments */
450 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
451 return ERROR_COMMAND_SYNTAX_ERROR;
452
453 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
454 return ERROR_TARGET_UNALIGNED_ACCESS;
455
456 switch (size) {
457 case 4:
458 return avr32_jtag_read_memory32(&ap7k->jtag, address, count,
459 (uint32_t *)(void *)buffer);
460 break;
461 case 2:
462 return avr32_jtag_read_memory16(&ap7k->jtag, address, count,
463 (uint16_t *)(void *)buffer);
464 break;
465 case 1:
466 return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
467 break;
468 default:
469 break;
470 }
471
472 return ERROR_OK;
473 }
474
475 static int avr32_ap7k_write_memory(struct target *target, target_addr_t address,
476 uint32_t size, uint32_t count, const uint8_t *buffer)
477 {
478 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
479
480 LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
481 address,
482 size,
483 count);
484
485 if (target->state != TARGET_HALTED) {
486 LOG_WARNING("target not halted");
487 return ERROR_TARGET_NOT_HALTED;
488 }
489
490 /* sanitize arguments */
491 if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
492 return ERROR_COMMAND_SYNTAX_ERROR;
493
494 if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
495 return ERROR_TARGET_UNALIGNED_ACCESS;
496
497 switch (size) {
498 case 4:
499 return avr32_jtag_write_memory32(&ap7k->jtag, address, count,
500 (uint32_t *)(void *)buffer);
501 break;
502 case 2:
503 return avr32_jtag_write_memory16(&ap7k->jtag, address, count,
504 (uint16_t *)(void *)buffer);
505 break;
506 case 1:
507 return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
508 break;
509 default:
510 break;
511 }
512
513 return ERROR_OK;
514 }
515
516 static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
517 struct target *target)
518 {
519 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
520
521 ap7k->jtag.tap = target->tap;
522 avr32_build_reg_cache(target);
523 return ERROR_OK;
524 }
525
526 static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
527 {
528 struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
529 avr32_ap7k_common));
530
531 ap7k->common_magic = AP7k_COMMON_MAGIC;
532 target->arch_info = ap7k;
533
534 return ERROR_OK;
535 }
536
537 static int avr32_ap7k_examine(struct target *target)
538 {
539 uint32_t devid, ds;
540 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
541
542 if (!target_was_examined(target)) {
543 target_set_examined(target);
544 avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid);
545 LOG_INFO("device id: %08" PRIx32, devid);
546 avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBE);
547 avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
548
549 /* check for processor halted */
550 if (ds & OCDREG_DS_DBA) {
551 LOG_INFO("target is halted");
552 target->state = TARGET_HALTED;
553 } else
554 target->state = TARGET_RUNNING;
555 }
556
557 return ERROR_OK;
558 }
559
560 int avr32_ap7k_arch_state(struct target *target)
561 {
562 struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
563
564 LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
565 debug_reason_name(target), ap7k->jtag.dpc);
566
567 return ERROR_OK;
568 }
569
570 int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
571 int *reg_list_size, enum target_register_class reg_class)
572 {
573 #if 0
574 /* get pointers to arch-specific information */
575 int i;
576
577 /* include floating point registers */
578 *reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS;
579 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
580
581 for (i = 0; i < AVR32NUMCOREREGS; i++)
582 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
583
584 /* add dummy floating points regs */
585 for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
586 (*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
587
588 #endif
589
590 LOG_ERROR("%s: implement me", __func__);
591 return ERROR_FAIL;
592 }
593
594 struct target_type avr32_ap7k_target = {
595 .name = "avr32_ap7k",
596
597 .poll = avr32_ap7k_poll,
598 .arch_state = avr32_ap7k_arch_state,
599
600 .halt = avr32_ap7k_halt,
601 .resume = avr32_ap7k_resume,
602 .step = avr32_ap7k_step,
603
604 .assert_reset = avr32_ap7k_assert_reset,
605 .deassert_reset = avr32_ap7k_deassert_reset,
606
607 .get_gdb_reg_list = avr32_ap7k_get_gdb_reg_list,
608
609 .read_memory = avr32_ap7k_read_memory,
610 .write_memory = avr32_ap7k_write_memory,
611 /* .checksum_memory = avr32_ap7k_checksum_memory, */
612 /* .blank_check_memory = avr32_ap7k_blank_check_memory, */
613
614 /* .run_algorithm = avr32_ap7k_run_algorithm, */
615
616 .add_breakpoint = avr32_ap7k_add_breakpoint,
617 .remove_breakpoint = avr32_ap7k_remove_breakpoint,
618 .add_watchpoint = avr32_ap7k_add_watchpoint,
619 .remove_watchpoint = avr32_ap7k_remove_watchpoint,
620
621 .target_create = avr32_ap7k_target_create,
622 .init_target = avr32_ap7k_init_target,
623 .examine = avr32_ap7k_examine,
624 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)