- preserve cortex_m3 C_MASKINTS during resume/step
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 20 Nov 2008 11:17:47 +0000 (11:17 +0000)
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 20 Nov 2008 11:17:47 +0000 (11:17 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@1179 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/target/armv7m.c
src/target/cortex_m3.c

index 2258967a316821f2cdd7356cb115d8b3c45ef321..d4c6d3576f345c41fea80068b812326f2211fec1 100644 (file)
@@ -303,14 +303,14 @@ static int armv7m_run_and_wait(struct target_s *target, u32 entry_point, int tim
        u32 pc;
        int retval;
        /* 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 */
+        * sequence to write register values to the processor and the read them back */
        if((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
        {
                return retval;
        }
 
        retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
-       // If the target fails to halt due to the breakpoint, force a halt
+       /* If the target fails to halt due to the breakpoint, force a halt */
        if (retval != ERROR_OK || target->state != TARGET_HALTED)
        {
                if ((retval=target_halt(target))!=ERROR_OK)
@@ -322,7 +322,6 @@ static int armv7m_run_and_wait(struct target_s *target, u32 entry_point, int tim
                return ERROR_TARGET_TIMEOUT;
        }
 
-
        armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
        if (pc != exit_point)
        {
index f94250b81562fdde228776fb88a63c15e8f974f2..d938210ad62d499736f31e4b22b4ed4902003631 100644 (file)
@@ -100,6 +100,21 @@ target_type_t cortexm3_target =
        .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 */
@@ -107,6 +122,9 @@ int cortex_m3_clear_halt(target_t *target)
        cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
        swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
        
+       /* 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 !! */
@@ -122,12 +140,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;
@@ -147,7 +172,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;
 }
@@ -181,16 +206,21 @@ 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);
@@ -441,7 +471,7 @@ int cortex_m3_poll(target_t *target)
 #if 0
        /* 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, Jim_Nvp_value2name( nvp_target_state, target->state )->name );
+       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;
@@ -449,13 +479,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", 
-               Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name );
+               Jim_Nvp_value2name_simple(nvp_target_state, target->state )->name);
        
        if (target->state == TARGET_HALTED)
        {
@@ -487,7 +512,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;
        
@@ -504,10 +529,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 */
@@ -539,10 +564,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)
        {
@@ -555,16 +578,13 @@ 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: 
+                * 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;
@@ -601,13 +621,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 */
@@ -616,13 +633,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;
@@ -658,9 +675,8 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle
        
        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 */
@@ -697,7 +713,7 @@ 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 );
        
@@ -705,7 +721,7 @@ int cortex_m3_assert_reset(target_t *target)
        {
                /* 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);
                                                        
@@ -715,7 +731,7 @@ 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
@@ -763,14 +779,14 @@ int cortex_m3_assert_reset(target_t *target)
        else
        {
                /* this causes the luminary device to reset using the watchdog */
-               ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ );
+               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 );
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_AIRCR, &tmp);
                }
        }
        
@@ -792,7 +808,7 @@ int cortex_m3_assert_reset(target_t *target)
 int cortex_m3_deassert_reset(target_t *target)
 {              
        LOG_DEBUG("target->state: %s", 
-               Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
+               Jim_Nvp_value2name_simple(nvp_target_state, target->state )->name);
        
        /* deassert reset lines */
        jtag_add_reset(0, 0);