avr32: work-in-progress
authorOleksandr Tymoshenko <gonzo@bluezbox.com>
Sun, 15 Aug 2010 19:51:34 +0000 (21:51 +0200)
committerØyvind Harboe <oyvind.harboe@zylin.com>
Sun, 15 Aug 2010 19:51:34 +0000 (21:51 +0200)
committed so as to ease cooperation and to let it be improved
over time.

So far it supports:
- halt/resume
- registers inspection
- memory inspection/modification

I'm still getting up to speed with OpenOCD internals and AVR32 so code is a little
bit messy and I'd appreciate any feedback.

src/target/Makefile.am
src/target/avr32_ap7k.c [new file with mode: 0644]
src/target/avr32_ap7k.h [new file with mode: 0644]
src/target/avr32_jtag.c [new file with mode: 0644]
src/target/avr32_jtag.h [new file with mode: 0644]
src/target/avr32_mem.c [new file with mode: 0644]
src/target/avr32_mem.h [new file with mode: 0644]
src/target/avr32_regs.c [new file with mode: 0644]
src/target/avr32_regs.h [new file with mode: 0644]
src/target/target.c

index ea6d88fce9f005c7b55f5f261cd887fe6e7022aa..e01e0774b78bee1bcb1d626e448c83ba23ed1cff 100644 (file)
@@ -32,6 +32,7 @@ libtarget_la_SOURCES = \
        $(ARMV6_SRC) \
        $(ARMV7_SRC) \
        $(ARM_MISC_SRC) \
+       $(AVR32_SRC) \
        $(MIPS32_SRC) \
        avrt.c \
        dsp563xx.c \
@@ -92,6 +93,12 @@ ARM_DEBUG_SRC = \
        $(OOCD_TRACE_FILES) \
        etm_dummy.c
 
+AVR32_SRC = \
+       avr32_ap7k.c \
+       avr32_jtag.c \
+       avr32_mem.c \
+       avr32_regs.c
+
 MIPS32_SRC = \
        mips32.c \
        mips_m4k.c \
diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c
new file mode 100644 (file)
index 0000000..a5cdbe4
--- /dev/null
@@ -0,0 +1,684 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com>       *
+ *   Based on mips_m4k code:                                               *
+ *       Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk>       *
+ *       Copyright (C) 2008 by David T.L. Wong                             *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "jtag/jtag.h"
+#include "register.h"
+#include "algorithm.h"
+#include "target.h"
+#include "breakpoints.h"
+#include "target_type.h"
+#include "avr32_jtag.h"
+#include "avr32_mem.h"
+#include "avr32_regs.h"
+#include "avr32_ap7k.h"
+
+static char* avr32_core_reg_list[] =
+{
+       "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", 
+       "r9", "r10", "r11", "r12", "sp", "lr", "pc", "sr"
+};
+
+static struct avr32_core_reg 
+       avr32_core_reg_list_arch_info[AVR32NUMCOREREGS] =
+{
+       {0, NULL, NULL},
+       {1, NULL, NULL},
+       {2, NULL, NULL},
+       {3, NULL, NULL},
+       {4, NULL, NULL},
+       {5, NULL, NULL},
+       {6, NULL, NULL},
+       {7, NULL, NULL},
+       {8, NULL, NULL},
+       {9, NULL, NULL},
+       {10, NULL, NULL},
+       {11, NULL, NULL},
+       {12, NULL, NULL},
+       {13, NULL, NULL},
+       {14, NULL, NULL},
+       {15, NULL, NULL},
+       {16, NULL, NULL},
+};
+
+
+static int avr32_read_core_reg(struct target *target, int num);
+static int avr32_write_core_reg(struct target *target, int num);
+
+int avr32_ap7k_save_context(struct target *target)
+{
+       int retval, i;
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       retval = avr32_jtag_read_regs(&ap7k->jtag, ap7k->core_regs);
+       if (retval != ERROR_OK)
+               return retval;
+
+       for (i = 0; i < AVR32NUMCOREREGS; i++)
+       {
+               if (!ap7k->core_cache->reg_list[i].valid)
+               {
+                       avr32_read_core_reg(target, i);
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int avr32_ap7k_restore_context(struct target *target)
+{
+       int i;
+
+       /* get pointers to arch-specific information */
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       for (i = 0; i < AVR32NUMCOREREGS; i++)
+       {
+               if (ap7k->core_cache->reg_list[i].dirty)
+               {
+                       avr32_write_core_reg(target, i);
+               }
+       }
+
+       /* write core regs */
+       avr32_jtag_write_regs(&ap7k->jtag, ap7k->core_regs);
+
+       return ERROR_OK;
+}
+
+static int avr32_read_core_reg(struct target *target, int num)
+{
+       uint32_t reg_value;
+       struct avr32_core_reg *mips_core_reg;
+
+       /* get pointers to arch-specific information */
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       if ((num < 0) || (num >= AVR32NUMCOREREGS))
+               return ERROR_INVALID_ARGUMENTS;
+
+       mips_core_reg = ap7k->core_cache->reg_list[num].arch_info;
+       reg_value = ap7k->core_regs[num];
+       buf_set_u32(ap7k->core_cache->reg_list[num].value, 0, 32, reg_value);
+       ap7k->core_cache->reg_list[num].valid = 1;
+       ap7k->core_cache->reg_list[num].dirty = 0;
+
+       return ERROR_OK;
+}
+
+static int avr32_write_core_reg(struct target *target, int num)
+{
+       uint32_t reg_value;
+       struct avr32_core_reg *mips_core_reg;
+
+       /* get pointers to arch-specific information */
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       if ((num < 0) || (num >= AVR32NUMCOREREGS))
+               return ERROR_INVALID_ARGUMENTS;
+
+       reg_value = buf_get_u32(ap7k->core_cache->reg_list[num].value, 0, 32);
+       mips_core_reg = ap7k->core_cache->reg_list[num].arch_info;
+       ap7k->core_regs[num] = reg_value;
+       LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
+       ap7k->core_cache->reg_list[num].valid = 1;
+       ap7k->core_cache->reg_list[num].dirty = 0;
+
+       return ERROR_OK;
+}
+
+static int avr32_get_core_reg(struct reg *reg)
+{
+       int retval;
+       struct avr32_core_reg *avr32_reg = reg->arch_info;
+       struct target *target = avr32_reg->target;
+
+       if (target->state != TARGET_HALTED)
+       {
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       retval = avr32_read_core_reg(target, avr32_reg->num);
+
+       return retval;
+}
+
+static int avr32_set_core_reg(struct reg *reg, uint8_t *buf)
+{
+       struct avr32_core_reg *avr32_reg = reg->arch_info;
+       struct target *target = avr32_reg->target;
+       uint32_t value = buf_get_u32(buf, 0, 32);
+
+       if (target->state != TARGET_HALTED)
+       {
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       buf_set_u32(reg->value, 0, 32, value);
+       reg->dirty = 1;
+       reg->valid = 1;
+
+       return ERROR_OK;
+}
+
+static const struct reg_arch_type avr32_reg_type = {
+       .get = avr32_get_core_reg,
+       .set = avr32_set_core_reg,
+};
+
+static struct reg_cache *avr32_build_reg_cache(struct target *target)
+{
+       int num_regs = AVR32NUMCOREREGS;
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+       struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
+       struct reg_cache *cache = malloc(sizeof(struct reg_cache));
+       struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
+       struct avr32_core_reg *arch_info = 
+               malloc(sizeof(struct avr32_core_reg) * num_regs);
+       int i;
+
+       /* Build the process context cache */
+       cache->name = "avr32 registers";
+       cache->next = NULL;
+       cache->reg_list = reg_list;
+       cache->num_regs = num_regs;
+       (*cache_p) = cache;
+       ap7k->core_cache = cache;
+
+       for (i = 0; i < num_regs; i++)
+       {
+               arch_info[i] = avr32_core_reg_list_arch_info[i];
+               arch_info[i].target = target;
+               arch_info[i].avr32_common = ap7k;
+               reg_list[i].name = avr32_core_reg_list[i];
+               reg_list[i].size = 32;
+               reg_list[i].value = calloc(1, 4);
+               reg_list[i].dirty = 0;
+               reg_list[i].valid = 0;
+               reg_list[i].type = &avr32_reg_type;
+               reg_list[i].arch_info = &arch_info[i];
+       }
+
+       return cache;
+}
+
+static int avr32_ap7k_debug_entry(struct target *target)
+{
+
+       uint32_t dpc, dinst;
+       int retval;
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DPC, &dpc);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DINST, &dinst);
+       if (retval != ERROR_OK)
+               return retval;
+
+       ap7k->jtag.dpc = dpc;
+
+       avr32_ap7k_save_context(target);
+
+       return ERROR_OK;
+}
+
+
+static int avr32_ap7k_poll(struct target *target)
+{
+       uint32_t ds;
+       int retval;
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       retval = avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* check for processor halted */
+       if (ds & OCDREG_DS_DBA)
+       {
+               if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
+               {
+                       target->state = TARGET_HALTED;
+
+                       if ((retval = avr32_ap7k_debug_entry(target)) != ERROR_OK)
+                               return retval;
+
+                       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+               }
+               else if (target->state == TARGET_DEBUG_RUNNING)
+               {
+                       target->state = TARGET_HALTED;
+
+                       if ((retval = avr32_ap7k_debug_entry(target)) != ERROR_OK)
+                               return retval;
+
+                       target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+               }
+       }
+       else
+       {
+               target->state = TARGET_RUNNING;
+       }
+
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_halt(struct target *target)
+{
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       LOG_DEBUG("target->state: %s",
+                 target_state_name(target));
+
+       if (target->state == TARGET_HALTED)
+       {
+               LOG_DEBUG("target was already halted");
+               return ERROR_OK;
+       }
+
+       if (target->state == TARGET_UNKNOWN)
+       {
+               LOG_WARNING("target was in unknown state when halt was requested");
+       }
+
+       if (target->state == TARGET_RESET)
+       {
+               if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst())
+               {
+                       LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
+                       return ERROR_TARGET_FAILURE;
+               }
+               else
+               {
+                       target->debug_reason = DBG_REASON_DBGRQ;
+
+                       return ERROR_OK;
+               }
+       }
+
+
+       avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC, OCDREG_DC_DBR);
+       target->debug_reason = DBG_REASON_DBGRQ;
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_assert_reset(struct target *target)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_deassert_reset(struct target *target)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_soft_reset_halt(struct target *target)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_resume(struct target *target, int current,
+               uint32_t address, int handle_breakpoints, int debug_execution)
+{
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+       struct breakpoint *breakpoint = NULL;
+       uint32_t resume_pc;
+       int retval;
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (!debug_execution)
+       {
+               target_free_all_working_areas(target);
+               /*
+               avr32_ap7k_enable_breakpoints(target);
+               avr32_ap7k_enable_watchpoints(target);
+               */
+       }
+
+       /* current = 1: continue on current pc, otherwise continue at <address> */
+       if (!current)
+       {
+#if 0
+               if (retval != ERROR_OK)
+                       return retval;
+#endif
+       }
+
+       resume_pc = 
+               buf_get_u32(ap7k->core_cache->reg_list[AVR32_REG_PC].value, 0, 32);
+       avr32_ap7k_restore_context(target);
+
+       /* the front-end may request us not to handle breakpoints */
+       if (handle_breakpoints)
+       {
+               /* Single step past breakpoint at current address */
+               if ((breakpoint = breakpoint_find(target, resume_pc)))
+               {
+                       LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
+#if 0
+                       avr32_ap7k_unset_breakpoint(target, breakpoint);
+                       avr32_ap7k_single_step_core(target);
+                       avr32_ap7k_set_breakpoint(target, breakpoint);
+#endif
+               }
+       }
+
+#if 0
+       /* enable interrupts if we are running */
+       avr32_ap7k_enable_interrupts(target, !debug_execution);
+
+       /* exit debug mode */
+       mips_ejtag_exit_debug(ejtag_info);
+#endif
+
+
+       retval = avr32_ocd_clearbits(&ap7k->jtag, AVR32_OCDREG_DC,
+                       OCDREG_DC_DBR);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = avr32_jtag_exec(&ap7k->jtag, RETD);
+       if (retval != ERROR_OK)
+               return retval;
+
+       target->debug_reason = DBG_REASON_NOTHALTED;
+
+       /* registers are now invalid */
+       register_cache_invalidate(ap7k->core_cache);
+
+       if (!debug_execution)
+       {
+               target->state = TARGET_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+               LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
+       }
+       else
+       {
+               target->state = TARGET_DEBUG_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
+               LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
+       }
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_step(struct target *target, int current,
+               uint32_t address, int handle_breakpoints)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_remove_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_remove_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_read_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count);
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
+               return ERROR_INVALID_ARGUMENTS;
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       switch (size)
+       {
+       case 4:
+               return avr32_jtag_read_memory32(&ap7k->jtag, address, count, (uint32_t*)buffer);
+               break;
+       case 2:
+               return avr32_jtag_read_memory16(&ap7k->jtag, address, count, (uint16_t*)buffer);
+               break;
+       case 1:
+               return avr32_jtag_read_memory8(&ap7k->jtag, address, count, buffer);
+               break;
+       default:
+               break;
+       }
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_write_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count);
+
+       if (target->state != TARGET_HALTED)
+       {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
+               return ERROR_INVALID_ARGUMENTS;
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       switch (size)
+       {
+       case 4:
+               return avr32_jtag_write_memory32(&ap7k->jtag, address, count, (uint32_t*)buffer);
+               break;
+       case 2:
+               return avr32_jtag_write_memory16(&ap7k->jtag, address, count, (uint16_t*)buffer);
+               break;
+       case 1:
+               return avr32_jtag_write_memory8(&ap7k->jtag, address, count, buffer);
+               break;
+       default:
+               break;
+       }
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_init_target(struct command_context *cmd_ctx,
+               struct target *target)
+{
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       ap7k->jtag.tap = target->tap;
+       avr32_build_reg_cache(target);
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_target_create(struct target *target, Jim_Interp *interp)
+{
+       struct avr32_ap7k_common *ap7k = calloc(1, sizeof(struct
+                               avr32_ap7k_common));
+
+       ap7k->common_magic = AP7k_COMMON_MAGIC;
+       target->arch_info = ap7k;
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_examine(struct target *target)
+{
+       uint32_t devid, ds;
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       if (!target_was_examined(target))
+       {
+               target_set_examined(target);
+               avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid);
+               LOG_INFO("device id: %08x", devid);
+               avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC,OCDREG_DC_DBE);
+               avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds);
+
+               /* check for processor halted */
+               if (ds & OCDREG_DS_DBA) 
+               {
+                       LOG_INFO("target is halted");
+                       target->state = TARGET_HALTED;
+               }
+               else
+                       target->state = TARGET_RUNNING;
+       }
+
+       return ERROR_OK;
+}
+
+static int avr32_ap7k_bulk_write_memory(struct target *target, uint32_t address,
+               uint32_t count, uint8_t *buffer)
+{
+       LOG_ERROR("%s: implement me", __func__);
+
+       return ERROR_OK;
+}
+
+
+int avr32_ap7k_arch_state(struct target *target)
+{
+       struct avr32_ap7k_common *ap7k = target_to_ap7k(target);
+
+       LOG_USER("target halted due to %s, pc: 0x%8.8" PRIx32 "",
+                debug_reason_name(target), ap7k->jtag.dpc);
+
+       return ERROR_OK;
+}
+
+int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
+{
+#if 0
+        /* get pointers to arch-specific information */
+        int i;
+
+        /* include floating point registers */
+        *reg_list_size = AVR32NUMCOREREGS + AVR32NUMFPREGS;
+        *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
+
+        for (i = 0; i < AVR32NUMCOREREGS; i++)
+        {
+                (*reg_list)[i] = &mips32->core_cache->reg_list[i];
+        }
+
+        /* add dummy floating points regs */
+        for (i = AVR32NUMCOREREGS; i < (AVR32NUMCOREREGS + AVR32NUMFPREGS); i++)
+        {
+                (*reg_list)[i] = &avr32_ap7k_gdb_dummy_fp_reg;
+        }
+#endif
+
+       LOG_ERROR("%s: implement me", __func__);
+       return ERROR_FAIL;
+}
+
+
+
+struct target_type avr32_ap7k_target =
+{
+       .name = "avr32_ap7k",
+
+       .poll = avr32_ap7k_poll,
+       .arch_state = avr32_ap7k_arch_state,
+
+       .target_request_data = NULL,
+
+       .halt = avr32_ap7k_halt,
+       .resume = avr32_ap7k_resume,
+       .step = avr32_ap7k_step,
+
+       .assert_reset = avr32_ap7k_assert_reset,
+       .deassert_reset = avr32_ap7k_deassert_reset,
+       .soft_reset_halt = avr32_ap7k_soft_reset_halt,
+
+       .get_gdb_reg_list = avr32_ap7k_get_gdb_reg_list,
+
+       .read_memory = avr32_ap7k_read_memory,
+       .write_memory = avr32_ap7k_write_memory,
+       .bulk_write_memory = avr32_ap7k_bulk_write_memory,
+       // .checksum_memory = avr32_ap7k_checksum_memory,
+       // .blank_check_memory = avr32_ap7k_blank_check_memory,
+
+       // .run_algorithm = avr32_ap7k_run_algorithm,
+
+       .add_breakpoint = avr32_ap7k_add_breakpoint,
+       .remove_breakpoint = avr32_ap7k_remove_breakpoint,
+       .add_watchpoint = avr32_ap7k_add_watchpoint,
+       .remove_watchpoint = avr32_ap7k_remove_watchpoint,
+
+       .target_create = avr32_ap7k_target_create,
+       .init_target = avr32_ap7k_init_target,
+       .examine = avr32_ap7k_examine,
+};
diff --git a/src/target/avr32_ap7k.h b/src/target/avr32_ap7k.h
new file mode 100644 (file)
index 0000000..d08254b
--- /dev/null
@@ -0,0 +1,49 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef AVR32_AP7K
+#define AVR32_AP7K
+
+#include <helper/types.h>
+
+struct target;
+
+#define AP7k_COMMON_MAGIC      0x4150374b
+struct avr32_ap7k_common
+{
+       int common_magic;
+       struct avr32_jtag jtag;
+       struct reg_cache *core_cache;
+       uint32_t core_regs[AVR32NUMCOREREGS];
+};
+
+static inline struct avr32_ap7k_common *
+target_to_ap7k(struct target *target)
+{
+       return (struct avr32_ap7k_common*)target->arch_info;
+}
+
+struct avr32_core_reg
+{
+       uint32_t num;
+       struct target *target;
+       struct avr32_ap7k_common *avr32_common;
+};
+
+#endif /*AVR32_AP7K*/
diff --git a/src/target/avr32_jtag.c b/src/target/avr32_jtag.c
new file mode 100644 (file)
index 0000000..b6b5e37
--- /dev/null
@@ -0,0 +1,392 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "target.h"
+#include "helper/types.h"
+#include "jtag/jtag.h"
+#include "avr32_jtag.h"
+
+static int avr32_jtag_set_instr(struct avr32_jtag *jtag_info, int new_instr)
+{
+       struct jtag_tap *tap;
+       int busy = 0;
+
+       tap = jtag_info->tap;
+       if (tap == NULL)
+               return ERROR_FAIL;
+
+       if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr)
+       {
+               do {
+                       struct scan_field field;
+                       uint8_t t[4];
+                       uint8_t ret[4];
+
+                       field.num_bits = tap->ir_length;
+                       field.out_value = t;
+                       buf_set_u32(t, 0, field.num_bits, new_instr);
+                       field.in_value = ret;
+
+                       jtag_add_ir_scan(tap, &field, TAP_IDLE);
+                       if (jtag_execute_queue() != ERROR_OK)
+                       {
+                               LOG_ERROR("%s: setting address failed", __func__);
+                               return ERROR_FAIL;
+                       }
+                       busy = buf_get_u32(ret, 2, 1);
+               } while (busy); /* check for busy bit */
+       }
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_nexus_set_address(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int mode)
+{
+       struct scan_field fields[2];
+       uint8_t addr_buf[4];
+       uint8_t busy_buf[4];
+       int busy;
+
+       memset(fields, 0, sizeof(fields));
+
+       do {
+               memset(addr_buf, 0, sizeof(addr_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+
+               buf_set_u32(addr_buf, 0, 1, mode);
+               buf_set_u32(addr_buf, 1, 7, addr);
+
+               fields[0].num_bits = 26;
+               fields[0].in_value = NULL;
+               fields[0].out_value = NULL;
+
+               fields[1].num_bits = 8;
+               fields[1].in_value = busy_buf;
+               fields[1].out_value = addr_buf;
+
+               jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
+               if (jtag_execute_queue() != ERROR_OK)
+               {
+                       LOG_ERROR("%s: setting address failed", __func__);
+                       return ERROR_FAIL;
+               }
+               busy = buf_get_u32(busy_buf, 6, 1);
+       } while(busy);
+
+       return ERROR_OK;
+}
+
+
+int avr32_jtag_nexus_read_data(struct avr32_jtag *jtag_info, 
+       uint32_t *pdata)
+{
+
+       struct scan_field fields[2];
+       uint8_t data_buf[4];
+       uint8_t busy_buf[4];
+       int busy;
+
+       do {
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+
+               fields[0].num_bits = 32;
+               fields[0].out_value = NULL;
+               fields[0].in_value = data_buf;
+
+
+               fields[1].num_bits = 2;
+               fields[1].in_value = busy_buf;
+               fields[1].out_value = NULL;
+
+               jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
+
+               if (jtag_execute_queue() != ERROR_OK)
+               {
+                       LOG_ERROR("%s: reading data  failed", __func__);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 1);
+       } while (busy);
+
+       *pdata = buf_get_u32(data_buf, 0, 32);
+
+       return ERROR_OK;
+}
+
+
+int avr32_jtag_nexus_write_data(struct avr32_jtag *jtag_info, 
+               uint32_t data)
+{
+
+       struct scan_field fields[2];
+       uint8_t data_buf[4];
+       uint8_t busy_buf[4];
+       uint8_t dummy_buf[4];
+       int busy;
+
+       do {
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+               memset(dummy_buf, 0, sizeof(dummy_buf));
+
+               fields[0].num_bits = 2;
+               fields[0].in_value = busy_buf;
+               fields[0].out_value = dummy_buf;
+
+
+               buf_set_u32(data_buf, 0, 32, data);
+               fields[1].num_bits = 32;
+               fields[1].in_value = NULL;
+               fields[1].out_value = data_buf;
+
+               jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
+
+               if (jtag_execute_queue() != ERROR_OK)
+               {
+                       LOG_ERROR("%s: reading data  failed", __func__);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 0);
+       } while (busy);
+
+
+       return ERROR_OK;
+}
+
+
+
+
+int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info,
+               uint32_t addr, uint32_t *value)
+{
+       avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS);
+       avr32_jtag_nexus_set_address(jtag_info, addr, MODE_READ);
+       avr32_jtag_nexus_read_data(jtag_info, value);
+
+       return ERROR_OK;
+
+}
+int avr32_jtag_nexus_write(struct avr32_jtag *jtag_info,
+               uint32_t addr, uint32_t value)
+{
+       avr32_jtag_set_instr(jtag_info, AVR32_INST_NEXUS_ACCESS);
+       avr32_jtag_nexus_set_address(jtag_info, addr, MODE_WRITE);
+       avr32_jtag_nexus_write_data(jtag_info, value);
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_mwa_set_address(struct avr32_jtag *jtag_info, int slave,
+               uint32_t addr, int mode)
+{
+       struct scan_field fields[2];
+       uint8_t addr_buf[4];
+       uint8_t slave_buf[4];
+       uint8_t busy_buf[4];
+       int busy;
+
+       memset(fields, 0, sizeof(fields));
+
+       do {
+               memset(addr_buf, 0, sizeof(addr_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+               memset(slave_buf, 0, sizeof(slave_buf));
+
+               buf_set_u32(slave_buf, 0, 4, slave);
+               buf_set_u32(addr_buf, 0, 1, mode);
+               buf_set_u32(addr_buf, 1, 30, addr >> 2);
+
+               fields[0].num_bits = 31;
+               fields[0].in_value = NULL;
+               fields[0].out_value = addr_buf;
+
+               fields[1].num_bits = 4;
+               fields[1].in_value = busy_buf;
+               fields[1].out_value = slave_buf;
+
+               jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
+               if (jtag_execute_queue() != ERROR_OK)
+               {
+                       LOG_ERROR("%s: setting address failed", __func__);
+                       return ERROR_FAIL;
+               }
+               busy = buf_get_u32(busy_buf, 1, 1);
+       } while(busy);
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_mwa_read_data(struct avr32_jtag *jtag_info, 
+       uint32_t *pdata)
+{
+
+       struct scan_field fields[2];
+       uint8_t data_buf[4];
+       uint8_t busy_buf[4];
+       int busy;
+
+       do {
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+
+               fields[0].num_bits = 32;
+               fields[0].out_value = NULL;
+               fields[0].in_value = data_buf;
+
+
+               fields[1].num_bits = 3;
+               fields[1].in_value = busy_buf;
+               fields[1].out_value = NULL;
+
+               jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
+
+               if (jtag_execute_queue() != ERROR_OK)
+               {
+                       LOG_ERROR("%s: reading data  failed", __func__);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 1);
+       } while (busy);
+
+       *pdata = buf_get_u32(data_buf, 0, 32);
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_mwa_write_data(struct avr32_jtag *jtag_info, 
+       uint32_t data)
+{
+
+       struct scan_field fields[2];
+       uint8_t data_buf[4];
+       uint8_t busy_buf[4];
+       uint8_t zero_buf[4];
+       int busy;
+
+       do {
+               memset(data_buf, 0, sizeof(data_buf));
+               memset(busy_buf, 0, sizeof(busy_buf));
+               memset(zero_buf, 0, sizeof(zero_buf));
+
+               buf_set_u32(data_buf, 0, 32, data);
+               fields[0].num_bits = 3;
+               fields[0].in_value = busy_buf;
+               fields[0].out_value = zero_buf;
+
+               fields[1].num_bits = 32;
+               fields[1].out_value = data_buf;
+               fields[1].in_value = NULL;
+
+
+               jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_IDLE);
+
+               if (jtag_execute_queue() != ERROR_OK)
+               {
+                       LOG_ERROR("%s: reading data  failed", __func__);
+                       return ERROR_FAIL;
+               }
+
+               busy = buf_get_u32(busy_buf, 0, 1);
+       } while (busy);
+
+       return ERROR_OK;
+}
+
+
+
+int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave,
+               uint32_t addr, uint32_t *value)
+{
+       avr32_jtag_set_instr(jtag_info, AVR32_INST_MW_ACCESS);
+       avr32_jtag_mwa_set_address(jtag_info, slave, addr, MODE_READ);
+       avr32_jtag_mwa_read_data(jtag_info, value);
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave,
+               uint32_t addr, uint32_t value)
+{
+       avr32_jtag_set_instr(jtag_info, AVR32_INST_MW_ACCESS);
+       avr32_jtag_mwa_set_address(jtag_info, slave, addr, MODE_WRITE);
+       avr32_jtag_mwa_write_data(jtag_info, value);
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst)
+{
+       int retval;
+       uint32_t ds;
+
+       retval = avr32_jtag_nexus_write(jtag_info, AVR32_OCDREG_DINST, inst);
+       if (retval != ERROR_OK)
+               return retval;
+
+       do {
+               retval = avr32_jtag_nexus_read(jtag_info, AVR32_OCDREG_DS, &ds);
+               if (retval != ERROR_OK)
+                       return retval;
+       } while ((ds & OCDREG_DS_DBA) && !(ds & OCDREG_DS_INC));
+
+       return ERROR_OK;
+}
+
+int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits)
+{
+       uint32_t value;
+       int res;
+
+       res = avr32_jtag_nexus_read(jtag, reg, &value);
+       if (res)
+               return res;
+
+       value |= bits;
+       res = avr32_jtag_nexus_write(jtag, reg, value);
+       if (res)
+               return res;
+
+       return ERROR_OK;
+}
+
+int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits)
+{
+       uint32_t value;
+       int res;
+
+       res = avr32_jtag_nexus_read(jtag, reg, &value);
+       if (res)
+               return res;
+
+       value &= ~bits;
+       res = avr32_jtag_nexus_write(jtag, reg, value);
+       if (res)
+               return res;
+
+       return ERROR_OK;
+}
+
diff --git a/src/target/avr32_jtag.h b/src/target/avr32_jtag.h
new file mode 100644 (file)
index 0000000..00f8330
--- /dev/null
@@ -0,0 +1,107 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef AVR32_JTAG
+#define AVR32_JTAG
+
+#define        AVR32NUMCOREREGS        17
+
+/* tap instructions */
+#define AVR32_INST_IDCODE              0x01
+#define AVR32_INST_NEXUS_ACCESS        0x10
+#define AVR32_INST_MW_ACCESS   0x11
+#define AVR32_INST_MB_ACCESS   0x12
+
+#define        SLAVE_OCD                               0x01
+#define        SLAVE_HSB_CACHED                0x04
+#define        SLAVE_HSB_UNCACHED              0x05
+
+/*
+ * Registers
+ */
+
+#define AVR32_OCDREG_DID               0x00
+#define AVR32_OCDREG_DC                        0x02
+#define                OCDREG_DC_SS                    (1 <<  8)
+#define                OCDREG_DC_DBR                   (1 << 12)
+#define                OCDREG_DC_DBE                   (1 << 13)
+#define                OCDREG_DC_SQA                   (1 << 22)
+#define                OCDREG_DC_RES                   (1 << 30)
+#define                OCDREG_DC_ABORT                 (1 << 31)
+#define AVR32_OCDREG_DS                        0x04
+#define                OCDREG_DS_SSS                   (1 <<  0)
+#define                OCDREG_DS_SWB                   (1 <<  1)
+#define                OCDREG_DS_HWB                   (1 <<  2)
+#define                OCDREG_DS_STP                   (1 <<  4)
+#define                OCDREG_DS_DBS                   (1 <<  5)
+#define                OCDREG_DS_BP_SHIFT              8
+#define                OCDREG_DS_BP_MASK               0xff
+#define                OCDREG_DS_INC                   (1 << 24)
+#define                OCDREG_DS_BOZ                   (1 << 25)
+#define                OCDREG_DS_DBA                   (1 << 26)
+#define                OCDREG_DS_EXB                   (1 << 27)
+#define                OCDREG_DS_NTBF                  (1 << 28)
+
+#define AVR32_OCDREG_DINST             0x41
+#define AVR32_OCDREG_DPC               0x42
+#define AVR32_OCDREG_DCCPU             0x44
+#define AVR32_OCDREG_DCEMU             0x45
+#define AVR32_OCDREG_DCSR              0x46
+#define                OCDREG_DCSR_CPUD                (1 <<  0)
+#define                OCDREG_DCSR_EMUD                (1 <<  1)
+
+/*
+ * Direction bit
+ */
+#define        MODE_WRITE                              0x00
+#define        MODE_READ                               0x01
+
+/*
+ * Some instructions
+ */
+
+#define        RETD                                    0xd703d623
+#define        MTDR(dreg, reg)                 (0xe7b00044 | ((reg) << 16) | dreg)
+#define        MFDR(reg, dreg)                 (0xe5b00044 | ((reg) << 16) | dreg)
+#define        MTSR(sysreg, reg)               (0xe3b00002 | ((reg) << 16) | sysreg)
+#define        MFSR(reg, sysreg)               (0xe1b00002 | ((reg) << 16) | sysreg)
+
+struct avr32_jtag
+{
+       struct jtag_tap *tap;
+       uint32_t dpc; /* Debug PC value */
+};
+
+int avr32_jtag_nexus_read(struct avr32_jtag *jtag_info,
+               uint32_t addr, uint32_t *value);
+int avr32_jtag_nexus_write(struct avr32_jtag *jtag_info,
+               uint32_t addr, uint32_t value);
+
+int avr32_jtag_mwa_read(struct avr32_jtag *jtag_info, int slave,
+               uint32_t addr, uint32_t *value);
+int avr32_jtag_mwa_write(struct avr32_jtag *jtag_info, int slave,
+               uint32_t addr, uint32_t value);
+
+
+int avr32_ocd_setbits(struct avr32_jtag *jtag, int reg, uint32_t bits);
+int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits);
+
+int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst);
+
+#endif /* AVR32_JTAG */
+
diff --git a/src/target/avr32_mem.c b/src/target/avr32_mem.c
new file mode 100644 (file)
index 0000000..0767c55
--- /dev/null
@@ -0,0 +1,333 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "target.h"
+#include "jtag/jtag.h"
+#include "avr32_jtag.h"
+#include "avr32_mem.h"
+
+int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint32_t *buffer)
+{
+       int i, retval;
+       uint32_t data;
+
+       for (i = 0; i < count; i++) 
+       {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i*4, &data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* XXX: Assume AVR32 is BE */
+               buffer[i] = be_to_h_u32((uint8_t*)&data);
+       }
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint16_t *buffer)
+{
+       int i, retval;
+       uint32_t data;
+
+       i = 0;
+
+       /* any unaligned half-words? */
+       if (addr & 3)
+       {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i*2, &data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* XXX: Assume AVR32 is BE */
+               data = be_to_h_u32((uint8_t*)&data);
+               buffer[i] = (data >> 16) & 0xffff;
+               i++;
+       }
+
+       /* read all complete words */
+       for (; i < (count & ~1); i+=2)
+       {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i*2, &data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* XXX: Assume AVR32 is BE */
+               data = be_to_h_u32((uint8_t*)&data);
+               buffer[i] = data & 0xffff;
+               buffer[i+1] = (data >> 16) & 0xffff;
+       }
+
+       /* last halfword */
+       if (i < count)
+       {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i*2, &data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* XXX: Assume AVR32 is BE */
+               data = be_to_h_u32((uint8_t*)&data);
+               buffer[i] = data & 0xffff;
+       }
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint8_t *buffer)
+{
+       int i, j, retval;
+       uint8_t data[4];
+       i = 0;
+
+       /* Do we have non-aligned bytes? */
+       if (addr & 3)
+       {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i, (uint32_t*)data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               for (j = addr & 3; (j < 4) && (i < count); j++, i++) 
+                               buffer[i] = data[3-j];
+       }
+
+
+       /* read all complete words */
+       for (; i < (count & ~3); i+=4)
+       {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i, (uint32_t*)data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               for (j = 0; j < 4; j++)
+                               buffer[i+j] = data[3-j];
+       }
+
+       /* remaining bytes */
+       if (i < count)
+       {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i, (uint32_t*)data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               for (j = 0; i + j < count; j++) 
+                               buffer[i+j] = data[3-j];
+       }
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint32_t *buffer)
+{
+       int i, retval;
+       uint32_t data;
+
+       for (i = 0; i < count; i++) 
+       {
+               /* XXX: Assume AVR32 is BE */
+               h_u32_to_be((uint8_t*)&data, buffer[i]);
+               retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i*4, data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+       }
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint16_t *buffer)
+{
+       int i, retval;
+       uint32_t data;
+       uint32_t data_out;
+
+       i = 0;
+
+       /*
+        * Do we have any non-aligned half-words?
+        */
+       if (addr & 3) {
+               /* 
+                * mwa_read will read whole world, no nead to fiddle
+                * with address. It will be truncated in set_addr
+                */
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr, &data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               data = be_to_h_u32((uint8_t*)&data);
+               data = (buffer[i] << 16) | (data & 0xffff);
+               h_u32_to_be((uint8_t*)&data_out, data);
+
+               retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr, data_out);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               i++;
+       }
+
+
+       /* write all complete words */
+       for (; i < (count & ~1); i+=2)
+       {
+               /* XXX: Assume AVR32 is BE */
+               data = (buffer[i+1] << 16) | buffer[i];
+               h_u32_to_be((uint8_t*)&data_out, data);
+
+               retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i*2, data_out);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       /* last halfword */
+       if (i < count)
+       {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i*2, &data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               data = be_to_h_u32((uint8_t*)&data);
+               data &= ~0xffff;
+               data |= buffer[i];
+               h_u32_to_be((uint8_t*)&data_out, data);
+
+               retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i*2, data_out);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
+
+int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint8_t *buffer)
+{
+       int i, j, retval;
+       uint32_t data;
+       uint32_t data_out;
+
+       i = 0;
+
+       /*
+        * Do we have any non-aligned bytes?
+        */
+       if (addr & 3) {
+               /* 
+                * mwa_read will read whole world, no nead to fiddle
+                * with address. It will be truncated in set_addr
+                */
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr, &data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               data = be_to_h_u32((uint8_t*)&data);
+               for (j = addr & 3; (j < 4) && (i < count); j++, i++) 
+               {
+                       data &= ~(0xff << j*8);
+                       data |= (buffer[i] << j*8);
+               }
+
+               h_u32_to_be((uint8_t*)&data_out, data);
+               retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr, data_out);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+
+       /* write all complete words */
+       for (; i < (count & ~3); i+=4)
+       {
+               data = 0;
+
+               for (j = 0; j < 4; j++)
+                       data |= (buffer[j+i] << j*8);
+
+               h_u32_to_be((uint8_t*)&data_out, data);
+
+               retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i, data_out);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       /*
+        * Write trailing bytes
+        */
+       if (i < count) {
+               retval = avr32_jtag_mwa_read(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr + i, &data);
+
+               if (retval != ERROR_OK)
+                       return retval;
+
+               data = be_to_h_u32((uint8_t*)&data);
+               for (j = 0; i < count; j++, i++)
+               {
+                       data &= ~(0xff << j*8);
+                       data |= (buffer[j+i] << j*8);
+               }
+
+               h_u32_to_be((uint8_t*)&data_out, data);
+
+               retval = avr32_jtag_mwa_write(jtag_info, SLAVE_HSB_UNCACHED,
+                               addr+i, data_out);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
diff --git a/src/target/avr32_mem.h b/src/target/avr32_mem.h
new file mode 100644 (file)
index 0000000..2a6f606
--- /dev/null
@@ -0,0 +1,37 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef AVR32_MEM
+#define AVR32_MEM
+
+int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint32_t *buffer);
+int avr32_jtag_read_memory16(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint16_t *buffer);
+int avr32_jtag_read_memory8(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint8_t *buffer);
+
+int avr32_jtag_write_memory32(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint32_t *buffer);
+int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint16_t *buffer);
+int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info, 
+               uint32_t addr, int count, uint8_t *buffer);
+
+#endif /* AVR32_MEM */
+
diff --git a/src/target/avr32_regs.c b/src/target/avr32_regs.c
new file mode 100644 (file)
index 0000000..eb283fc
--- /dev/null
@@ -0,0 +1,112 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "target.h"
+#include "jtag/jtag.h"
+#include "avr32_jtag.h"
+#include "avr32_regs.h"
+
+static int avr32_jtag_read_reg(struct avr32_jtag *jtag_info, int reg, 
+               uint32_t *val)
+{
+       int retval;
+       uint32_t dcsr;
+
+       retval = avr32_jtag_exec(jtag_info, MTDR(AVR32_OCDREG_DCCPU, reg));
+       if (retval != ERROR_OK)
+               return retval;
+
+       do {
+               retval = avr32_jtag_nexus_read(jtag_info, 
+                       AVR32_OCDREG_DCSR, &dcsr);
+
+               if (retval != ERROR_OK)
+                       return retval;
+       } while (!(dcsr & OCDREG_DCSR_CPUD));
+
+       retval = avr32_jtag_nexus_read(jtag_info, 
+                       AVR32_OCDREG_DCCPU, val);
+
+       return retval;
+}
+
+static int avr32_jtag_write_reg(struct avr32_jtag *jtag_info, int reg, 
+               uint32_t val)
+{
+       int retval;
+       uint32_t dcsr;
+
+       /* Restore Status reg */
+       retval = avr32_jtag_nexus_write(jtag_info, 
+                               AVR32_OCDREG_DCEMU, val);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = avr32_jtag_exec(jtag_info, MFDR(reg, AVR32_OCDREG_DCEMU));
+       if (retval != ERROR_OK)
+               return retval;
+       do {
+               retval = avr32_jtag_nexus_read(jtag_info, 
+                       AVR32_OCDREG_DCSR, &dcsr);
+       } while (!(dcsr & OCDREG_DCSR_EMUD) && (retval == ERROR_OK));
+
+       return retval;
+}
+
+
+
+int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs)
+{
+       int i, retval;
+
+       /* read core registers */
+       for (i = 0; i < AVR32NUMCOREREGS - 1; i++) 
+               avr32_jtag_read_reg(jtag_info, i, regs + i);
+
+       /* read status register */
+       retval = avr32_jtag_exec(jtag_info, MFSR(0, 0));
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = avr32_jtag_read_reg(jtag_info, 0, regs + AVR32_REG_SR);
+
+       return retval;
+}
+
+int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs)
+{
+       int i, retval;
+
+       retval = avr32_jtag_write_reg(jtag_info, 0, regs[AVR32_REG_SR]);
+       /* Restore Status reg */
+       retval = avr32_jtag_exec(jtag_info, MTSR(0, 0));
+       if (retval != ERROR_OK)
+               return retval;
+
+       /*
+        * And now the rest of registers
+        */
+       for (i = 0; i < AVR32NUMCOREREGS - 1; i++) 
+               avr32_jtag_write_reg(jtag_info, i, regs[i]);
+
+       return ERROR_OK;
+}
diff --git a/src/target/avr32_regs.h b/src/target/avr32_regs.h
new file mode 100644 (file)
index 0000000..01ea3ed
--- /dev/null
@@ -0,0 +1,46 @@
+/***************************************************************************
+ *   Copyright (C) 2010 by Oleksandr Tymoshenko <gonzo@bluezbox.com>       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef AVR32_REGS
+#define AVR32_REGS
+
+enum avr32_reg_nums {
+       AVR32_REG_R0 = 0,
+       AVR32_REG_R1,
+       AVR32_REG_R2,
+       AVR32_REG_R3,
+       AVR32_REG_R4,
+       AVR32_REG_R5,
+       AVR32_REG_R6,
+       AVR32_REG_R7,
+       AVR32_REG_R8,
+       AVR32_REG_R9,
+       AVR32_REG_R10,
+       AVR32_REG_R11,
+       AVR32_REG_R12,
+       AVR32_REG_SP,
+       AVR32_REG_LR,
+       AVR32_REG_PC,
+       AVR32_REG_SR,
+};
+
+int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs);
+int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs);
+
+#endif /* AVR32_REGS */
+
index 16caea5fc9a04c37a38106bf0c7b7905de185ea3..c37432a30ca0ad7a6d6476250585b116e1a3cfe4 100644 (file)
@@ -70,6 +70,7 @@ extern struct target_type mips_m4k_target;
 extern struct target_type avr_target;
 extern struct target_type dsp563xx_target;
 extern struct target_type testee_target;
+extern struct target_type avr32_ap7k_target;
 
 static struct target_type *target_types[] =
 {
@@ -90,6 +91,7 @@ static struct target_type *target_types[] =
        &avr_target,
        &dsp563xx_target,
        &testee_target,
+       &avr32_ap7k_target,
        NULL,
 };
 

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)