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