- remove target specific variant and use target->variant member
[fw/openocd] / src / target / cortex_m3.c
index 1f9674fad000590b9890896120275ae7bc3448a7..a0832238c1a7313430781e94225793cde00b7819 100644 (file)
@@ -5,6 +5,9 @@
  *   Copyright (C) 2006 by Magnus Lundin                                   *
  *   lundin@mlu.mine.nu                                                    *
  *                                                                         *
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
  *   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     *
 
 /* cli handling */
 int cortex_m3_register_commands(struct command_context_s *cmd_ctx);
+int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 /* forward declarations */
 void cortex_m3_enable_breakpoints(struct target_s *target);
 void cortex_m3_enable_watchpoints(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_target_create(struct target_s *target, Jim_Interp *interp);
 int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
-int cortex_m3_quit();
+int cortex_m3_quit(void);
 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);
 int cortex_m3_target_request_data(target_t *target, u32 size, u8 *buffer);
-int cortex_m3_examine(struct command_context_s *cmd_ctx, struct target_s *target);
+int cortex_m3_examine(struct target_s *target);
 
 #ifdef ARMV7_GDB_HACKS
 extern u8 armv7m_gdb_dummy_cpsr_value[];
@@ -81,6 +85,7 @@ target_type_t cortexm3_target =
        .write_memory = cortex_m3_write_memory,
        .bulk_write_memory = cortex_m3_bulk_write_memory,
        .checksum_memory = armv7m_checksum_memory,
+       .blank_check_memory = armv7m_blank_check_memory,
        
        .run_algorithm = armv7m_run_algorithm,
        
@@ -90,26 +95,44 @@ target_type_t cortexm3_target =
        .remove_watchpoint = cortex_m3_remove_watchpoint,
 
        .register_commands = cortex_m3_register_commands,
-       .target_command = cortex_m3_target_command,
+       .target_create = cortex_m3_target_create,
        .init_target = cortex_m3_init_target,
        .examine = cortex_m3_examine,
        .quit = cortex_m3_quit
 };
 
+int cortex_m3_write_debug_halt_mask(target_t *target, u32 mask_on, u32 mask_off)
+{
+       /* 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;
+       
+       /* mask off status bits */
+       cortex_m3->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
+       /* create new register mask */
+       cortex_m3->dcb_dhcsr |= DBGKEY | C_DEBUGEN | mask_on;
+       
+       return ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, cortex_m3->dcb_dhcsr);
+}
+
 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);
-    LOG_DEBUG(" NVIC_DFSR 0x%x", cortex_m3->nvic_dfsr);
-
-    return ERROR_OK;
+       
+       /* clear step if any */
+       cortex_m3_write_debug_halt_mask(target, C_HALT, C_STEP);
+       
+       /* 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);
+       LOG_DEBUG(" NVIC_DFSR 0x%x", cortex_m3->nvic_dfsr);
+
+       return ERROR_OK;
 }
 
 int cortex_m3_single_step_core(target_t *target)
@@ -118,12 +141,19 @@ int cortex_m3_single_step_core(target_t *target)
        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 dhcsr_save;
+       
+       /* backup dhcsr reg */
+       dhcsr_save = cortex_m3->dcb_dhcsr;
+       
+       /* mask interrupts if not done already */
        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;
+               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);
        LOG_DEBUG(" ");
+       
+       /* restore dhcsr reg */
+       cortex_m3->dcb_dhcsr = dhcsr_save;      
        cortex_m3_clear_halt(target);
        
        return ERROR_OK;
@@ -143,7 +173,7 @@ int cortex_m3_exec_opcode(target_t *target,u32 opcode, int len /* MODE, r0_inval
        ahbap_write_coreregister_u32(swjdp, 0x20000000, 15);
        cortex_m3_single_step_core(target);
        armv7m->core_cache->reg_list[15].dirty = armv7m->core_cache->reg_list[15].valid;
-       retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram);          
+       retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram);
        
        return retvalue;
 }
@@ -177,19 +207,25 @@ int cortex_m3_endreset_event(target_t *target)
        ahbap_read_system_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
        LOG_DEBUG("DCB_DEMCR = 0x%8.8x",dcb_demcr);
        
-       ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 );
+       /* this regsiter is used for emulated dcc channel */
+       ahbap_write_system_u32(swjdp, DCB_DCRDR, 0);
        
        /* 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 );
+               ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
+       
+       /* clear any interrupt masking */
+       cortex_m3_write_debug_halt_mask(target, 0, C_MASKINTS);
+       
        /* Enable trace and dwt */
-       ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR );
+       ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
        /* Monitor bus faults */
-       ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA );
+       ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA);
 
        /* Enable FPB */
        target_write_u32(target, FP_CTRL, 3);
+       cortex_m3->fpb_enabled = 1;
 
        /* Restore FPB registers */
        for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++)
@@ -283,8 +319,8 @@ int cortex_m3_examine_exception_reason(target_t *target)
                        break;
        }
        swjdp_transaction_endcheck(swjdp);
-    LOG_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);
+       LOG_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;
 }
 
@@ -358,8 +394,10 @@ int cortex_m3_debug_entry(target_t *target)
                cortex_m3_examine_exception_reason(target);
        }
 
-       LOG_DEBUG("entered debug state in core mode: %s at PC 0x%x, target->state: %s", armv7m_mode_strings[armv7m->core_mode], \
-               *(u32*)(armv7m->core_cache->reg_list[15].value), target_state_strings[target->state]);
+       LOG_DEBUG("entered debug state in core mode: %s at PC 0x%x, target->state: %s", 
+               armv7m_mode_strings[armv7m->core_mode],
+               *(u32*)(armv7m->core_cache->reg_list[15].value), 
+               Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
 
        if (armv7m->post_debug_entry)
                armv7m->post_debug_entry(target);
@@ -370,7 +408,7 @@ int cortex_m3_debug_entry(target_t *target)
 int cortex_m3_poll(target_t *target)
 {
        int retval;
-       u32 prev_target_state = target->state;
+       enum target_state prev_target_state = target->state;
        
        /* get pointers to arch-specific information */
        armv7m_common_t *armv7m = target->arch_info;
@@ -433,9 +471,9 @@ int cortex_m3_poll(target_t *target)
        */
 
 #if 0
-    /* Read Debug Fault Status Register, added to figure out the lockup when running flashtest.script  */
+       /* 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);
-       LOG_DEBUG("dcb_dhcsr 0x%x, nvic_dfsr 0x%x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, target_state_strings[target->state]);
+       LOG_DEBUG("dcb_dhcsr 0x%x, nvic_dfsr 0x%x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
 #endif
        
        return ERROR_OK;
@@ -443,12 +481,8 @@ int cortex_m3_poll(target_t *target)
 
 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;
-       
-       LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
+       LOG_DEBUG("target->state: %s", 
+               Jim_Nvp_value2name_simple(nvp_target_state, target->state )->name);
        
        if (target->state == TARGET_HALTED)
        {
@@ -480,7 +514,7 @@ int cortex_m3_halt(target_t *target)
        }
 
        /* Write to Debug Halting Control and Status Register */
-       ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT );
+       cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
 
        target->debug_reason = DBG_REASON_DBGRQ;
        
@@ -497,10 +531,10 @@ int cortex_m3_soft_reset_halt(struct target_s *target)
        int retval, timeout = 0;
 
        /* Enter debug state on reset, cf. end_reset_event() */
-       ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET );
+       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 );
+       ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET);
        target->state = TARGET_RESET;
 
        /* registers are now invalid */
@@ -511,7 +545,7 @@ int cortex_m3_soft_reset_halt(struct target_s *target)
                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);
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr);
                        if ((dcb_dhcsr & S_HALT) && (cortex_m3->nvic_dfsr & DFSR_VCATCH))
                        {
                                LOG_DEBUG("system reset-halted, dcb_dhcsr 0x%x, nvic_dfsr 0x%x", dcb_dhcsr, cortex_m3->nvic_dfsr);
@@ -522,7 +556,7 @@ int cortex_m3_soft_reset_halt(struct target_s *target)
                                LOG_DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%x, %i ms", dcb_dhcsr, timeout);
                }
                timeout++;
-               usleep(1000);
+               alive_sleep(1);
        }
                
        return ERROR_OK;
@@ -532,10 +566,8 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand
 {
        /* 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;
+       u32 resume_pc;
        
        if (target->state != TARGET_HALTED)
        {
@@ -548,23 +580,23 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand
                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)
        {
                /* 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.
-               */
+               /* We disable interrupts in the PRIMASK register instead of masking with C_MASKINTS,
+                * This is probably the same issue 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);
+               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
+               armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 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));
+               armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
+               armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
        }
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
@@ -591,13 +623,10 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand
                        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 );
+       cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
+       
        target->debug_reason = DBG_REASON_NOTHALTED;
 
        /* registers are now invalid */
@@ -606,13 +635,13 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand
        {
                target->state = TARGET_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-               LOG_DEBUG("target resumed at 0x%x",resume_pc);
+               LOG_DEBUG("target resumed at 0x%x", resume_pc);
        }
        else
        {
                target->state = TARGET_DEBUG_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
-               LOG_DEBUG("target debug resumed at 0x%x",resume_pc);
+               LOG_DEBUG("target debug resumed at 0x%x", resume_pc);
        }
        
        return ERROR_OK;
@@ -647,10 +676,9 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle
        armv7m_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);
+       
+       /* set step and clear halt */
+       cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT);
        ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
 
        /* registers are now invalid */
@@ -673,8 +701,10 @@ int cortex_m3_assert_reset(target_t *target)
        armv7m_common_t *armv7m = target->arch_info;
        cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
        swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       int assert_srst = 1;
        
-       LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
+       LOG_DEBUG("target->state: %s", 
+               Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
        
        if (!(jtag_reset_config & RESET_HAS_SRST))
        {
@@ -685,15 +715,15 @@ int cortex_m3_assert_reset(target_t *target)
        /* 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 );
+               ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN);
                
        ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 );
        
-       if (target->reset_mode == RESET_RUN)
+       if (!target->reset_halt)
        {
                /* Set/Clear C_MASKINTS in a separate operation */
                if (cortex_m3->dcb_dhcsr & C_MASKINTS)
-                       ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT );
+                       ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT);
        
                cortex_m3_clear_halt(target);
                                                        
@@ -703,21 +733,42 @@ int cortex_m3_assert_reset(target_t *target)
        else
        {
                /* Enter debug state on reset, cf. end_reset_event() */
-               ahbap_write_system_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET );
+               ahbap_write_system_atomic_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
        }
        
        /* following hack is to handle luminary reset
         * when srst is asserted the luminary device seesm to also clear the debug registers
         * which does not match the armv7 debug TRM */
                
-       if (strcmp(cortex_m3->variant, "luminary") == 0)
+       if (strcmp(target->variant, "lm3s") == 0)
        {
-               /* this causes the luminary device to reset using the watchdog */
-               ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ );
-               LOG_DEBUG("Using Luminary Reset: SYSRESETREQ");
+               /* get revision of lm3s target, only early silicon has this issue
+                * Fury Rev B, DustDevil Rev B, Tempest all ok */
+               
+               u32 did0;
+               
+               if (target_read_u32(target, 0x400fe000, &did0) == ERROR_OK)
+               {
+                       switch ((did0 >> 16) & 0xff)
+                       {
+                               case 0:
+                                       /* all Sandstorm suffer issue */
+                                       assert_srst = 0;
+                                       break;
+                               
+                               case 1:
+                               case 3:
+                                       /* only Fury/DustDevil rev A suffer reset problems */
+                                       if (((did0 >> 8) & 0xff) == 0)
+                                               assert_srst = 0;
+                                       break;
+                       }
+               }
        }
-       else
+       
+       if (assert_srst)
        {
+               /* default to asserting srst */
                if (jtag_reset_config & RESET_SRST_PULLS_TRST)
                {
                        jtag_add_reset(1, 1);
@@ -727,18 +778,39 @@ int cortex_m3_assert_reset(target_t *target)
                        jtag_add_reset(0, 1);
                }
        }
+       else
+       {
+               /* this causes the luminary device to reset using the watchdog */
+               ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
+               LOG_DEBUG("Using Luminary Reset: SYSRESETREQ");
+
+               {
+                       /* I do not know why this is necessary, but it fixes strange effects
+                        * (step/resume cause a NMI after reset) on LM3S6918 -- Michael Schwingen */
+                       u32 tmp;
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_AIRCR, &tmp);
+               }
+       }
        
        target->state = TARGET_RESET;
        jtag_add_sleep(50000);
        
        armv7m_invalidate_core_regs(target);
 
+       if (target->reset_halt)
+       {
+               int retval;
+               if ((retval = target_halt(target))!=ERROR_OK)
+                       return retval;
+       }
+       
        return ERROR_OK;
 }
 
 int cortex_m3_deassert_reset(target_t *target)
 {              
-       LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
+       LOG_DEBUG("target->state: %s", 
+               Jim_Nvp_value2name_simple(nvp_target_state, target->state )->name);
        
        /* deassert reset lines */
        jtag_add_reset(0, 0);
@@ -761,6 +833,7 @@ void cortex_m3_enable_breakpoints(struct target_s *target)
 
 int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 {
+       int retval;
        int fp_num=0;
        u32 hilo;
        
@@ -775,7 +848,7 @@ int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                LOG_WARNING("breakpoint already set");
                return ERROR_OK;
        }
-    
+       
        if (cortex_m3->auto_bp_type)
        {
                breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT;
@@ -797,13 +870,24 @@ int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                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);
                LOG_DEBUG("fpc_num %i fpcr_value 0x%x", fp_num, comparator_list[fp_num].fpcr_value);
+               if (!cortex_m3->fpb_enabled)
+               {
+                       LOG_DEBUG("FPB wasn't enabled, do it now");
+                       target_write_u32(target, FP_CTRL, 3);
+               }
        }
        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);
+               if((retval = target->type->read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK)
+               {
+                       return retval;
+               }
+               if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code)) != ERROR_OK)
+               {
+                       return retval;
+               }
                breakpoint->set = 0x11; /* Any nice value but 0 */
        }
 
@@ -812,6 +896,7 @@ 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 retval;
        /* get pointers to arch-specific information */
        armv7m_common_t *armv7m = target->arch_info;
        cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
@@ -840,11 +925,17 @@ int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint
                /* restore original instruction (kept in target endianness) */
                if (breakpoint->length == 4)
                {
-                       target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr);
+                       if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       {
+                               return retval;
+                       }
                }
                else
                {
-                       target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr);
+                       if((retval = target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       {
+                               return retval;
+                       }
                }
        }
        breakpoint->set = 0;
@@ -1278,7 +1369,7 @@ int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *ta
        return ERROR_OK;
 }
 
-int cortex_m3_examine(struct command_context_s *cmd_ctx, struct target_s *target)
+int cortex_m3_examine(struct target_s *target)
 {
        int retval;
        u32 cpuid, fpcr, dwtcr, ictr;
@@ -1289,57 +1380,60 @@ int cortex_m3_examine(struct command_context_s *cmd_ctx, struct target_s *target
        cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
        swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
        
-       target->type->examined = 1;
-
-       if ((retval=ahbap_debugport_init(swjdp))!=ERROR_OK)
+       if ((retval = ahbap_debugport_init(swjdp)) != ERROR_OK)
                return retval;
-
-       /* Read from Device Identification Registers */
-       if ((retval=target_read_u32(target, CPUID, &cpuid))!=ERROR_OK)
-               return retval;
-       
-       if (((cpuid >> 4) & 0xc3f) == 0xc23)
-               LOG_DEBUG("CORTEX-M3 processor detected");
-       LOG_DEBUG("cpuid: 0x%8.8x", cpuid);
-       
-       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);
-               LOG_DEBUG("interrupt enable[%i] = 0x%8.8x", 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++)
+       if (!target->type->examined)
        {
-               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;
-       }
-       LOG_DEBUG("FPB fpcr 0x%x, numcode %i, numlit %i", fpcr, cortex_m3->fp_num_code, cortex_m3->fp_num_lit);
+               target->type->examined = 1;
                
-       /* 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;
+               /* Read from Device Identification Registers */
+               if ((retval = target_read_u32(target, CPUID, &cpuid)) != ERROR_OK)
+                       return retval;
+               
+               if (((cpuid >> 4) & 0xc3f) == 0xc23)
+                       LOG_DEBUG("CORTEX-M3 processor detected");
+               LOG_DEBUG("cpuid: 0x%8.8x", cpuid);
+               
+               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);
+                       LOG_DEBUG("interrupt enable[%i] = 0x%8.8x", 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 >> 8) & 0x70) | ((fpcr >> 4) & 0xF); /* bits [14:12] and [7:4] */
+               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));
+               cortex_m3->fpb_enabled = fpcr & 1;
+               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;
+               }
+               LOG_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()
+int cortex_m3_quit(void)
 {
        
        return ERROR_OK;
@@ -1423,13 +1517,13 @@ int cortex_m3_handle_target_request(void *priv)
        return ERROR_OK;
 }
 
-int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, int chain_pos, char *variant)
+int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, jtag_tap_t *tap)
 {
        armv7m_common_t *armv7m;
        armv7m = &cortex_m3->armv7m;
 
        /* prepare JTAG information for the new target */
-       cortex_m3->jtag_info.chain_pos = chain_pos;
+       cortex_m3->jtag_info.tap = tap;
        cortex_m3->jtag_info.scann_size = 4;
        
        cortex_m3->swjdp_info.dp_select_value = -1;
@@ -1451,15 +1545,6 @@ int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, in
        armv7m->pre_restore_context = NULL;
        armv7m->post_restore_context = NULL;
        
-       if (variant)
-       {
-               cortex_m3->variant = strdup(variant);
-       }
-       else
-       {
-               cortex_m3->variant = strdup("");
-       }
-       
        armv7m_init_arch_info(target, armv7m);  
        armv7m->arch_info = cortex_m3;
        armv7m->load_core_reg_u32 = cortex_m3_load_core_reg_u32;
@@ -1470,27 +1555,11 @@ int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, in
        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 cortex_m3_target_create(struct target_s *target, Jim_Interp *interp)
 {
-       int chain_pos;
-       char *variant = NULL;
-       cortex_m3_common_t *cortex_m3 = malloc(sizeof(cortex_m3_common_t));
-       memset(cortex_m3, 0, sizeof(*cortex_m3));
-
-       if (argc < 4)
-       {
-               LOG_ERROR("'target cortex_m3' requires at least one additional argument");
-               exit(-1);
-       }
-       
-       chain_pos = strtoul(args[3], NULL, 0);
+       cortex_m3_common_t *cortex_m3 = calloc(1,sizeof(cortex_m3_common_t));
        
-       if (argc >= 5)
-               variant = args[4];
-       
-       cortex_m3_init_arch_info(target, cortex_m3, chain_pos, variant);
-       cortex_m3_register_commands(cmd_ctx);
+       cortex_m3_init_arch_info(target, cortex_m3, target->tap);
        
        return ERROR_OK;
 }
@@ -1498,9 +1567,46 @@ int cortex_m3_target_command(struct command_context_s *cmd_ctx, char *cmd, char
 int cortex_m3_register_commands(struct command_context_s *cmd_ctx)
 {
        int retval;
+       command_t *cortex_m3_cmd;
        
        retval = armv7m_register_commands(cmd_ctx);
        
+       cortex_m3_cmd = register_command(cmd_ctx, NULL, "cortex_m3", NULL, COMMAND_ANY, "cortex_m3 specific commands");         
+       register_command(cmd_ctx, cortex_m3_cmd, "maskisr", handle_cortex_m3_mask_interrupts_command, COMMAND_EXEC, "mask cortex_m3 interrupts ['on'|'off']");
+       
        return retval;
 }
 
+int handle_cortex_m3_mask_interrupts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv7m_common_t *armv7m = target->arch_info;
+       cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
+               
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       
+       if (argc > 0)
+       {
+               if (!strcmp(args[0], "on"))
+               {
+                       cortex_m3_write_debug_halt_mask(target, C_HALT|C_MASKINTS, 0);
+               }
+               else if (!strcmp(args[0], "off"))
+               {
+                       cortex_m3_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
+               }
+               else
+               {
+                       command_print(cmd_ctx, "usage: cortex_m3 maskisr ['on'|'off']");
+               }
+       }
+       
+       command_print(cmd_ctx, "cortex_m3 interrupt mask %s",
+                       (cortex_m3->dcb_dhcsr & C_MASKINTS) ? "on" : "off");
+       
+       return ERROR_OK;
+}