Remove FSF address from GPL notices
[fw/openocd] / 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         uint32_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" PRIx32 "", 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         uint32_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, uint32_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" PRIx32 ", 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, uint32_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" PRIx32 ", 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 };