- merged support for Cortex-M3 from cortex-m3 branch (thanks to Magnus Lundin)
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 14 Jun 2007 14:48:22 +0000 (14:48 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 14 Jun 2007 14:48:22 +0000 (14:48 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@170 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/flash/Makefile.am
src/flash/flash.c
src/target/Makefile.am
src/target/armv7m.c [new file with mode: 0644]
src/target/armv7m.h [new file with mode: 0644]
src/target/cortex_m3.c [new file with mode: 0644]
src/target/cortex_m3.h [new file with mode: 0644]
src/target/cortex_swjdp.c [new file with mode: 0644]
src/target/cortex_swjdp.h [new file with mode: 0644]
src/target/target.c

index 8f99e05e98119f31d8472f7c22dc3526be260e05..8d30790b45ff4b3bf007b8af41b012e8d76edbc0 100644 (file)
@@ -1,5 +1,5 @@
 INCLUDES = -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target $(all_includes)
 METASOURCES = AUTO
 noinst_LIBRARIES = libflash.a
-libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c
-noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h
+libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c stellaris.c
+noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h stellaris.h
index fecb89b72d3d23c749c341bf3c0fc40b0bea92eb..3c368f3f3532552295fbf1efc369fc006e39f7f5 100644 (file)
@@ -55,6 +55,7 @@ extern flash_driver_t cfi_flash;
 extern flash_driver_t at91sam7_flash;
 extern flash_driver_t str7x_flash;
 extern flash_driver_t str9x_flash;
+extern flash_driver_t stellaris_flash;
 
 flash_driver_t *flash_drivers[] =
 {
@@ -63,6 +64,7 @@ flash_driver_t *flash_drivers[] =
        &at91sam7_flash,
        &str7x_flash,
        &str9x_flash,
+       &stellaris_flash,
        NULL,
 };
 
index b1e6f91924640f6730d2c8a9e0047585f100ea53..c6cf95259a54ec6947f4063fd2b5a39fb6cf440e 100644 (file)
@@ -3,7 +3,7 @@ METASOURCES = AUTO
 noinst_LIBRARIES = libtarget.a
 libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \
        arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \
-       arm966e.c arm926ejs.c etb.c xscale.c arm_simulator.c image.c
+       arm966e.c arm926ejs.c etb.c xscale.c arm_simulator.c image.c armv7m.c cortex_m3.c cortex_swjdp.c
 noinst_HEADERS = target.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \
                arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \
-               arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h image.h
+               arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h image.h armv7m.h cortex_m3.h cortex_swjdp.h
diff --git a/src/target/armv7m.c b/src/target/armv7m.c
new file mode 100644 (file)
index 0000000..d77eb0b
--- /dev/null
@@ -0,0 +1,590 @@
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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 "replacements.h"
+
+#include "armv7m.h"
+#include "register.h"
+#include "target.h"
+#include "log.h"
+#include "jtag.h"
+#include "arm_jtag.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+char* armv7m_mode_strings[] =
+{
+       "Handler", "Thread"
+};
+
+char* armv7m_state_strings[] =
+{
+       "Thumb", "Debug"
+};
+
+char* armv7m_exception_strings[] =
+{
+       "", "Reset", "NMI", "HardFault", "MemManage", "BusFault", "UsageFault", "RESERVED", "RESERVED", "RESERVED", "RESERVED",
+       "SVCall", "DebugMonitor", "RESERVED", "PendSV", "SysTick"
+};
+
+char* armv7m_core_reg_list[] =
+{
+/* Registers accessed through core debug */
+       "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",
+       "sp", "lr", "pc",
+       "xPSR", "msp", "psp",
+/* Registers accessed through MSR instructions */
+//     "apsr", "iapsr", "ipsr", "epsr",
+       "primask", "basepri", "faultmask", "control"
+};
+
+char* armv7m_core_dbgreg_list[] =
+{
+/* Registers accessed through core debug */
+       "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",
+       "sp", "lr", "pc",
+       "xPSR", "msp", "psp",
+/* Registers accessed through MSR instructions */
+//     "dbg_apsr", "iapsr", "ipsr", "epsr",
+       "primask", "basepri", "faultmask", "dbg_control"
+};
+
+u8 armv7m_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+reg_t armv7m_gdb_dummy_fp_reg =
+{
+       "GDB dummy floating-point register", armv7m_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
+};
+
+armv7m_core_reg_t armv7m_core_reg_list_arch_info[] = 
+{
+       /*  CORE_GP are accesible using the core debug registers */
+       {0, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {1, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {2, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {3, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {4, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {5, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {6, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {7, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {8, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {9, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {10, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {11, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {12, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {13, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+       {14, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},     
+       {15, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
+
+       {16, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* xPSR */
+       {17, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* MSP */
+       {18, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* PSP */
+
+       /*  CORE_SP are accesible using MSR and MRS instructions */
+//     {0x00, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* APSR */
+//     {0x01, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* IAPSR */
+//     {0x05, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* IPSR */
+//     {0x06, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* EPSR */
+
+       {0x10, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* PRIMASK */
+       {0x11, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* BASEPRI */
+       {0x13, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* FAULTMASK */
+       {0x14, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}  /* CONTROL */
+};
+
+int armv7m_core_reg_arch_type = -1;
+
+
+/* Keep different contexts for the process being debugged and debug algorithms */
+enum armv7m_runcontext armv7m_get_context(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       
+       if (armv7m->process_context == armv7m->core_cache) return ARMV7M_PROCESS_CONTEXT;
+       if (armv7m->debug_context == armv7m->core_cache) return ARMV7M_DEBUG_CONTEXT;
+       
+       ERROR("Invalid runcontext");
+       exit(-1);
+}
+
+int armv7m_use_context(target_t *target, enum armv7m_runcontext new_ctx)
+{
+       int i;
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       
+       if ((target->state != TARGET_HALTED) && (target->state != TARGET_RESET))
+       {
+               WARNING("target not halted, switch context ");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (new_ctx == armv7m_get_context(target))
+               return ERROR_OK;
+               
+       switch (new_ctx)
+       {
+               case ARMV7M_PROCESS_CONTEXT:
+                        armv7m->core_cache = armv7m->process_context;
+                        break;
+               case ARMV7M_DEBUG_CONTEXT:
+                        armv7m->core_cache = armv7m->debug_context;
+                        break;
+               default:
+                       ERROR("Invalid runcontext");
+                       exit(-1);               
+       } 
+       /* Mark registers in new context as dirty to force reload when run */
+       
+       for (i = 0; i < armv7m->core_cache->num_regs-1; i++) /* EXCLUDE CONTROL TODOLATER : CHECK THIS */
+       {
+               armv7m->core_cache->reg_list[i].dirty = 1;
+       }
+       
+       return ERROR_OK;
+}
+
+/* Core state functions */
+char enamebuf[32];
+char *armv7m_exception_string(int number)
+{
+       if ((number<0)|(number>511)) return "Invalid exception";
+       if (number<16) return armv7m_exception_strings[number];
+       sprintf(enamebuf,"External Interrupt(%i)",number-16);
+       return enamebuf;
+}
+
+int armv7m_get_core_reg(reg_t *reg)
+{
+       int retval;
+       armv7m_core_reg_t *armv7m_reg = reg->arch_info;
+       target_t *target = armv7m_reg->target;
+       armv7m_common_t *armv7m_target = target->arch_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       retval = armv7m_target->read_core_reg(target, armv7m_reg->num);
+       
+       return retval;
+}
+
+int armv7m_set_core_reg(reg_t *reg, u8 *buf)
+{
+       armv7m_core_reg_t *armv7m_reg = reg->arch_info;
+       target_t *target = armv7m_reg->target;
+       armv7m_common_t *armv7m_target = target->arch_info;
+       u32 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;
+}
+
+int armv7m_read_core_reg(struct target_s *target, int num)
+{
+       u32 reg_value;
+       int retval;
+       armv7m_core_reg_t * armv7m_core_reg;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+               
+       if ((num < 0) || (num >= ARMV7NUMCOREREGS))
+               return ERROR_INVALID_ARGUMENTS;
+
+       armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
+       retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, &reg_value);
+       buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
+       armv7m->core_cache->reg_list[num].valid=1;
+       armv7m->core_cache->reg_list[num].dirty=0;
+               
+       return ERROR_OK;        
+}
+
+int armv7m_write_core_reg(struct target_s *target, int num)
+{
+       int retval;
+       u32 reg_value;
+       armv7m_core_reg_t * armv7m_core_reg;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+
+       if ((num < 0) || (num >= ARMV7NUMCOREREGS))
+               return ERROR_INVALID_ARGUMENTS;
+       
+       
+       reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
+       armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
+       retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, reg_value);
+       if (retval != ERROR_OK)
+       {
+                       ERROR("JTAG failure");
+                       armv7m->core_cache->reg_list[num].dirty=1;
+                       return ERROR_JTAG_DEVICE_ERROR;
+       }
+       DEBUG("write core reg %i value 0x%x",num ,reg_value);
+       armv7m->core_cache->reg_list[num].valid=1;
+       armv7m->core_cache->reg_list[num].dirty=0;
+       
+       return ERROR_OK;
+       
+}
+
+
+
+int armv7m_invalidate_core_regs(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       int i;
+       
+       for (i = 0; i < armv7m->core_cache->num_regs; i++)
+       {
+               armv7m->core_cache->reg_list[i].valid = 0;
+               armv7m->core_cache->reg_list[i].dirty = 0;
+       }
+       
+       return ERROR_OK;
+}
+
+
+int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       int i;
+       
+       
+       if (target->state != TARGET_HALTED)
+       {
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       
+       *reg_list_size = 26;
+       *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
+       
+       /* TODOLATER correct list of registers, names ? */
+       for (i = 0; i < *reg_list_size; i++)
+       {
+               if (i<ARMV7NUMCOREREGS)
+                       (*reg_list)[i] = &armv7m->process_context->reg_list[i];
+                       //(*reg_list)[i] = &armv7m->core_cache->reg_list[i];
+               else
+                       (*reg_list)[i] = &armv7m_gdb_dummy_fp_reg;
+       }
+       /* ARMV7M is always in thumb mode, try to make GDB understand this if it does not support this arch */
+       //armv7m->core_cache->reg_list[15].value[0] |= 1;       
+       armv7m->process_context->reg_list[15].value[0] |= 1;    
+       //armv7m->core_cache->reg_list[ARMV7M_xPSR].value[0] = (1<<5);
+       //armv7m->process_context->reg_list[ARMV7M_xPSR].value[0] = (1<<5);
+       (*reg_list)[25] = &armv7m->process_context->reg_list[ARMV7M_xPSR];      
+       //(*reg_list)[25] = &armv7m->process_context->reg_list[ARMV7M_xPSR];    
+       return ERROR_OK;
+}
+
+int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
+{
+       // get pointers to arch-specific information
+       armv7m_common_t *armv7m = target->arch_info;
+       armv7m_algorithm_t *armv7m_algorithm_info = arch_info;
+       enum armv7m_state core_state = armv7m->core_state;
+       enum armv7m_mode core_mode = armv7m->core_mode;
+       int retval = ERROR_OK;
+       u32 pc;
+       int exit_breakpoint_size = 0;
+       int i;
+               
+       armv7m->core_state = core_state;
+       armv7m->core_mode = core_mode;
+
+       if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
+       {
+               ERROR("current target isn't an ARMV7M target");
+               return ERROR_TARGET_INVALID;
+       }
+       
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       
+       /* refresh core register cache */
+       /* Not needed if core register cache is always consistent with target process state */ 
+       armv7m_use_context(target, ARMV7M_DEBUG_CONTEXT);
+       
+       for (i = 0; i < num_mem_params; i++)
+       {
+               target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
+       }
+       
+       for (i = 0; i < num_reg_params; i++)
+       {
+               reg_t *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
+               //reg_t *reg = register_get_by_name(armv7m->debug_context, reg_params[i].reg_name, 0);
+               //armv7m_core_reg_t * armv7m_core_reg = reg->arch_info;
+               u32 regvalue;
+               
+               if (!reg)
+               {
+                       ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
+                       exit(-1);
+               }
+               
+               if (reg->size != reg_params[i].size)
+               {
+                       ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
+                       exit(-1);
+               }
+               
+               regvalue = buf_get_u32(reg_params[i].value, 0, 32);
+               //armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, regvalue);
+               armv7m_set_core_reg(reg, reg_params[i].value);
+       }
+       
+       /* ARMV7M always runs in Tumb state */
+       exit_breakpoint_size = 2;
+       if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_SOFT)) != ERROR_OK)
+       {
+               ERROR("can't add breakpoint to finish algorithm execution");
+               return ERROR_TARGET_FAILURE;
+       }
+       
+       /* This code relies on the target specific  resume() and  poll()->debug_entry() 
+       sequence to write register values to the processor and the read them back */
+       target->type->resume(target, 0, entry_point, 1, 1);
+       target->type->poll(target);
+       
+       while (target->state != TARGET_HALTED)
+       {
+               usleep(5000);
+               target->type->poll(target);
+               if ((timeout_ms -= 5) <= 0)
+               {
+                       ERROR("timeout waiting for algorithm to complete, trying to halt target");
+                       target->type->halt(target);
+                       timeout_ms = 1000;
+                       while (target->state != TARGET_HALTED)
+                       {
+                               usleep(10000);
+                               target->type->poll(target);
+                               if ((timeout_ms -= 10) <= 0)
+                               {
+                                       ERROR("target didn't reenter debug state, exiting");
+                                       exit(-1);
+                               }
+                       }
+                       armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
+                       DEBUG("failed algoritm halted at 0x%x ",pc); 
+                       retval = ERROR_TARGET_TIMEOUT;
+               }
+       }
+       
+       breakpoint_remove(target, exit_point);
+       
+       /* Read memory values to mem_params[] */
+       for (i = 0; i < num_mem_params; i++)
+       {
+               if (mem_params[i].direction != PARAM_OUT)
+                       target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
+       }
+       
+       /* Copy core register values to reg_params[] */
+       for (i = 0; i < num_reg_params; i++)
+       {
+               if (reg_params[i].direction != PARAM_OUT)
+               {
+                       //reg_t *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
+                       reg_t *reg = register_get_by_name(armv7m->debug_context, reg_params[i].reg_name, 0);
+                       u32 regvalue;
+               
+                       if (!reg)
+                       {
+                               ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
+                               exit(-1);
+                       }
+                       
+                       if (reg->size != reg_params[i].size)
+                       {
+                               ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
+                               exit(-1);
+                       }
+                       
+                       armv7m_core_reg_t * armv7m_core_reg = reg->arch_info;
+                       //armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, &regvalue);
+                       //buf_set_u32(reg_params[i].value, 0, 32, regvalue);
+                       buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
+               }
+       }
+       
+       /* Mark all core registers !! except control !! as valid but dirty */
+       /* This will be done by armv7m_use_context in resume function */
+       //for (i = 0; i < armv7m->core_cache->num_regs-1; i++)
+       //{
+       //      armv7m->core_cache->reg_list[i].dirty = 1;
+       //}
+
+       
+       // ????armv7m->core_state = core_state;
+       // ????armv7m->core_mode = core_mode;
+
+
+       return retval;
+}
+
+int armv7m_arch_state(struct target_s *target, char *buf, int buf_size)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       
+       snprintf(buf, buf_size,
+                        "target halted in %s state due to %s, current mode: %s %s\nxPSR: 0x%8.8x pc: 0x%8.8x",
+                        armv7m_state_strings[armv7m->core_state],
+                        target_debug_reason_strings[target->debug_reason],
+                        armv7m_mode_strings[armv7m->core_mode],
+                        armv7m_exception_string(armv7m->exception_number),
+                        buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
+                        buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32));
+       
+       return ERROR_OK;
+}
+
+reg_cache_t *armv7m_build_reg_cache(target_t *target)
+{
+
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       arm_jtag_t *jtag_info = &armv7m->jtag_info;
+
+       int num_regs = ARMV7NUMCOREREGS;
+       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+       reg_cache_t *cache = malloc(sizeof(reg_cache_t));
+       reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
+       armv7m_core_reg_t *arch_info = malloc(sizeof(armv7m_core_reg_t) * num_regs);
+       int i;
+       
+       if (armv7m_core_reg_arch_type == -1)
+               armv7m_core_reg_arch_type = register_reg_arch_type(armv7m_get_core_reg, armv7m_set_core_reg);
+               
+       /* Build the process context cache */ 
+       cache->name = "arm v7m registers";
+       cache->next = NULL;
+       cache->reg_list = reg_list;
+       cache->num_regs = num_regs;
+       (*cache_p) = cache;
+       armv7m->core_cache = cache;
+       armv7m->process_context = cache;
+       
+       for (i = 0; i < num_regs; i++)
+       {
+               arch_info[i] = armv7m_core_reg_list_arch_info[i];
+               arch_info[i].target = target;
+               arch_info[i].armv7m_common = armv7m;
+               reg_list[i].name = armv7m_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].bitfield_desc = NULL;
+               reg_list[i].num_bitfields = 0;
+               reg_list[i].arch_type = armv7m_core_reg_arch_type;
+               reg_list[i].arch_info = &arch_info[i];
+       }
+
+       /* Build the debug context cache*/
+       cache = malloc(sizeof(reg_cache_t));
+       reg_list = malloc(sizeof(reg_t) * num_regs);
+
+       cache->name = "arm v7m debug registers";
+       cache->next = NULL;
+       cache->reg_list = reg_list;
+       cache->num_regs = num_regs;
+       armv7m->debug_context = cache;
+       armv7m->process_context->next = cache;
+
+       for (i = 0; i < num_regs; i++)
+       {
+               reg_list[i].name = armv7m_core_dbgreg_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].bitfield_desc = NULL;
+               reg_list[i].num_bitfields = 0;
+               reg_list[i].arch_type = armv7m_core_reg_arch_type;
+               reg_list[i].arch_info = &arch_info[i];
+       }
+    return cache;
+}
+
+int armv7m_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       
+       armv7m_build_reg_cache(target);
+       
+       return ERROR_OK;
+       
+}
+
+int armv7m_init_arch_info(target_t *target, armv7m_common_t *armv7m)
+{
+
+       /* register arch-specific functions */
+       
+       target->arch_info = armv7m;
+       armv7m->core_state = ARMV7M_STATE_THUMB;
+       armv7m->read_core_reg = armv7m_read_core_reg;
+       armv7m->write_core_reg = armv7m_write_core_reg;
+       
+       return ERROR_OK;
+}
+
+
+int armv7m_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       
+       return ERROR_OK;
+
+}
diff --git a/src/target/armv7m.h b/src/target/armv7m.h
new file mode 100644 (file)
index 0000000..cf2b3c7
--- /dev/null
@@ -0,0 +1,248 @@
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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 ARMV7M_COMMON_H
+#define ARMV7M_COMMON_H
+
+#include "register.h"
+#include "target.h"
+#include "arm_jtag.h"
+
+
+enum armv7m_mode
+{
+       ARMV7M_MODE_HANDLER = 0, 
+       ARMV7M_MODE_THREAD = 1, 
+       ARMV7M_MODE_ANY = -1
+};
+
+extern char* armv7m_mode_strings[];
+
+enum armv7m_state
+{
+       ARMV7M_STATE_THUMB,
+       ARMV7M_STATE_DEBUG,
+};
+
+enum armv7m_regtype
+{
+       ARMV7M_REGISTER_CORE_GP,
+       ARMV7M_REGISTER_CORE_SP,
+       ARMV7M_REGISTER_MEMMAP
+};
+
+enum armv7m_runcontext
+{
+       ARMV7M_PROCESS_CONTEXT,
+       ARMV7M_DEBUG_CONTEXT
+};
+
+extern char* armv7m_state_strings[];
+
+//#define ARMV7NUMCOREREGS 23
+
+/* offsets into armv7m core register cache */
+enum 
+{
+       ARMV7M_PC = 15,
+       ARMV7M_xPSR = 16,
+       ARMV7M_MSP ,
+       ARMV7M_PSP ,
+       ARMV7M_PRIMASK ,
+       ARMV7M_BASEPRI,
+       ARMV7M_FAULTMASK,
+       ARMV7M_CONTROL,
+       ARMV7NUMCOREREGS
+};
+
+#define ARMV7M_COMMON_MAGIC 0x2A452A45
+
+typedef struct armv7m_common_s
+{
+       int common_magic;
+       reg_cache_t *core_cache;
+       reg_cache_t *process_context;
+       reg_cache_t *debug_context;
+       enum armv7m_mode core_mode;
+       enum armv7m_state core_state;
+       int  exception_number;
+       int (*full_context)(struct target_s *target);
+       /* Direct processor core register read and writes */
+       int (*load_core_reg_u32)(struct target_s *target, enum armv7m_regtype type, u32 num, u32 *value);
+       int (*store_core_reg_u32)(struct target_s *target, enum armv7m_regtype type, u32 num, u32 value);
+       /* register cache to processor synchronization */
+       int (*read_core_reg)(struct target_s *target, int num);
+       int (*write_core_reg)(struct target_s *target, int num);
+       /* get or set register through cache, return error if target is running and synchronisation is impossible */
+       int (*get_core_reg_32)(struct target_s *target, int num, u32* value);
+       int (*set_core_reg_32)(struct target_s *target, int num, u32 value);
+
+       arm_jtag_t jtag_info;
+       reg_cache_t *eice_cache;
+       reg_cache_t *etm_cache;
+
+       int (*examine_debug_reason)(target_t *target);
+       
+       void (*change_to_arm)(target_t *target, u32 *r0, u32 *pc);
+       
+//     void (*read_core_regs)(target_t *target, u32 mask, u32 *core_regs[16]);
+//     void (*read_core_regs_target_buffer)(target_t *target, u32 mask, void *buffer, int size);
+//     void (*write_core_regs)(target_t *target, u32 mask, u32 core_regs[16]);
+
+/*
+       void (*write_xpsr_im8)(target_t *target, u8 xpsr_im, int rot, int spsr);
+       
+       void (*load_word_regs)(target_t *target, u32 mask);
+       void (*load_hword_reg)(target_t *target, int num);
+       void (*load_byte_reg)(target_t *target, int num);
+
+       void (*store_word_regs)(target_t *target, u32 mask);
+       void (*store_hword_reg)(target_t *target, int num);
+       void (*store_byte_reg)(target_t *target, int num);
+       
+       void (*write_pc)(target_t *target, u32 pc);
+       void (*branch_resume)(target_t *target);
+*/     
+
+       void (*pre_debug_entry)(target_t *target);
+       void (*post_debug_entry)(target_t *target);
+       
+       void (*pre_restore_context)(target_t *target);
+       void (*post_restore_context)(target_t *target);
+
+       void *arch_info;
+} armv7m_common_t;
+
+typedef struct armv7m_algorithm_s
+{
+       int common_magic;
+               
+       enum armv7m_mode core_mode;
+       enum armv7m_state core_state;
+} armv7m_algorithm_t;
+
+typedef struct armv7m_core_reg_s
+{
+       u32 num;
+       enum armv7m_regtype type;
+       enum armv7m_mode mode;
+       target_t *target;
+       armv7m_common_t *armv7m_common;
+} armv7m_core_reg_t;
+
+extern reg_cache_t *armv7m_build_reg_cache(target_t *target);
+extern enum armv7m_mode armv7m_number_to_mode(int number);
+extern int armv7m_mode_to_number(enum armv7m_mode mode);
+
+extern int armv7m_arch_state(struct target_s *target, char *buf, int buf_size);
+extern int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size);
+extern int armv7m_invalidate_core_regs(target_t *target);
+
+extern int armv7m_register_commands(struct command_context_s *cmd_ctx);
+extern int armv7m_init_arch_info(target_t *target, armv7m_common_t *armv7m);
+
+extern int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info);
+
+extern int armv7m_invalidate_core_regs(target_t *target);
+
+
+
+
+/* Thumb mode instructions
+ */
+/* Move to Register from Special Register  (Thumb mode) 32 bit Thumb2 instruction
+ * Rd: destination register
+ * SYSm: source special register
+ */
+#define ARMV7M_T_MRS(Rd, SYSm) ((0xF3EF) | ((0x8000 | (Rd<<8) | SYSm) << 16)) 
+
+/* Move from Register from Special Register  (Thumb mode) 32 bit Thumb2 instruction
+ * Rd: source register
+ * SYSm: destination special register
+ */
+#define ARMV7M_T_MSR(SYSm, Rn) ((0xF380 | ( Rn<<8 )) | ((0x8800 | SYSm) << 16)) 
+
+/* Change Processor State. The instruction modifies the PRIMASK and FAULTMASK 
+ * special-purpose register values  (Thumb mode) 16 bit Thumb2 instruction
+ * Rd: source register
+ * IF: 
+ */
+#define I_FLAG 2
+#define F_FLAG 1  
+#define ARMV7M_T_CPSID(IF)     ((0xB660 | (1<<8) | (IF&0x3)) | ((0xB660 | (1<<8) | (IF&0x3)) << 16)) 
+#define ARMV7M_T_CPSIE(IF)     ((0xB660 | (0<<8) | (IF&0x3)) | ((0xB660 | (0<<8) | (IF&0x3)) << 16)) 
+
+/* Breakpoint (Thumb mode) v5 onwards
+ * Im: immediate value used by debugger
+ */
+#define ARMV7M_T_BKPT(Im)      ((0xBE00 | Im ) | ((0xBE00 | Im ) << 16))
+
+/* Store register (Thumb mode)
+ * Rd: source register
+ * Rn: base register
+ */
+#define ARMV7M_T_STR(Rd, Rn)   ((0x6000 | Rd | (Rn << 3)) | ((0x6000 | Rd | (Rn << 3)) << 16))
+
+/* Load register (Thumb state)
+ * Rd: destination register
+ * Rn: base register
+ */
+#define ARMV7M_T_LDR(Rd, Rn)   ((0x6800 | (Rn << 3) | Rd) | ((0x6800 | (Rn << 3) | Rd) << 16))
+
+/* Load multiple (Thumb state)
+ * Rn: base register
+ * List: for each bit in list: store register
+ */
+#define ARMV7M_T_LDMIA(Rn, List) ((0xc800 | (Rn << 8) | List) | ((0xc800 | (Rn << 8) | List) << 16))
+/* Load register with PC relative addressing
+ * Rd: register to load
+ */
+#define ARMV7M_T_LDR_PCREL(Rd) ((0x4800 | (Rd << 8)) | ((0x4800 | (Rd << 8)) << 16)) 
+/* Move hi register (Thumb mode)
+ * Rd: destination register
+ * Rm: source register
+ */
+#define ARMV7M_T_MOV(Rd, Rm)   ((0x4600 | (Rd & 0x7) | ((Rd & 0x8) << 4) | ((Rm & 0x7) << 3) | ((Rm & 0x8) << 3)) | ((0x4600 | (Rd & 0x7) | ((Rd & 0x8) << 4) | ((Rm & 0x7) << 3) | ((Rm & 0x8) << 3)) << 16))
+
+/* No operation (Thumb mode)
+ */
+#define ARMV7M_T_NOP   (0x46c0 | (0x46c0 << 16))
+
+/* Move immediate to register (Thumb state)
+ * Rd: destination register
+ * Im: 8-bit immediate value
+ */
+#define ARMV7M_T_MOV_IM(Rd, Im)        ((0x2000 | (Rd << 8) | Im) | ((0x2000 | (Rd << 8) | Im) << 16))
+
+/* Branch and Exchange
+ * Rm: register containing branch target
+ */
+#define ARMV7M_T_BX(Rm)                ((0x4700 | (Rm << 3)) | ((0x4700 | (Rm << 3)) << 16))
+
+/* Branch (Thumb state)
+ * Imm: Branch target
+ */
+#define ARMV7M_T_B(Imm)        ((0xe000 | Imm) | ((0xe000 | Imm) << 16))
+
+#endif /* ARMV7M_H */
diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c
new file mode 100644 (file)
index 0000000..93521cf
--- /dev/null
@@ -0,0 +1,1413 @@
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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
+
+#define USE_SP_REGS
+
+#include "replacements.h"
+
+#include "cortex_m3.h"
+
+#include "register.h"
+#include "target.h"
+#include "log.h"
+#include "jtag.h"
+#include "arm_jtag.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/* cli handling */
+int cortex_m3_register_commands(struct command_context_s *cmd_ctx);
+
+/* forward declarations */
+void cortex_m3_unset_all_breakpoints_and_watchpoints(struct target_s *target);
+void cortex_m3_enable_breakpoints(struct target_s *target);
+void cortex_m3_enable_watchpoints(struct target_s *target);
+void cortex_m3_disable_bkpts_and_wpts(struct target_s *target);
+int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int cortex_m3_quit();
+int cortex_m3_load_core_reg_u32(target_t *target, enum armv7m_regtype type, u32 num, u32 *value);
+int cortex_m3_store_core_reg_u32(target_t *target, enum armv7m_regtype type, u32 num, u32 value);
+               
+target_type_t cortexm3_target =
+{
+       .name = "cortex_m3",
+
+       .poll = cortex_m3_poll,
+       .arch_state = armv7m_arch_state,
+
+       .halt = cortex_m3_halt,
+       .resume = cortex_m3_resume,
+       .step = cortex_m3_step,
+
+       .assert_reset = cortex_m3_assert_reset,
+       .deassert_reset = cortex_m3_deassert_reset,
+       .soft_reset_halt = cortex_m3_soft_reset_halt,
+
+       .get_gdb_reg_list = armv7m_get_gdb_reg_list,
+
+       .read_memory = cortex_m3_read_memory,
+       .write_memory = cortex_m3_write_memory,
+       .bulk_write_memory = cortex_m3_bulk_write_memory,
+
+       .run_algorithm = armv7m_run_algorithm,
+       
+       .add_breakpoint = cortex_m3_add_breakpoint,
+       .remove_breakpoint = cortex_m3_remove_breakpoint,
+       .add_watchpoint = cortex_m3_add_watchpoint,
+       .remove_watchpoint = cortex_m3_remove_watchpoint,
+
+       .register_commands = cortex_m3_register_commands,
+       .target_command = cortex_m3_target_command,
+       .init_target = cortex_m3_init_target,
+       .quit = cortex_m3_quit
+};
+
+int cortex_m3_clear_halt(target_t *target)
+{
+
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+    
+    /* Read Debug Fault Status Register */
+    ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
+    /* Write Debug Fault Status Register to enable processing to resume ?? Try with and without this !! */
+    ahbap_write_system_atomic_u32(swjdp, NVIC_DFSR, cortex_m3->nvic_dfsr);
+    DEBUG(" NVIC_DFSR 0x%x",cortex_m3->nvic_dfsr);
+
+    return ERROR_OK;
+}
+
+int cortex_m3_single_step_core(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+
+       if (!(cortex_m3->dcb_dhcsr&C_MASKINTS))
+               ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN );
+       ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN );
+       cortex_m3->dcb_dhcsr |= C_MASKINTS;
+       DEBUG("");
+       cortex_m3_clear_halt(target);
+       
+       return ERROR_OK;
+}
+
+int cortex_m3_exec_opcode(target_t *target,u32 opcode, int len /* MODE, r0_invalue, &r0_outvalue */ )
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       u32 savedram;
+       int retvalue;
+
+       {
+               ahbap_read_system_u32(swjdp, 0x20000000, &savedram);
+               ahbap_write_system_u32(swjdp, 0x20000000, opcode);
+               ahbap_write_coreregister_u32(swjdp, 0x20000000, 15);
+               cortex_m3_single_step_core(target);
+               armv7m->core_cache->reg_list[15].dirty=1;
+               retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram);          
+       }
+       
+       return retvalue;
+}
+
+/* Enable interrupts */
+int cortex_m3_cpsie(target_t *target, u32 IF)
+{
+       return cortex_m3_exec_opcode(target, ARMV7M_T_CPSIE(IF), 2);
+}
+
+/* Disable interrupts */
+int cortex_m3_cpsid(target_t *target, u32 IF)
+{
+       return cortex_m3_exec_opcode(target, ARMV7M_T_CPSID(IF), 2);
+}
+
+int cortex_m3_endreset_event(target_t *target)
+{
+       int i;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       cortex_m3_fp_comparator_t *fp_list = cortex_m3->fp_comparator_list; 
+       cortex_m3_dwt_comparator_t * dwt_list = cortex_m3->dwt_comparator_list;
+
+       DEBUG("");
+       /* Enable debug requests */
+       ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
+       if (!(cortex_m3->dcb_dhcsr&C_DEBUGEN))
+               ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN );
+       /* Enable trace and dwt */
+       ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA|VC_HARDERR|VC_BUSERR|VC_CORERESET );
+       /* Monitor bus faults */
+       ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA );
+
+       /* Enable FPB */
+       target_write_u32(target, FP_CTRL, 3);
+
+       /* Restore FPB registers */
+       for (i=0;i<cortex_m3->fp_num_code+cortex_m3->fp_num_lit;i++)
+       {
+               target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
+       }
+       
+       /* Restore DWT registers */
+       for (i=0;i<cortex_m3->dwt_num_comp;i++)
+       {
+               target_write_u32(target, dwt_list[i].dwt_comparator_address, dwt_list[i].comp);
+               target_write_u32(target, dwt_list[i].dwt_comparator_address|0x4, dwt_list[i].mask);
+               target_write_u32(target, dwt_list[i].dwt_comparator_address|0x8, dwt_list[i].function);
+       }
+       
+       /* Make sure working_areas are all free */
+       target_free_all_working_areas(target);
+       
+       /* We are in process context */
+       armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
+       armv7m_invalidate_core_regs(target);
+       return ERROR_OK;
+}
+
+int cortex_m3_examine_debug_reason(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+
+/* THIS IS NOT GOOD, TODO - better logic for detection of debug state reason */
+       /* only check the debug reason if we don't know it already */
+       
+       if ((target->debug_reason != DBG_REASON_DBGRQ)
+                       && (target->debug_reason != DBG_REASON_SINGLESTEP))
+       {
+
+               /*  INCOPMPLETE */
+
+               if (cortex_m3->nvic_dfsr & 0x2)
+               {
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       if (cortex_m3->nvic_dfsr & 0x4)
+                               target->debug_reason = DBG_REASON_WPTANDBKPT;
+               }
+               else if (cortex_m3->nvic_dfsr & 0x4)
+                       target->debug_reason = DBG_REASON_WATCHPOINT;
+       }
+
+       return ERROR_OK;
+}
+
+int cortex_m3_examine_exception_reason(target_t *target)
+{
+       u32 shcsr,except_sr,cfsr=-1,except_ar=-1;
+
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+
+       ahbap_read_system_u32(swjdp, NVIC_SHCSR, &shcsr);
+       switch (armv7m->exception_number)
+       {
+               case 2: /* NMI */
+                       break;
+               case 3: /* Hard Fault */
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_HFSR, &except_sr);
+                       if (except_sr&0x40000000)
+                       {
+                               ahbap_read_system_u32(swjdp, NVIC_CFSR, &cfsr);
+                       }
+                       break;
+               case 4: /* Memory Management */
+                       ahbap_read_system_u32(swjdp, NVIC_CFSR, &except_sr);
+                       ahbap_read_system_u32(swjdp, NVIC_MMFAR, &except_ar);           
+                       break;
+               case 5: /* Bus Fault */
+                       ahbap_read_system_u32(swjdp, NVIC_CFSR, &except_sr);
+                       ahbap_read_system_u32(swjdp, NVIC_BFAR, &except_ar);                            
+                       break;
+               case 6: /* Usage Fault */
+                       ahbap_read_system_u32(swjdp, NVIC_CFSR, &except_sr);
+                       break;
+               case 11:        /* SVCall */
+               
+                       break;
+               case 12:        /* Debug Monitor */
+                       ahbap_read_system_u32(swjdp, NVIC_DFSR, &except_sr);
+                       break;
+               case 14:        /* PendSV */
+               
+                       break;
+               case 15:        /* SysTick */
+               
+                       break;
+               default:
+                       except_sr = 0;
+                       break;
+                       
+       }
+       swjdp_transaction_endcheck(swjdp);
+    DEBUG("%s  SHCSR 0x%x,  SR 0x%x,  CFSR 0x%x, AR 0x%x",armv7m_exception_string(armv7m->exception_number),shcsr,except_sr,cfsr, except_ar);
+       return ERROR_OK;
+}
+
+
+int cortex_m3_debug_entry(target_t *target)
+{
+       int i, irq_is_pending;
+       u32 xPSR;
+       int retval;
+
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+
+       DEBUG("");
+       if (armv7m->pre_debug_entry)
+               armv7m->pre_debug_entry(target);
+
+       cortex_m3_clear_halt(target);
+       ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
+
+       if ((retval = armv7m->examine_debug_reason(target)) != ERROR_OK)
+               return retval;
+
+       /* Examine target state and mode */
+       /* First load register acessible through core debug port*/      
+       for (i = 0; i < ARMV7M_PRIMASK; i++)
+       {
+               if (!armv7m->core_cache->reg_list[i].valid)
+                       armv7m->read_core_reg(target, i);               
+       }
+
+       xPSR = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32);
+       
+       /* For IT instructions xPSR must be reloaded on resume and clear on debug exec*/
+       if (xPSR&0xf00)
+       {
+               armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
+               cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR&~0xff);
+       }
+
+
+       /* Now we can load SP core registers */ 
+#ifdef USE_SP_REGS
+       for (i = ARMV7M_PRIMASK; i < ARMV7NUMCOREREGS; i++)
+       {
+               if (!armv7m->core_cache->reg_list[i].valid)
+                       armv7m->read_core_reg(target, i);               
+       }
+#endif
+
+       /* Are we in an exception handler */
+    armv7m->core_mode = (xPSR&0x1FF)?ARMV7M_MODE_HANDLER:ARMV7M_MODE_THREAD;
+    armv7m->exception_number = xPSR&0x1FF;;
+       if (armv7m->exception_number)
+       {
+               cortex_m3_examine_exception_reason(target);
+       }
+
+       DEBUG("entered debug state at PC 0x%x ", *(u32*)(armv7m->core_cache->reg_list[15].value), target_state_strings[target->state]);
+
+       if (armv7m->post_debug_entry)
+               armv7m->post_debug_entry(target);
+
+       return ERROR_OK;
+}
+
+int cortex_m3_restore_context(target_t *target)
+{
+       int i;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+
+       DEBUG("");
+
+       if (armv7m->pre_restore_context)
+               armv7m->pre_restore_context(target);
+               
+#ifdef USE_SP_REGS
+       for (i = ARMV7NUMCOREREGS; i >= 0; i--)
+#else
+       for (i = ARMV7M_PSP; i >= 0; i--)
+#endif
+       {
+               if (armv7m->core_cache->reg_list[i].dirty)
+               {
+                       armv7m->write_core_reg(target, i);
+               }
+       }
+       
+       if (armv7m->post_restore_context)
+               armv7m->post_restore_context(target);
+               
+       return ERROR_OK;                
+}
+
+
+enum target_state cortex_m3_poll(target_t *target)
+{
+       int retval;
+       u32 prev_target_state = target->state;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+
+       /* Read from Debug Halting Control and Status Register */
+       retval = ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
+       if (retval != ERROR_OK)
+       {
+               target->state = TARGET_UNKNOWN;
+               return TARGET_UNKNOWN;
+       }
+       
+       if (cortex_m3->dcb_dhcsr&S_RESET_ST)
+       {
+               target->state = TARGET_RESET;
+               return target->state;
+       }
+       else if (target->state==TARGET_RESET)
+       {
+               /* Cannot switch context while running so endreset is called with target->state == TARGET_RESET */
+               DEBUG("Exit from reset with dcb_dhcsr %x", cortex_m3->dcb_dhcsr);
+               cortex_m3_endreset_event(target);
+               target->state = TARGET_RUNNING;
+               prev_target_state = TARGET_RUNNING;
+       }
+       
+       if (cortex_m3->dcb_dhcsr&S_HALT)
+       {
+               target->state = TARGET_HALTED;
+
+               if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET))
+               {
+                       if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
+                               return retval;
+                       
+                       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+               }
+               if (prev_target_state == TARGET_DEBUG_RUNNING)
+               {
+                       DEBUG("");
+                       if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
+                               return retval;
+
+                       target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+               }
+
+       }
+               
+       /*
+       if (cortex_m3->dcb_dhcsr&S_SLEEP)
+               target->state = TARGET_SLEEP;
+       */
+
+       
+    /* Read Debug Fault Status Register, added to figure out the lockup when running flashtest.script  */
+    ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
+       DEBUG("dcb_dhcsr %x, nvic_dfsr %x,  target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, target_state_strings[target->state]);       
+       return target->state;
+}
+
+int cortex_m3_halt(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       
+       DEBUG("target->state: %s", target_state_strings[target->state]);
+       
+       /* Write to Debug Halting Control and Status Register */
+       ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT );
+
+       target->debug_reason = DBG_REASON_DBGRQ;
+       
+       return ERROR_OK;
+}
+
+int cortex_m3_soft_reset_halt(struct target_s *target)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       u32 dcb_dhcsr=0;
+       int retval, timeout=0;
+       
+       /* Check that we are using process_context, or change and print warning */
+       if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
+       {
+               DEBUG("Changing to process contex registers");
+               armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
+       }
+
+       /* Enter debug state on reset, cf. end_reset_event() */
+       ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA|VC_HARDERR|VC_BUSERR|VC_CORERESET );
+       
+       /* Request a reset */ 
+       ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET );
+       target->state = TARGET_RESET;
+
+       /* registers are now invalid */
+       armv7m_invalidate_core_regs(target);
+
+       while (timeout<100)
+       {
+               retval = ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
+               if (retval == ERROR_OK)
+               {
+                   ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
+                       if ( (dcb_dhcsr&S_HALT)&&(cortex_m3->nvic_dfsr&DFSR_VCATCH) )
+                       {
+                               DEBUG("system reset-halted, dcb_dhcsr 0x%x, nvic_dfsr 0x%x",dcb_dhcsr,cortex_m3->nvic_dfsr);
+                               cortex_m3_poll(target);
+                               return ERROR_OK;
+                       }
+                       else
+                               DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%x, %i ms",dcb_dhcsr,timeout);
+               }
+               timeout++;
+               usleep(1000);
+       }
+               
+       return ERROR_OK;
+}
+
+int cortex_m3_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       breakpoint_t *breakpoint = NULL;
+       u32 dcb_dhcsr, resume_pc;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       
+       if (!debug_execution)
+       {
+               /* Check that we are using process_context, or change and print warning */
+               if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
+               {
+                       WARNING("Incorrect context in resume");
+                       armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
+               }
+
+
+               target_free_all_working_areas(target);
+               cortex_m3_enable_breakpoints(target);
+               cortex_m3_enable_watchpoints(target);
+
+               /* TODOLATER Interrupt handling/disable for debug execution, cache ... ... */ 
+
+       }
+       
+       dcb_dhcsr = DBGKEY | C_DEBUGEN;
+       if (debug_execution)
+       {
+               /* Check that we are using debug_context, or change and print warning */
+               if (armv7m_get_context(target) != ARMV7M_DEBUG_CONTEXT)
+               {
+                       WARNING("Incorrect context in debug_exec resume");
+                       armv7m_use_context(target, ARMV7M_DEBUG_CONTEXT);
+               }
+               /* Disable interrupts */
+               /* 
+                  We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
+                  This is probably the same inssue as Cortex-M3 Errata 377493: 
+                  C_MASKINTS in parallel with disabled interrupts can cause local faults to not be taken.
+               */
+               buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
+               /* Make sure we are in Thumb mode */
+               buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32, 
+                           buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32)|(1<<24));
+       }
+
+       /* current = 1: continue on current pc, otherwise continue at <address> */
+       if (!current) 
+       {
+               buf_set_u32(armv7m->core_cache->reg_list[15].value, 0, 32, address);
+               armv7m->core_cache->reg_list[15].dirty = 1;
+               armv7m->core_cache->reg_list[15].valid = 1;
+       }
+       
+       resume_pc = buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32);
+
+       cortex_m3_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)))
+               {
+                               DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
+                               cortex_m3_unset_breakpoint(target, breakpoint);
+                               cortex_m3_single_step_core(target);
+                               cortex_m3_set_breakpoint(target, breakpoint);
+               }
+       }
+
+       /* Set/Clear C_MASKINTS in a separate operation */
+       if ((cortex_m3->dcb_dhcsr&C_MASKINTS) != (dcb_dhcsr&C_MASKINTS))
+               ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, dcb_dhcsr | C_HALT );
+       /* Restart core */
+       ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, dcb_dhcsr );
+       target->debug_reason = DBG_REASON_NOTHALTED;
+
+       /* registers are now invalid */
+       armv7m_invalidate_core_regs(target);
+       if (!debug_execution)
+       {
+               target->state = TARGET_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+               DEBUG("target resumed at 0x%x",resume_pc);
+       }
+       else
+       {
+               target->state = TARGET_DEBUG_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
+               DEBUG("target debug resumed at 0x%x",resume_pc);
+       }
+       
+       
+       return ERROR_OK;
+}
+
+int irqstepcount=0;
+int cortex_m3_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       breakpoint_t *breakpoint = NULL;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       
+       /* Check that we are using process_context, or change and print warning */
+       if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT)
+       {
+               WARNING("Incorrect context in step, must be process");
+               armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
+       }
+
+       /* current = 1: continue on current pc, otherwise continue at <address> */
+       if (!current)
+               buf_set_u32(armv7m->core_cache->reg_list[15].value, 0, 32, address);
+       
+       /* the front-end may request us not to handle breakpoints */
+       if (handle_breakpoints)
+               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32))))
+                       cortex_m3_unset_breakpoint(target, breakpoint);
+       
+       target->debug_reason = DBG_REASON_SINGLESTEP;
+       
+       cortex_m3_restore_context(target);
+       
+       target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+    
+       if (cortex_m3->dcb_dhcsr&C_MASKINTS)
+               ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN );
+       ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY| C_STEP | C_DEBUGEN);
+       ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
+
+       /* If we run in process context then registers are now invalid */
+       if (armv7m_get_context(target) == ARMV7M_PROCESS_CONTEXT)
+               armv7m_invalidate_core_regs(target);
+       
+       if (breakpoint)
+               cortex_m3_set_breakpoint(target, breakpoint);
+
+       DEBUG("target stepped dcb_dhcsr=0x%x nvic_icsr=0x%x",cortex_m3->dcb_dhcsr,cortex_m3->nvic_icsr);
+
+       cortex_m3_debug_entry(target);
+       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+
+       DEBUG("target stepped dcb_dhcsr=0x%x nvic_icsr=0x%x",cortex_m3->dcb_dhcsr,cortex_m3->nvic_icsr);
+       return ERROR_OK;
+
+}
+
+int cortex_m3_assert_reset(target_t *target)
+{
+       int retval;
+       
+       DEBUG("target->state: %s", target_state_strings[target->state]);
+       
+       if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN)
+       {
+               /* assert SRST and TRST */
+               /* system would get ouf sync if we didn't reset test-logic, too */
+               if ((retval = jtag_add_reset(1, 1)) != ERROR_OK)
+               {
+                       if (retval == ERROR_JTAG_RESET_CANT_SRST)
+                       {
+                               WARNING("can't assert srst");
+                               return retval;
+                       }
+                       else
+                       {
+                               ERROR("unknown error");
+                               exit(-1);
+                       }
+               }
+               jtag_add_sleep(5000);
+               if ((retval = jtag_add_reset(0, 1)) != ERROR_OK)
+               {
+                       if (retval == ERROR_JTAG_RESET_WOULD_ASSERT_TRST)
+                       {
+                               WARNING("srst resets test logic, too");
+                               retval = jtag_add_reset(1, 1);
+                       }
+               }
+       }
+       else
+       {
+               if ((retval = jtag_add_reset(0, 1)) != ERROR_OK)
+               {
+                       if (retval == ERROR_JTAG_RESET_WOULD_ASSERT_TRST)
+                       {
+                               WARNING("srst resets test logic, too");
+                               retval = jtag_add_reset(1, 1);
+                       }
+                       
+                       if (retval == ERROR_JTAG_RESET_CANT_SRST)
+                       {
+                               WARNING("can't assert srsrt");
+                               return retval;
+                       }
+                       else if (retval != ERROR_OK)
+                       {
+                               ERROR("unknown error");
+                               exit(-1);
+                       }
+               }
+       }
+       
+       target->state = TARGET_RESET;
+       jtag_add_sleep(50000);
+       
+       armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
+       armv7m_invalidate_core_regs(target);
+
+       return ERROR_OK;
+
+}
+
+int cortex_m3_deassert_reset(target_t *target)
+{
+       DEBUG("target->state: %s", target_state_strings[target->state]);
+       
+       /* deassert reset lines */
+       jtag_add_reset(0, 0);
+               
+       return ERROR_OK;
+
+}
+
+void cortex_m3_unset_all_breakpoints_and_watchpoints(struct target_s *target)
+{
+
+}
+void cortex_m3_enable_breakpoints(struct target_s *target)
+{
+       breakpoint_t *breakpoint = target->breakpoints;
+       
+       /* set any pending breakpoints */
+       while (breakpoint)
+       {
+               if (breakpoint->set == 0)
+                       cortex_m3_set_breakpoint(target, breakpoint);
+               breakpoint = breakpoint->next;
+       }
+}
+
+int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       int fp_num=0;
+       u32 hilo;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       
+       cortex_m3_fp_comparator_t * comparator_list = cortex_m3->fp_comparator_list;
+
+       if (breakpoint->set)
+       {
+               WARNING("breakpoint already set");
+               return ERROR_OK;
+       }
+
+       if (cortex_m3->auto_bp_type)
+       {
+               breakpoint->type = (breakpoint->address<0x20000000)?BKPT_HARD:BKPT_SOFT;
+       }
+
+       if (breakpoint->type == BKPT_HARD)
+       {
+               while(comparator_list[fp_num].used && (fp_num<cortex_m3->fp_num_code))
+                       fp_num++;
+               if (fp_num>=cortex_m3->fp_num_code)
+               {
+                       DEBUG("ERROR Can not find free FP Comparator");
+                       WARNING("ERROR Can not find free FP Comparator");
+                       exit(-1);
+               }
+               breakpoint->set = fp_num+1;
+               hilo = (breakpoint->address & 0x2)? FPCR_REPLACE_BKPT_HIGH:FPCR_REPLACE_BKPT_LOW;
+               comparator_list[fp_num].used = 1;
+               comparator_list[fp_num].fpcr_value = breakpoint->address&0x1FFFFFFC | hilo | 1;
+               target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value);
+               DEBUG("fpc_num %i    fpcr_value 0x%x", fp_num, comparator_list[fp_num].fpcr_value);
+       }
+       else if (breakpoint->type == BKPT_SOFT)
+       {
+               u8 code[4];
+               buf_set_u32(code, 0, 32, ARMV7M_T_BKPT(0x11));
+               target->type->read_memory(target, breakpoint->address&0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr);
+               target->type->write_memory(target, breakpoint->address&0xFFFFFFFE, breakpoint->length, 1, code);
+               breakpoint->set = 0x11; /* Any nice value but 0 */
+       }
+
+       return ERROR_OK;
+
+}
+
+int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       cortex_m3_fp_comparator_t * comparator_list = cortex_m3->fp_comparator_list;
+
+       if (!breakpoint->set)
+       {
+               WARNING("breakpoint not set");
+               return ERROR_OK;
+       }
+       
+       if (breakpoint->type == BKPT_HARD)
+       {
+               int fp_num = breakpoint->set-1;
+               if ((fp_num<0)||(fp_num>=cortex_m3->fp_num_code))
+               {
+                       DEBUG("Invalid FP Comparator number in breakpoint");
+                       return ERROR_OK;
+               }
+               comparator_list[fp_num].used = 0;
+               comparator_list[fp_num].fpcr_value = 0;
+               target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value);
+       }
+       else
+       {
+               /* restore original instruction (kept in target endianness) */
+               if (breakpoint->length == 4)
+               {
+                       target->type->write_memory(target, breakpoint->address&0xFFFFFFFE, 4, 1, breakpoint->orig_instr);
+               }
+               else
+               {
+                       target->type->write_memory(target, breakpoint->address&0xFFFFFFFE, 2, 1, breakpoint->orig_instr);
+               }
+       }
+       breakpoint->set = 0;
+
+       return ERROR_OK;
+}
+
+
+int cortex_m3_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       
+       if (cortex_m3->auto_bp_type)
+       {
+               breakpoint->type = (breakpoint->address<0x20000000)?BKPT_HARD:BKPT_SOFT;
+       }
+
+       if ((breakpoint->type == BKPT_HARD) && (breakpoint->address>=0x20000000))
+       {
+               INFO("flash patch comparator requested outside code memory region");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       if ((breakpoint->type == BKPT_SOFT) && (breakpoint->address<0x20000000))
+       {
+               INFO("soft breakpoint requested in code (flash) memory region");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       if ((breakpoint->type == BKPT_HARD) && (cortex_m3->fp_code_available < 1))
+       {
+               INFO("no flash patch comparator unit available for hardware breakpoint");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       if ((breakpoint->length != 2))
+       {
+               INFO("only breakpoints of two bytes length supported");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+       
+       if (breakpoint->type == BKPT_HARD)
+               cortex_m3->fp_code_available--;
+       cortex_m3_set_breakpoint(target, breakpoint);
+       
+       return ERROR_OK;
+}
+
+int cortex_m3_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       
+       if (cortex_m3->auto_bp_type)
+       {
+               breakpoint->type = (breakpoint->address<0x20000000)?BKPT_HARD:BKPT_SOFT;
+       }
+
+       if (breakpoint->set)
+       {
+               cortex_m3_unset_breakpoint(target, breakpoint);
+       }
+       
+       if (breakpoint->type == BKPT_HARD)
+               cortex_m3->fp_code_available++;
+       
+       return ERROR_OK;
+}
+
+void cortex_m3_enable_watchpoints(struct target_s *target)
+{
+       watchpoint_t *watchpoint = target->watchpoints;
+       
+       /* set any pending watchpoints */
+       while (watchpoint)
+       {
+               if (watchpoint->set == 0)
+                       cortex_m3_set_watchpoint(target, watchpoint);
+               watchpoint = watchpoint->next;
+       }
+}
+
+int cortex_m3_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       int dwt_num=0;
+       u32 mask, temp;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       cortex_m3_dwt_comparator_t * comparator_list = cortex_m3->dwt_comparator_list;
+
+       if (watchpoint->set)
+       {
+               WARNING("watchpoint already set");
+               return ERROR_OK;
+       }
+
+       if (watchpoint->mask == 0xffffffffu)
+       {
+               while(comparator_list[dwt_num].used && (dwt_num<cortex_m3->dwt_num_comp))
+                       dwt_num++;
+               if (dwt_num>=cortex_m3->dwt_num_comp)
+               {
+                       DEBUG("ERROR Can not find free DWT Comparator");
+                       WARNING("ERROR Can not find free DWT Comparator");
+                       return -1;
+               }
+               watchpoint->set = dwt_num+1;
+               mask = 0;
+               temp = watchpoint->length;
+               while (temp>1)
+               {
+                       temp = temp/2;
+                       mask++;
+               }
+               comparator_list[dwt_num].used = 1;
+               comparator_list[dwt_num].comp = watchpoint->address;
+               comparator_list[dwt_num].mask = mask;
+               comparator_list[dwt_num].function = watchpoint->rw+5;
+               target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address, comparator_list[dwt_num].comp);
+               target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address|0x4, comparator_list[dwt_num].mask);
+               target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address|0x8, comparator_list[dwt_num].function);
+               DEBUG("dwt_num %i    0x%x 0x%x 0x%x", dwt_num, comparator_list[dwt_num].comp, comparator_list[dwt_num].mask, comparator_list[dwt_num].function);
+       }
+       else
+       {
+               WARNING("Cannot watch data values");  /* Move this test to add_watchpoint */
+               return ERROR_OK;
+       }
+
+       return ERROR_OK;
+
+}
+
+int cortex_m3_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       cortex_m3_dwt_comparator_t * comparator_list = cortex_m3->dwt_comparator_list;
+       int dwt_num;
+       
+       if (!watchpoint->set)
+       {
+               WARNING("watchpoint not set");
+               return ERROR_OK;
+       }
+
+       dwt_num = watchpoint->set-1;
+
+       if ((dwt_num<0)||(dwt_num>=cortex_m3->dwt_num_comp))
+       {
+               DEBUG("Invalid DWT Comparator number in watchpoint");
+               return ERROR_OK;
+       }
+       comparator_list[dwt_num].used = 0;
+       comparator_list[dwt_num].function = 0;
+       target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address|0x8, comparator_list[dwt_num].function);
+
+       watchpoint->set = 0;
+
+       return ERROR_OK;
+}
+
+
+
+int cortex_m3_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (cortex_m3->dwt_comp_available < 1)
+       {
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+       
+       if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
+       {
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+       
+       cortex_m3->dwt_comp_available--;
+               
+       return ERROR_OK;
+}
+
+int cortex_m3_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       
+       if (watchpoint->set)
+       {
+               cortex_m3_unset_watchpoint(target, watchpoint);
+       }
+               
+       cortex_m3->dwt_comp_available++;
+       
+       return ERROR_OK;
+}
+
+
+int cortex_m3_load_core_reg_u32(struct target_s *target, enum armv7m_regtype type, u32 num, u32 * value)
+{
+       int retval;
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+               
+       if ((type == ARMV7M_REGISTER_CORE_GP) && (num <= ARMV7M_PSP))
+       {
+               /* read a normal core register */
+               retval = ahbap_read_coreregister_u32(swjdp, value, num);
+               
+               if (retval != ERROR_OK)
+               {
+                       ERROR("JTAG failure %i",retval);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               //DEBUG("load from core reg %i  value 0x%x",num,*value);
+       }
+       else if (type == ARMV7M_REGISTER_CORE_SP) /* Special purpose core register */
+       {
+               /* read other registers */
+               /* cortex_m3_MRS(struct target_s *target, int num, u32* value) */
+               u32 savedram;
+               u32 SYSm;
+               u32 instr;
+               SYSm = num & 0x1F;
+               ahbap_read_system_u32(swjdp, 0x20000000, &savedram);
+               instr = ARMV7M_T_MRS(0, SYSm);
+               ahbap_write_system_u32(swjdp, 0x20000000, ARMV7M_T_MRS(0, SYSm));
+               ahbap_write_coreregister_u32(swjdp, 0x20000000, 15);
+               cortex_m3_single_step_core(target);
+               ahbap_read_coreregister_u32(swjdp, value, 0);
+               armv7m->core_cache->reg_list[0].dirty=1;
+               armv7m->core_cache->reg_list[15].dirty=1;
+               ahbap_write_system_u32(swjdp, 0x20000000, savedram);
+               swjdp_transaction_endcheck(swjdp);
+               DEBUG("load from special reg %i  value 0x%x",SYSm, *value);
+       }
+       else return ERROR_INVALID_ARGUMENTS;
+       
+       return ERROR_OK;
+       
+}
+
+int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype type, u32 num, u32 value)
+{
+       int retval;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+
+       if ((type == ARMV7M_REGISTER_CORE_GP) && (num <= ARMV7M_PSP))
+       {
+               retval = ahbap_write_coreregister_u32(swjdp, value, num);
+               if (retval != ERROR_OK)
+               {
+                       ERROR("JTAG failure %i",retval);
+                       armv7m->core_cache->reg_list[num].dirty=1;
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               DEBUG("write core reg %i value 0x%x",num, value);
+       }
+       else if (type == ARMV7M_REGISTER_CORE_SP) /* Special purpose core register */
+       {
+               /* write other registers */
+               u32 savedram , tempr0;
+               u32 SYSm;
+               u32 instr;
+               SYSm = num & 0x1F;
+               ahbap_read_system_u32(swjdp, 0x20000000, &savedram);
+               instr = ARMV7M_T_MSR(SYSm, 0);
+               ahbap_write_system_u32(swjdp, 0x20000000, ARMV7M_T_MSR(SYSm, 0));
+               ahbap_read_coreregister_u32(swjdp, &tempr0, 0);
+               ahbap_write_coreregister_u32(swjdp, value, 0);
+               ahbap_write_coreregister_u32(swjdp, 0x20000000, 15);
+               cortex_m3_single_step_core(target);
+               ahbap_write_coreregister_u32(swjdp, tempr0, 0);
+               armv7m->core_cache->reg_list[15].dirty=1;
+               ahbap_write_system_u32(swjdp, 0x20000000, savedram);
+               swjdp_transaction_endcheck(swjdp);
+               DEBUG("write special reg %i  value 0x%x ",SYSm, value);
+       }
+       else return ERROR_INVALID_ARGUMENTS;
+       
+       return ERROR_OK;
+       
+}
+
+
+int cortex_m3_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       
+       /* 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;
+       
+       /* Is not optimal, autoincrement of tar should be used (  ahbap_block_read and CSW_ADDRINC_SINGLE ) */
+       switch (size)
+       {
+               case 4:
+                       /* TODOLATER Check error return value ! */
+                       {
+                               ahbap_read_buf(swjdp, buffer, 4*count, address);
+                       }
+                       break;
+               case 2:
+                       {
+                               ahbap_read_buf(swjdp, buffer, 2*count, address);
+                       }       
+                       break;
+               case 1:
+                       {
+                               ahbap_read_buf(swjdp, buffer, count, address);
+                       }       
+                       break;
+               default:
+                       ERROR("BUG: we shouldn't get here");
+                       exit(-1);
+       }
+               
+
+       return ERROR_OK;
+}
+
+int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       
+       /* 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:
+                       /* TODOLATER Check error return value ! */
+                       {
+                               ahbap_write_buf(swjdp, buffer, 4*count, address);
+                       }
+                       break;
+               case 2:
+                       {
+                               ahbap_write_buf(swjdp, buffer, 2*count, address);
+                       }       
+                       break;
+               case 1:
+                       {
+                               ahbap_write_buf(swjdp, buffer, count, address);
+                       }       
+                       break;
+               default:
+                       ERROR("BUG: we shouldn't get here");
+                       exit(-1);
+       }
+       
+       return ERROR_OK;
+}
+
+int cortex_m3_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
+{
+
+       cortex_m3_write_memory(target, address, 4,count,buffer);
+       
+       return ERROR_OK;
+}
+
+
+
+void cortex_m3_build_reg_cache(target_t *target)
+{
+       armv7m_build_reg_cache(target);
+}
+
+int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       u32 did1, dc0, cpuid, fpcr, dwtcr, ictr;
+       int i;
+       
+       /* get pointers to arch-specific information */
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+       swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+
+       cortex_m3_build_reg_cache(target);
+       ahbap_debugport_init(swjdp);
+
+       /* Read from Device Identification Registers, IS THIS CORTEX OR Luminary Micro SPECIFIC ?? */
+       target_read_u32(target, CPUID, &cpuid );
+       if (cpuid == 0x410fc231)
+               DEBUG("CORTEX-M3 processor");
+       DEBUG("cpuid %x",cpuid);
+       /* Probably only valid for LMI parts, move to flash/stellaris ? */
+       target_read_u32(target, SYSTEM_CONTROL_BASE|0x04, &did1);
+       target_read_u32(target,SYSTEM_CONTROL_BASE|0x08,&dc0);
+       DEBUG("did1 %x",did1);
+       DEBUG("dc0 %x",dc0);
+       
+       target_read_u32(target,NVIC_ICTR,&ictr);
+       cortex_m3->intlinesnum = (ictr&0x1F) + 1;
+       cortex_m3->intsetenable = calloc(cortex_m3->intlinesnum,4);
+       for (i=0;i<cortex_m3->intlinesnum;i++)
+       {
+               target_read_u32(target,NVIC_ISE0+4*i,cortex_m3->intsetenable+i);
+               DEBUG(" interrupt enable[%i]=0x%x",i,cortex_m3->intsetenable[i]);
+       }
+       
+       /* Setup FPB */
+       target_read_u32(target, FP_CTRL, &fpcr);
+       cortex_m3->auto_bp_type = 1;
+       cortex_m3->fp_num_code = (fpcr>>4)&0xF;
+       cortex_m3->fp_num_lit = (fpcr>>8)&0xF;
+       cortex_m3->fp_code_available = cortex_m3->fp_num_code;
+       cortex_m3->fp_comparator_list=calloc(cortex_m3->fp_num_code+cortex_m3->fp_num_lit, sizeof(cortex_m3_fp_comparator_t));
+       for (i=0;i<cortex_m3->fp_num_code+cortex_m3->fp_num_lit;i++)
+       {
+               cortex_m3->fp_comparator_list[i].type = (i<cortex_m3->fp_num_code)?FPCR_CODE:FPCR_LITERAL;
+               cortex_m3->fp_comparator_list[i].fpcr_address = FP_COMP0+4*i;
+       }
+       DEBUG("FPB fpcr 0x%x, numcode %i, numlit %i",fpcr,cortex_m3->fp_num_code,cortex_m3->fp_num_lit);
+               
+       /* Setup DWT */
+       target_read_u32(target, DWT_CTRL, &dwtcr);
+       cortex_m3->dwt_num_comp = (dwtcr>>28)&0xF;
+       cortex_m3->dwt_comp_available = cortex_m3->dwt_num_comp;
+       cortex_m3->dwt_comparator_list=calloc(cortex_m3->dwt_num_comp, sizeof(cortex_m3_dwt_comparator_t));
+       for (i=0; i<cortex_m3->dwt_num_comp; i++)
+       {
+               cortex_m3->dwt_comparator_list[i].dwt_comparator_address = DWT_COMP0+0x10*i;
+       }
+       
+       return ERROR_OK;
+}
+
+int cortex_m3_quit()
+{
+       
+       return ERROR_OK;
+}
+
+int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, int chain_pos, char *variant)
+{
+       armv7m_common_t *armv7m;
+       armv7m = &cortex_m3->armv7m;
+
+       arm_jtag_t * jtag_info = &cortex_m3->jtag_info; 
+
+       /* prepare JTAG information for the new target */
+       cortex_m3->jtag_info.chain_pos = chain_pos;
+       cortex_m3->jtag_info.scann_size = 4;
+       
+       cortex_m3->swjdp_info.dp_select_value = -1;
+       cortex_m3->swjdp_info.ap_csw_value = -1;
+       cortex_m3->swjdp_info.ap_tar_value = -1;
+       cortex_m3->swjdp_info.jtag_info = &cortex_m3->jtag_info;
+
+       /* initialize arch-specific breakpoint handling */
+       
+       cortex_m3->common_magic = CORTEX_M3_COMMON_MAGIC;
+       cortex_m3->arch_info = NULL;
+
+       /* register arch-specific functions */
+       armv7m->examine_debug_reason = cortex_m3_examine_debug_reason;
+
+       armv7m->pre_debug_entry = NULL;
+       armv7m->post_debug_entry = NULL;
+       
+       armv7m->pre_restore_context = NULL;
+       armv7m->post_restore_context = NULL;
+       
+       armv7m_init_arch_info(target, armv7m);  
+       armv7m->arch_info = cortex_m3;
+       armv7m->load_core_reg_u32 = cortex_m3_load_core_reg_u32;
+       armv7m->store_core_reg_u32 = cortex_m3_store_core_reg_u32;
+//     armv7m->full_context = cortex_m3_full_context;
+       
+       return ERROR_OK;
+}
+
+/* target cortex_m3 <endianess> <startup_mode> <chain_pos> <variant>*/
+int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       cortex_m3_common_t *cortex_m3 = malloc(sizeof(cortex_m3_common_t));
+
+       if (argc < 4)
+       {
+               ERROR("'target cortex_m3' requires at least one additional argument");
+               exit(-1);
+       }
+       
+       chain_pos = strtoul(args[3], NULL, 0);
+       
+       if (argc >= 5)
+               variant = args[4];
+       
+       cortex_m3_init_arch_info(target, cortex_m3, chain_pos, variant);
+       cortex_m3_register_commands(cmd_ctx);
+       
+       return ERROR_OK;
+}
+
+int cortex_m3_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       
+       retval = armv7m_register_commands(cmd_ctx);
+       
+       return retval;
+}
diff --git a/src/target/cortex_m3.h b/src/target/cortex_m3.h
new file mode 100644 (file)
index 0000000..63a5c43
--- /dev/null
@@ -0,0 +1,218 @@
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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 CORTEX_M3_H
+#define CORTEX_M3_H
+
+#include "register.h"
+#include "target.h"
+#include "armv7m.h"
+#include "cortex_swjdp.h"
+
+extern char* cortex_m3_state_strings[];
+
+#define CORTEX_M3_COMMON_MAGIC 0x1A451A45
+
+#define SYSTEM_CONTROL_BASE 0x400FE000
+
+#define CPUID          0xE000ED00
+/* Debug Control Block */
+#define DCB_DHCSR      0xE000EDF0
+#define DCB_DCRSR      0xE000EDF4
+#define DCB_DCRDR      0xE000EDF8
+#define DCB_DEMCR      0xE000EDFC
+
+
+#define DCRSR_WnR      (1<<16) 
+
+#define DWT_CTRL       0xE0001000
+#define DWT_COMP0      0xE0001020
+#define DWT_MASK0      0xE0001024
+#define DWT_FUNCTION0  0xE0001028
+
+#define FP_CTRL                0xE0002000
+#define FP_REMAP       0xE0002004
+#define FP_COMP0       0xE0002008
+#define FP_COMP1       0xE000200C
+#define FP_COMP2       0xE0002010
+#define FP_COMP3       0xE0002014
+#define FP_COMP4       0xE0002018
+#define FP_COMP5       0xE000201C
+#define FP_COMP6       0xE0002020
+#define FP_COMP7       0xE0002024
+
+#define DWT_CTRL       0xE0001000
+
+/* DCB_DHCSR bit and field definitions */
+#define DBGKEY         (0xA05F<<16)
+#define C_DEBUGEN      (1<<0)
+#define C_HALT         (1<<1)
+#define C_STEP         (1<<2)
+#define C_MASKINTS     (1<<3)
+#define S_REGRDY       (1<<16)
+#define S_HALT         (1<<17)
+#define S_SLEEP                (1<<18)
+#define S_LOCKUP       (1<<19)
+#define S_RETIRE_ST    (1<<24)
+#define S_RESET_ST     (1<<25)
+
+/* DCB_DEMCR bit and field definitions */
+#define        TRCENA                  (1<<24)
+#define        VC_HARDERR              (1<<10)
+#define        VC_BUSERR               (1<<8)
+#define        VC_CORERESET    (1<<0)
+
+#define NVIC_ICTR              0xE000E004
+#define NVIC_ISE0              0xE000E100
+#define NVIC_ICSR              0xE000ED04
+#define NVIC_AIRCR             0xE000ED0C
+#define NVIC_SHCSR             0xE000ED24
+#define NVIC_CFSR              0xE000ED28
+#define NVIC_MMFSRb            0xE000ED28
+#define NVIC_BFSRb             0xE000ED29
+#define NVIC_USFSRh            0xE000ED2A
+#define NVIC_HFSR              0xE000ED2C
+#define NVIC_DFSR              0xE000ED30
+#define NVIC_MMFAR             0xE000ED34
+#define NVIC_BFAR              0xE000ED38
+
+/* NVIC_AIRCR bits */
+#define AIRCR_VECTKEY          (0x5FA<<16)
+#define AIRCR_SYSRESETREQ      (1<<2)
+#define AIRCR_VECTCLRACTIVE    (1<<1)
+#define AIRCR_VECTRESET                (1<<0)
+/* NVIC_SHCSR bits */
+#define SHCSR_BUSFAULTENA      (1<<17)
+/* NVIC_DFSR bits */
+#define DFSR_HALTED    1
+#define DFSR_BKPT      2
+#define DFSR_DWTTRAP   4
+#define DFSR_VCATCH    8
+
+
+#define FPCR_CODE 0
+#define FPCR_LITERAL 1
+#define FPCR_REPLACE_REMAP  (0<<30)
+#define FPCR_REPLACE_BKPT_LOW  (1<<30)
+#define FPCR_REPLACE_BKPT_HIGH  (2<<30)
+#define FPCR_REPLACE_BKPT_BOTH  (3<<30)
+
+typedef struct  cortex_m3_fp_comparator_s
+{
+       int used;
+       int type;
+       u32 fpcr_value;
+       u32 fpcr_address;
+} cortex_m3_fp_comparator_t;
+
+typedef struct  cortex_m3_dwt_comparator_s
+{
+       int used;
+       u32 comp;
+       u32 mask;
+       u32 function;
+       u32 dwt_comparator_address;
+} cortex_m3_dwt_comparator_t;
+
+typedef struct cortex_m3_common_s
+{
+       int common_magic;
+//     int (*full_context)(struct target_s *target);
+
+       arm_jtag_t jtag_info;
+       
+       /* Context information */
+       u32 dcb_dhcsr;
+       u32 nvic_dfsr;  /* Debug Fault Status Register - shows reason for debug halt */
+       u32 nvic_icsr;  /* Interrupt Control State Register - shows active and pending IRQ */
+       
+       /* Flash Patch and Breakpoint */
+       int fp_num_lit;
+       int fp_num_code;
+       int fp_code_available;
+       int auto_bp_type;
+       cortex_m3_fp_comparator_t * fp_comparator_list;
+       
+       /* DWT */
+       int dwt_num_comp;
+       int dwt_comp_available;
+       cortex_m3_dwt_comparator_t * dwt_comparator_list;
+       
+       /* Interrupts */
+       int intlinesnum;
+       u32 * intsetenable;
+       
+/*
+       u32 arm_bkpt;
+       u16 thumb_bkpt;
+       int sw_bkpts_use_wp;
+       int wp_available;
+       int wp0_used;
+       int wp1_used;
+       
+       int force_hw_bkpts;
+       int dbgreq_adjust_pc;
+       int use_dbgrq;
+       int has_etm;
+       
+       int reinit_embeddedice;
+       
+       struct working_area_s *dcc_working_area;
+       
+       int fast_memory_access;
+       int dcc_downloads;
+*/
+       /* breakpoint use map */
+       int sw_bkpts_enabled;
+
+       armv7m_common_t armv7m;
+       swjdp_common_t swjdp_info;
+       
+       void *arch_info;
+} cortex_m3_common_t;
+
+
+extern void cortex_m3_build_reg_cache(target_t *target);
+
+enum target_state cortex_m3_poll(target_t *target);
+int cortex_m3_halt(target_t *target);
+int cortex_m3_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
+int cortex_m3_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
+
+int cortex_m3_assert_reset(target_t *target);
+int cortex_m3_deassert_reset(target_t *target);
+int cortex_m3_soft_reset_halt(struct target_s *target);
+
+int cortex_m3_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int cortex_m3_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
+
+int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int cortex_m3_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int cortex_m3_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int cortex_m3_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+int cortex_m3_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+
+extern int cortex_m3_register_commands(struct command_context_s *cmd_ctx);
+extern int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, int chain_pos, char *variant);
+
+#endif /* CORTEX_M3_H */
diff --git a/src/target/cortex_swjdp.c b/src/target/cortex_swjdp.c
new file mode 100644 (file)
index 0000000..15fc26d
--- /dev/null
@@ -0,0 +1,665 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+/***************************************************************************
+ *                                                                         *
+ * CoreSight (Light?) SerialWireJtagDebugPort                              *
+ *                                                                         *
+ * CoreSightâ„¢ DAP-Lite TRM, ARM DDI 0316A                                  *
+ * Cortex-M3â„¢ TRM, ARM DDI 0337C                                            *
+ *                                                                         *
+***************************************************************************/
+
+#include "replacements.h"
+
+#include "cortex_m3.h"
+#include "cortex_swjdp.h"
+#include "jtag.h"
+#include "log.h"
+#include <stdlib.h>
+
+/*
+
+Transaction Mode:
+swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+Uses Overrun checking mode and does not do actual JTAG send/receive or transaction 
+result checking until swjdp_end_transaction()
+This must be done before using or deallocating any return variables.
+
+swjdp->trans_mode == TRANS_MODE_ATOMIC
+All reads and writes to the AHB bus are checked for valid completion, and return values
+are immediatley available.
+
+*/
+
+/***************************************************************************
+ *                                                                         *
+ * DPACC and APACC scanchain access through JTAG-DR                        *
+ *                                                                         *
+***************************************************************************/
+
+int swjdp_jtag_error_handler(u8 *in_value, void *priv)
+{
+       char *caller = priv;
+       
+       DEBUG("caller: %s", caller);
+       
+       return ERROR_OK;
+}
+
+/* Scan out and in from target ordered u8 buffers */
+int swjdp_scan(arm_jtag_t *jtag_info, u8 chain, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack)
+{
+       scan_field_t fields[2];
+       u8 out_addr_buf;
+       error_handler_t error_handler;
+       
+       jtag_add_end_state(TAP_RTI);
+       error_handler.error_handler = swjdp_jtag_error_handler;
+       error_handler.error_handler_priv = "swjdp_scan";
+       arm_jtag_set_instr(jtag_info, chain, &error_handler);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 3;
+       buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr>>1)&0x6) | (RnW&0x1));
+       fields[0].out_value = &out_addr_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = ack;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = outvalue;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = invalue;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       jtag_add_dr_scan(2, fields, -1, NULL);
+
+       return ERROR_OK;
+
+}
+
+/* Scan out and in from host ordered u32 variables */
+int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 chain, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack)
+{
+       scan_field_t fields[2];
+       u8 out_value_buf[4];
+       u8 out_addr_buf;
+       error_handler_t error_handler;
+       
+       jtag_add_end_state(TAP_RTI);
+       error_handler.error_handler = swjdp_jtag_error_handler;
+       error_handler.error_handler_priv = "swjdp_scan_u32";
+       arm_jtag_set_instr(jtag_info, chain, &error_handler);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 3;
+       buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr>>1)&0x6) | (RnW&0x1));
+       fields[0].out_value = &out_addr_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = ack;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       buf_set_u32(out_value_buf, 0, 32, outvalue);
+       fields[1].out_value = out_value_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       if (invalue)
+       {
+               fields[1].in_handler = arm_jtag_buf_to_u32;
+               fields[1].in_handler_priv = invalue;
+       }
+       else
+       {
+               fields[1].in_handler = NULL;
+               fields[1].in_handler_priv = NULL;
+       }
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       jtag_add_dr_scan(2, fields, -1, NULL);
+
+       return ERROR_OK;
+
+}
+
+/* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ 
+int scan_inout_check(swjdp_common_t *swjdp, u8 chain, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue)
+{
+
+       swjdp_scan(swjdp->jtag_info, chain, reg_addr, RnW, outvalue, NULL, NULL);
+       if ((RnW==DPAP_READ) && (invalue != NULL))
+       {
+               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
+       }
+       
+       /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */
+       if ((chain == SWJDP_IR_APACC)&&(swjdp->trans_mode == TRANS_MODE_ATOMIC))
+       {
+               return swjdp_transaction_endcheck(swjdp);
+       }
+
+       return ERROR_OK;
+}
+
+int scan_inout_check_u32(swjdp_common_t *swjdp, u8 chain, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue)
+{
+
+       swjdp_scan_u32(swjdp->jtag_info, chain, reg_addr, RnW, outvalue, NULL, NULL);
+       if ((RnW==DPAP_READ) && (invalue != NULL))
+       {
+               swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
+       }
+       
+       /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */
+       if ((chain == SWJDP_IR_APACC)&&(swjdp->trans_mode == TRANS_MODE_ATOMIC))
+       {
+               return swjdp_transaction_endcheck(swjdp);
+       }
+
+       return ERROR_OK;
+}
+
+int swjdp_transaction_endcheck(swjdp_common_t *swjdp)
+{
+       int waitcount = 0;
+       u32 ctrlstat;
+       u8 ack=0;
+
+       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+       jtag_execute_queue();
+       swjdp->ack = swjdp->ack&0x7;
+       while (swjdp->ack != 2)
+       {
+               if (swjdp->ack==1)
+               {
+                       waitcount++;
+                       if (waitcount>100)
+                       {
+                               WARNING("Timeout waiting for ACK = OK/FAULT in SWJDP transaction");
+                               return ERROR_JTAG_DEVICE_ERROR;
+                       }
+               }
+               else
+               {
+                       WARNING("Invalid ACK in SWJDP transaction");
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+               jtag_execute_queue();
+               swjdp->ack = swjdp->ack&0x7;
+       }
+
+       /* Check for STICKYERR and STICKYORUN */
+       if (ctrlstat & (SSTICKYORUN|SSTICKYERR))
+       {
+               DEBUG("      swjdp: CTRL/STAT error 0x%x",ctrlstat);
+               /* Check power to debug regions */
+               if ((ctrlstat&0xf0000000)!=0xf0000000)
+               {
+                        ahbap_debugport_init(swjdp);
+               }
+               else
+               {
+                       u32 dcb_dhcsr,nvic_shcsr, nvic_bfar, nvic_cfsr;
+                       if (ctrlstat&SSTICKYORUN) ERROR("SWJ-DP OVERRUN - check clock or reduce jtag speed");
+                       if (ctrlstat&SSTICKYERR) ERROR("SWJ-DP STICKY ERROR");
+                       /* Clear Sticky Error Bits */
+                       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat|SSTICKYORUN|SSTICKYERR, NULL);
+                       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+                       jtag_execute_queue();
+
+                       /* Can we find out the reason for the error ?? */                       
+                       ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_SHCSR, &nvic_shcsr);
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_CFSR, &nvic_cfsr);
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_BFAR, &nvic_bfar);
+                       //DEBUG("dcb_dhcsr %x,  nvic_shcsr %x,  nvic_cfsr %x,  nvic_bfar %x",dcb_dhcsr,nvic_shcsr,nvic_cfsr,nvic_bfar);
+                       ERROR("dcb_dhcsr %x,  nvic_shcsr %x,  nvic_cfsr %x,  nvic_bfar %x",dcb_dhcsr,nvic_shcsr,nvic_cfsr,nvic_bfar);
+               }
+               jtag_execute_queue();
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       return ERROR_OK;
+
+}
+
+/***************************************************************************
+ *                                                                         *
+ * DP and AHB-AP  register access  through APACC and DPACC                 *
+ *                                                                         *
+***************************************************************************/
+
+int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr)
+{
+       u8 out_value_buf[4];
+       
+       buf_set_u32(out_value_buf, 0, 32, value);
+       return scan_inout_check(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+
+}
+
+int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr)
+{
+
+       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);
+
+    return ERROR_OK;
+}
+
+int swjdp_bankselect_apacc(swjdp_common_t *swjdp,u32 reg_addr)
+{
+       u32 select;
+       select = (reg_addr&0xFF0000F0);
+
+       if ( select != swjdp->dp_select_value )
+       {
+               swjdp_write_dpacc(swjdp, select, DP_SELECT);
+               swjdp->dp_select_value = select;
+       }
+
+       return ERROR_OK;
+}
+
+int ahbap_write_reg(swjdp_common_t *swjdp, u32 reg_addr, u8* out_value_buf)
+{
+       swjdp_bankselect_apacc(swjdp, reg_addr);
+       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+
+       return ERROR_OK;
+}
+
+int ahbap_read_reg(swjdp_common_t *swjdp, u32 reg_addr, u8 *in_value_buf)
+{
+       swjdp_bankselect_apacc(swjdp, reg_addr);
+       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, in_value_buf);
+
+       return ERROR_OK;
+}
+int ahbap_write_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 value)
+{
+       u8 out_value_buf[4];
+       
+       buf_set_u32(out_value_buf, 0, 32, value);
+       swjdp_bankselect_apacc(swjdp, reg_addr);
+       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+
+       return ERROR_OK;
+}
+
+int ahbap_read_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 *value)
+{
+       swjdp_bankselect_apacc(swjdp, reg_addr);
+       scan_inout_check_u32(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, value);
+
+       return ERROR_OK;
+}
+
+/***************************************************************************
+ *                                                                         *
+ * AHB-AP access to memory and system registers on AHB bus                 *
+ *                                                                         *
+***************************************************************************/
+
+int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar)
+{
+
+       csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;
+       if ( csw != swjdp->ap_csw_value )
+       {
+       //DEBUG("swjdp : Set CSW %x",csw);
+               ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw ); 
+               swjdp->ap_csw_value = csw;
+       }
+       if ( tar != swjdp->ap_tar_value )
+       {
+       //DEBUG("swjdp : Set TAR %x",tar);
+               ahbap_write_reg_u32(swjdp, AHBAP_TAR, tar );
+               swjdp->ap_tar_value = tar;
+       }
+       if (csw & CSW_ADDRINC_MASK)
+       {       
+               /* Do not cache TAR value when autoincrementing */      
+               swjdp->ap_tar_value = -1;
+       }
+       return ERROR_OK;
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)      *
+*                                                                            *
+* Read a u32 value from memory or system register                            *
+* Functionally equivalent to target_read_u32(target, address, u32 *value),   *
+* but with less overhead                                                     *
+*****************************************************************************/
+int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)
+{
+
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address&0xFFFFFFF0);
+       ahbap_read_reg_u32(swjdp, AHBAP_BD0|address&0xC, value );
+       
+       return ERROR_OK;
+}
+
+int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value)
+{
+       ahbap_read_system_u32(swjdp, address, value);
+       
+       return swjdp_transaction_endcheck(swjdp);
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)      *
+*                                                                            *
+* Write a u32 value to memory or system register                             *
+*                                                                            *
+*****************************************************************************/
+int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)
+{
+
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address&0xFFFFFFF0);
+       ahbap_write_reg_u32(swjdp, AHBAP_BD0|address&0xC, value );
+
+       return ERROR_OK;
+}
+
+int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value)
+{
+
+       ahbap_write_system_u32(swjdp, address, value);
+       
+       return swjdp_transaction_endcheck(swjdp);
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) *
+*                                                                            *
+* Write a buffer in target order (little endian)                             *
+*                                                                            *
+*****************************************************************************/
+int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 outvalue;
+       int wcount, blocksize, writecount, errorcount=0, retval=ERROR_OK;
+
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       while ( (address&0x3)&&(count>0) )
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               outvalue = (*buffer++)<<8*(address&0x3) ;
+               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+               swjdp_transaction_endcheck(swjdp);
+               count--;
+               address++;
+       }
+       wcount = count>>2;
+       count = count-4*wcount;
+       while (wcount>0)
+       {
+               /* Adjust to read within 4K block boundaries */
+               blocksize = (0x1000-(0xFFF&address))>>2;
+               if (wcount<blocksize)
+                       blocksize = wcount;
+               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               for (writecount=0; writecount<blocksize; writecount++)
+               {
+                       ahbap_write_reg(swjdp, AHBAP_DRW, buffer+4*writecount );
+               }
+               if (swjdp_transaction_endcheck(swjdp)==ERROR_OK)
+               {
+                       wcount = wcount-blocksize;
+                       address = address+4*blocksize;
+                       buffer = buffer + 4*blocksize;
+               }
+               else
+               {
+                       errorcount++;
+               }
+               if (errorcount>1)
+               {
+                       WARNING("Block read error address %x, count %x", address, count);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+       }
+
+       while (count>0)
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               outvalue = (*buffer++)<<8*(address&0x3) ;
+               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+               retval = swjdp_transaction_endcheck(swjdp);
+               count--;
+               address++;
+       }
+
+       return retval;
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)  *
+*                                                                            *
+* Read block fast in target order (little endian) into a buffer       *
+*                                                                            *
+*****************************************************************************/
+int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 invalue;
+       int wcount, blocksize, readcount, errorcount=0, retval=ERROR_OK;
+
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       while ( (address&0x3)&&(count>0) )
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+               swjdp_transaction_endcheck(swjdp);
+               *buffer++ = (invalue>>8*(address&0x3))&0xFF;
+               count--;
+               address++;
+       }
+       wcount = count>>2;
+       count = count-4*wcount;
+       while (wcount>0)
+       {
+               /* Adjust to read within 4K block boundaries */
+               blocksize = (0x1000-(0xFFF&address))>>2;
+               if (wcount<blocksize)
+                       blocksize = wcount;
+               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               /* Scan out first read */
+               swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, NULL, NULL);
+               for (readcount=0; readcount<blocksize-1; readcount++)
+               {
+                       /* Scan out read instruction and scan in previous value */
+                       swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer+4*readcount, &swjdp->ack);
+               }
+               /* Scan in last value */
+               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer+4*readcount, &swjdp->ack);
+               if (swjdp_transaction_endcheck(swjdp)==ERROR_OK)
+               {
+                       wcount = wcount-blocksize;
+                       address += 4*blocksize;
+                       buffer += 4*blocksize; 
+               }
+               else
+               {
+                       errorcount++;
+               }
+               if (errorcount>1)
+               {
+                       WARNING("Block read error address %x, count %x", address, count);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+       }
+
+       while (count>0)
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+               retval = swjdp_transaction_endcheck(swjdp);
+               *buffer++ = (invalue>>8*(address&0x3))&0xFF;
+               count--;
+               address++;
+       }
+
+       return retval;
+}
+
+int ahbap_block_read_u32(swjdp_common_t *swjdp, u32 *buffer, int count, u32 address)
+{
+       int readcount, errorcount=0;
+       u32 blockmax, blocksize;
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       while (count>0)
+       {
+               /* Adjust to read within 4K block boundaries */
+               blocksize = (0x1000-(0xFFF&address))>>2;
+               if (count<blocksize)
+                       blocksize = count;
+               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               for (readcount=0; readcount<blocksize; readcount++)
+               {
+                       ahbap_read_reg_u32(swjdp, AHBAP_DRW, buffer+readcount );
+               }
+               if (swjdp_transaction_endcheck(swjdp)==ERROR_OK)
+               {
+                       count = count-blocksize;
+                       address = address+4*blocksize;
+                       buffer = buffer + blocksize;
+               }
+               else
+               {
+                       errorcount++;
+               }
+               if (errorcount>1)
+               {
+                       WARNING("Block read error address %x, count %x", address, count);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum)
+{
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       /* ahbap_write_system_u32(swjdp, DCB_DCRSR, regnum); */
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR&0xFFFFFFF0);
+       ahbap_write_reg_u32(swjdp, AHBAP_BD0|DCB_DCRSR&0xC, regnum );
+
+       /* ahbap_read_system_u32(swjdp, DCB_DCRDR, value); */
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR&0xFFFFFFF0);
+       ahbap_read_reg_u32(swjdp, AHBAP_BD0|DCB_DCRDR&0xC, value );
+       
+       return swjdp_transaction_endcheck(swjdp);
+}
+
+int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum)
+{
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       /* ahbap_write_system_u32(swjdp, DCB_DCRDR, core_regs[i]); */
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR&0xFFFFFFF0);
+       ahbap_write_reg_u32(swjdp, AHBAP_BD0|DCB_DCRDR&0xC, value );
+
+       /* ahbap_write_system_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR       ); */
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR&0xFFFFFFF0);
+       ahbap_write_reg_u32(swjdp, AHBAP_BD0|DCB_DCRSR&0xC, regnum | DCRSR_WnR );
+
+       return swjdp_transaction_endcheck(swjdp);
+}
+
+int ahbap_debugport_init(swjdp_common_t *swjdp)
+{
+
+u32 idreg, romaddr, dummy;
+u32 ctrlstat;
+int cnt=0;
+DEBUG("");
+       swjdp->ap_csw_value = -1;
+       swjdp->ap_tar_value = -1;
+       swjdp->trans_mode = TRANS_MODE_ATOMIC;
+       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+       swjdp_write_dpacc(swjdp, SSTICKYERR, DP_CTRL_STAT);
+       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+
+       swjdp->dp_ctrl_stat = CDBGPWRUPREQ|CSYSPWRUPREQ;
+
+       swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT);
+       swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+       jtag_execute_queue();
+
+       /* Check that we have debug power domains activated */
+       while (!(ctrlstat & CDBGPWRUPACK) && (cnt++<10))
+       {
+               DEBUG("      swjdp: wait CDBGPWRUPACK");
+               swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+               jtag_execute_queue();
+
+               usleep(10000);
+       }
+
+       while (!(ctrlstat & CSYSPWRUPACK) && (cnt++<10))
+       {
+               DEBUG("      swjdp: wait CSYSPWRUPACK");
+               swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+               jtag_execute_queue();
+               usleep(10000);
+       }
+
+
+       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+       /* With debug power on we can activate OVERRUN checking */
+       swjdp->dp_ctrl_stat = CDBGPWRUPREQ|CSYSPWRUPREQ|CORUNDETECT;
+       swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat , DP_CTRL_STAT);
+       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+       
+       ahbap_read_reg_u32(swjdp, 0xFC, &idreg );
+       ahbap_read_reg_u32(swjdp, 0xF8, &romaddr );
+       
+DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x",idreg,romaddr);        
+       
+       return ERROR_OK;
+}
diff --git a/src/target/cortex_swjdp.h b/src/target/cortex_swjdp.h
new file mode 100644 (file)
index 0000000..093f2ed
--- /dev/null
@@ -0,0 +1,130 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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 CORTEX_SWJDP_H
+#define CORTEX_SWJDP_H
+
+#include "target.h"
+#include "register.h"
+#include "arm_jtag.h"
+
+#define SWJDP_IR_DPACC 0xA
+#define SWJDP_IR_APACC 0xB
+
+#define DPAP_WRITE             0
+#define DPAP_READ              1
+#define DP_ZERO                        0
+#define DP_CTRL_STAT    0x4
+#define DP_SELECT       0x8
+#define DP_RDBUFF       0xC
+
+#define CORUNDETECT    (1<<0)
+#define SSTICKYORUN    (1<<1)
+#define SSTICKYERR     (1<<5)
+#define CDBGRSTREQ     (1<<26)
+#define CDBGRSTACK     (1<<27)
+#define CDBGPWRUPREQ   (1<<28)
+#define CDBGPWRUPACK   (1<<29)
+#define CSYSPWRUPREQ   (1<<30)
+#define CSYSPWRUPACK   (1<<31)
+
+
+
+#define        AHBAP_CSW       0x00
+#define AHBAP_TAR      0x04
+#define AHBAP_DRW      0x0C
+#define AHBAP_BD0      0x10
+#define AHBAP_BD1      0x14
+#define AHBAP_BD2      0x18
+#define AHBAP_BD3      0x1C
+#define AHBAP_DBGROMA  0xF8
+#define AHBAP_IDR      0xFC
+
+
+#define CSW_8BIT               0
+#define CSW_16BIT              1
+#define CSW_32BIT              2
+
+#define CSW_ADDRINC_MASK       (3<<4)
+#define CSW_ADDRINC_OFF                0
+#define CSW_ADDRINC_SINGLE     (1<<4)
+#define CSW_ADDRINC_PACKED     (2<<4)
+#define CSW_HPROT      (1<<25)
+#define CSW_MASTER_DEBUG       (1<<29)
+#define CSW_DBGSWENABLE        (1<<31)
+#define TRANS_MODE_NONE        0
+
+/* Transaction waits for previous to complete */
+#define TRANS_MODE_ATOMIC      1
+/* Freerunning transactions with delays and overrun checking */
+#define TRANS_MODE_COMPOSITE   2
+
+
+typedef struct swjdp_reg_s
+{
+       int addr;
+       arm_jtag_t *jtag_info;
+} swjdp_reg_t;
+
+typedef struct swjdp_common_s
+{
+       arm_jtag_t *jtag_info;
+       /* Control config */
+       u32 dp_ctrl_stat;
+       /* Register select cache */
+       u32 dp_select_value;
+       u32 ap_csw_value;
+       u32 ap_tar_value;
+       u8  prev_ack;
+       /* information about current pending SWjDP-AHBAP transaction */
+       u8  trans_mode;
+       u8  trans_rw;
+       u8  ack;
+       u32 * trans_value;
+} swjdp_common_t;
+
+/* Internal functions used in the module, partial transactions, use with caution */
+extern int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr);
+//extern int swjdp_write_apacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr);
+extern int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr);
+//extern int swjdp_read_apacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr);
+extern int ahbap_write_reg(swjdp_common_t *swjdp, u32 reg_addr, u8* out_value_buf);
+extern int ahbap_read_reg(swjdp_common_t *swjdp, u32 reg_addr, u8 *in_value_buf);
+
+/* External interface, partial operations must be completed with swjdp_transaction_endcheck() */
+extern int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value);
+extern int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value);
+extern int swjdp_transaction_endcheck(swjdp_common_t *swjdp);
+
+
+/* External interface, complete atomic operations  */
+/* Host endian word transfer of single memory and system registers */
+extern int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value);
+extern int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value);
+/* Target endian (u8*) buffer transfers of blocks of memory and system registers */
+extern int ahbap_read_block(swjdp_common_t *swjdp, u8 *buffer, int bytecount, u32 address);
+extern int ahbap_write_block(swjdp_common_t *swjdp, u8 *buffer, int bytecount, u32 address);
+/* Host endian word transfers of processor core registers */
+extern int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum);
+extern int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum);
+
+/* Initialisation of the debug system, power domains and registers */
+extern int ahbap_debugport_init(swjdp_common_t *swjdp);
+
+#endif
index 3797c3cffa01029bc7d36332d0be36d862addd0a..e7fb3ec8783e91dff133f24a4f51da2488d8bd8f 100644 (file)
@@ -81,6 +81,7 @@ extern target_type_t arm920t_target;
 extern target_type_t arm966e_target;
 extern target_type_t arm926ejs_target;
 extern target_type_t xscale_target;
+extern target_type_t cortexm3_target;
 
 target_type_t *target_types[] =
 {
@@ -91,6 +92,7 @@ target_type_t *target_types[] =
        &arm966e_target,
        &arm926ejs_target,
        &xscale_target,
+       &cortexm3_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)