Ensure Cortex-M reset wakes device from sleep (wfi/wfe)
[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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 char *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 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 = malloc(sizeof(struct reg) * num_regs);
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_soft_reset_halt(struct target *target)
317 {
318         LOG_ERROR("%s: implement me", __func__);
319
320         return ERROR_OK;
321 }
322
323 static int avr32_ap7k_resume(struct target *target, int current,
324         uint32_t address, int handle_breakpoints, int debug_execution)
325 {
326         struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
327         struct breakpoint *breakpoint = NULL;
328         uint32_t resume_pc;
329         int retval;
330
331         if (target->state != TARGET_HALTED) {
332                 LOG_WARNING("target not halted");
333                 return ERROR_TARGET_NOT_HALTED;
334         }
335
336         if (!debug_execution) {
337                 target_free_all_working_areas(target);
338                 /*
339                 avr32_ap7k_enable_breakpoints(target);
340                 avr32_ap7k_enable_watchpoints(target);
341                 */
342         }
343
344         /* current = 1: continue on current pc, otherwise continue at <address> */
345         if (!current) {
346 #if 0
347                 if (retval != ERROR_OK)
348                         return retval;
349 #endif
350         }
351
352         resume_pc = buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32);
353         avr32_ap7k_restore_context(target);
354
355         /* the front-end may request us not to handle breakpoints */
356         if (handle_breakpoints) {
357                 /* Single step past breakpoint at current address */
358                 breakpoint = breakpoint_find(target, resume_pc);
359                 if (breakpoint) {
360                         LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
361 #if 0
362                         avr32_ap7k_unset_breakpoint(target, breakpoint);
363                         avr32_ap7k_single_step_core(target);
364                         avr32_ap7k_set_breakpoint(target, breakpoint);
365 #endif
366                 }
367         }
368
369 #if 0
370         /* enable interrupts if we are running */
371         avr32_ap7k_enable_interrupts(target, !debug_execution);
372
373         /* exit debug mode */
374         mips_ejtag_exit_debug(ejtag_info);
375 #endif
376
377
378         retval = avr32_ocd_clearbits(&ap7k->jtag, AVR32_OCDREG_DC,
379                         OCDREG_DC_DBR);
380         if (retval != ERROR_OK)
381                 return retval;
382
383         retval = avr32_jtag_exec(&ap7k->jtag, RETD);
384         if (retval != ERROR_OK)
385                 return retval;
386
387         target->debug_reason = DBG_REASON_NOTHALTED;
388
389         /* registers are now invalid */
390         register_cache_invalidate(ap7k->core_cache);
391
392         if (!debug_execution) {
393                 target->state = TARGET_RUNNING;
394                 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
395                 LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
396         } else {
397                 target->state = TARGET_DEBUG_RUNNING;
398                 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
399                 LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
400         }
401
402         return ERROR_OK;
403 }
404
405 static int avr32_ap7k_step(struct target *target, int current,
406         uint32_t address, int handle_breakpoints)
407 {
408         LOG_ERROR("%s: implement me", __func__);
409
410         return ERROR_OK;
411 }
412
413 static int avr32_ap7k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
414 {
415         LOG_ERROR("%s: implement me", __func__);
416
417         return ERROR_OK;
418 }
419
420 static int avr32_ap7k_remove_breakpoint(struct target *target,
421         struct breakpoint *breakpoint)
422 {
423         LOG_ERROR("%s: implement me", __func__);
424
425         return ERROR_OK;
426 }
427
428 static int avr32_ap7k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
429 {
430         LOG_ERROR("%s: implement me", __func__);
431
432         return ERROR_OK;
433 }
434
435 static int avr32_ap7k_remove_watchpoint(struct target *target,
436         struct watchpoint *watchpoint)
437 {
438         LOG_ERROR("%s: implement me", __func__);
439
440         return ERROR_OK;
441 }
442
443 static int avr32_ap7k_read_memory(struct target *target, uint32_t address,
444         uint32_t size, uint32_t count, uint8_t *buffer)
445 {
446         struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
447
448         LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
449                 address,
450                 size,
451                 count);
452
453         if (target->state != TARGET_HALTED) {
454                 LOG_WARNING("target not halted");
455                 return ERROR_TARGET_NOT_HALTED;
456         }
457
458         /* sanitize arguments */
459         if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
460                 return ERROR_COMMAND_SYNTAX_ERROR;
461
462         if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
463                 return ERROR_TARGET_UNALIGNED_ACCESS;
464
465         switch (size) {
466                 case 4:
467                         return avr32_jtag_read_memory32(&ap7k->jtag, address, count,
468                                 (uint32_t *)(void *)buffer);
469                         break;
470                 case 2:
471                         return avr32_jtag_read_memory16(&ap7k->jtag, address, count,
472                                 (uint16_t *)(void *)buffer);
473                         break;
474                 case 1:
475                         return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
476                         break;
477                 default:
478                         break;
479         }
480
481         return ERROR_OK;
482 }
483
484 static int avr32_ap7k_write_memory(struct target *target, uint32_t address,
485         uint32_t size, uint32_t count, const uint8_t *buffer)
486 {
487         struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
488
489         LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
490                 address,
491                 size,
492                 count);
493
494         if (target->state != TARGET_HALTED) {
495                 LOG_WARNING("target not halted");
496                 return ERROR_TARGET_NOT_HALTED;
497         }
498
499         /* sanitize arguments */
500         if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
501                 return ERROR_COMMAND_SYNTAX_ERROR;
502
503         if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
504                 return ERROR_TARGET_UNALIGNED_ACCESS;
505
506         switch (size) {
507                 case 4:
508                         return avr32_jtag_write_memory32(&ap7k->jtag, address, count,
509                                 (uint32_t *)(void *)buffer);
510                         break;
511                 case 2:
512                         return avr32_jtag_write_memory16(&ap7k->jtag, address, count,
513                                 (uint16_t *)(void *)buffer);
514                         break;
515                 case 1:
516                         return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
517                         break;
518                 default:
519                         break;
520         }
521
522         return ERROR_OK;
523 }
524
525 static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
526         struct target *target)
527 {
528         struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
529
530         ap7k->jtag.tap = target->tap;
531         avr32_build_reg_cache(target);
532         return ERROR_OK;
533 }
534
535 static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
536 {
537         struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
538                         avr32_ap7k_common));
539
540         ap7k->common_magic = AP7k_COMMON_MAGIC;
541         target->arch_info = ap7k;
542
543         return ERROR_OK;
544 }
545
546 static int avr32_ap7k_examine(struct target *target)
547 {
548         uint32_t devid, ds;
549         struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
550
551         if (!target_was_examined(target)) {
552                 target_set_examined(target);
553                 avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid);
554                 LOG_INFO("device id: %08x", devid);
555                 avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBE);
556                 avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
557
558                 /* check for processor halted */
559                 if (ds & OCDREG_DS_DBA) {
560                         LOG_INFO("target is halted");
561                         target->state = TARGET_HALTED;
562                 } else
563                         target->state = TARGET_RUNNING;
564         }
565
566         return ERROR_OK;
567 }
568
569 static int avr32_ap7k_bulk_write_memory(struct target *target, uint32_t address,
570         uint32_t count, const uint8_t *buffer)
571 {
572         LOG_ERROR("%s: implement me", __func__);
573
574         return ERROR_OK;
575 }
576
577
578 int avr32_ap7k_arch_state(struct target *target)
579 {
580         struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
581
582         LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
583                 debug_reason_name(target), ap7k->jtag.dpc);
584
585         return ERROR_OK;
586 }
587
588 int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
589 {
590 #if 0
591         /* get pointers to arch-specific information */
592         int i;
593
594         /* include floating point registers */
595         *reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS;
596         *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
597
598         for (i = 0; i < AVR32NUMCOREREGS; i++)
599                 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
600
601         /* add dummy floating points regs */
602         for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
603                 (*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
604
605 #endif
606
607         LOG_ERROR("%s: implement me", __func__);
608         return ERROR_FAIL;
609 }
610
611
612
613 struct target_type avr32_ap7k_target = {
614         .name = "avr32_ap7k",
615
616         .poll = avr32_ap7k_poll,
617         .arch_state = avr32_ap7k_arch_state,
618
619         .target_request_data = NULL,
620
621         .halt = avr32_ap7k_halt,
622         .resume = avr32_ap7k_resume,
623         .step = avr32_ap7k_step,
624
625         .assert_reset = avr32_ap7k_assert_reset,
626         .deassert_reset = avr32_ap7k_deassert_reset,
627         .soft_reset_halt = avr32_ap7k_soft_reset_halt,
628
629         .get_gdb_reg_list = avr32_ap7k_get_gdb_reg_list,
630
631         .read_memory = avr32_ap7k_read_memory,
632         .write_memory = avr32_ap7k_write_memory,
633         .bulk_write_memory = avr32_ap7k_bulk_write_memory,
634         /* .checksum_memory = avr32_ap7k_checksum_memory, */
635         /* .blank_check_memory = avr32_ap7k_blank_check_memory, */
636
637         /* .run_algorithm = avr32_ap7k_run_algorithm, */
638
639         .add_breakpoint = avr32_ap7k_add_breakpoint,
640         .remove_breakpoint = avr32_ap7k_remove_breakpoint,
641         .add_watchpoint = avr32_ap7k_add_watchpoint,
642         .remove_watchpoint = avr32_ap7k_remove_watchpoint,
643
644         .target_create = avr32_ap7k_target_create,
645         .init_target = avr32_ap7k_init_target,
646         .examine = avr32_ap7k_examine,
647 };