Check return values to avoid infinite wait in loop on error.
[fw/openocd] / src / target / cortex_a8.c
index 6ef585cc7090c30c26f80eb4454ad9e9ae7e1d8d..ae97f87ed180ab1a1605375147bf59c8eac6bddf 100644 (file)
@@ -85,7 +85,6 @@ target_type_t cortexa8_target =
        .deassert_reset = NULL,
        .soft_reset_halt = NULL,
 
-//     .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
        .read_memory = cortex_a8_read_memory,
@@ -154,7 +153,7 @@ mdw 0x54011080 4
 int cortex_a8_exec_opcode(target_t *target, uint32_t opcode)
 {
        uint32_t dscr;
-       int retvalue;
+       int retval;
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
        armv7a_common_t *armv7a = armv4_5->arch_info;
@@ -163,8 +162,10 @@ int cortex_a8_exec_opcode(target_t *target, uint32_t opcode)
        LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
        do
        {
-               retvalue = mem_ap_read_atomic_u32(swjdp,
+               retval = mem_ap_read_atomic_u32(swjdp,
                                OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
        while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
 
@@ -172,12 +173,14 @@ int cortex_a8_exec_opcode(target_t *target, uint32_t opcode)
 
        do
        {
-               retvalue = mem_ap_read_atomic_u32(swjdp,
+               retval = mem_ap_read_atomic_u32(swjdp,
                                OMAP3530_DEBUG_BASE + CPUDBG_DSCR, &dscr);
+               if (retval != ERROR_OK)
+                       return retval;
        }
        while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
 
-       return retvalue;
+       return retval;
 }
 
 /**************************************************************************
@@ -225,7 +228,6 @@ int cortex_a8_read_cp(target_t *target, uint32_t *value, uint8_t CP,
 
 int cortex_a8_write_cp(target_t *target, uint32_t value,
        uint8_t CP, uint8_t op1, uint8_t CRn, uint8_t CRm, uint8_t op2)
-/* TODO Fix this */
 {
        int retval;
        /* get pointers to arch-specific information */
@@ -238,7 +240,7 @@ int cortex_a8_write_cp(target_t *target, uint32_t value,
        /* Move DTRRX to r0 */
        cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
 
-       cortex_a8_exec_opcode(target, ARMV4_5_MCR(CP, 0, 0, 0, 5, 0));
+       cortex_a8_exec_opcode(target, ARMV4_5_MCR(CP, op1, 0, CRn, CRm, op2));
        return retval;
 }
 
@@ -458,7 +460,6 @@ int cortex_a8_resume(struct target_s *target, int current,
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
        armv7a_common_t *armv7a = armv4_5->arch_info;
-       cortex_a8_common_t *cortex_a8 = armv7a->arch_info;
        swjdp_common_t *swjdp = &armv7a->swjdp_info;
 
 //     breakpoint_t *breakpoint = NULL;
@@ -506,10 +507,17 @@ int cortex_a8_resume(struct target_s *target, int current,
        /* Make sure that the Armv7 gdb thumb fixups does not
         * kill the return address
         */
-       if (!(cortex_a8->cpudbg_dscr & (1 << 5)))
+       if (armv7a->core_state == ARMV7A_STATE_ARM)
        {
                resume_pc &= 0xFFFFFFFC;
        }
+       /* When the return address is loaded into PC
+        * bit 0 must be 1 to stay in Thumb state
+        */
+       if (armv7a->core_state == ARMV7A_STATE_THUMB)
+       {
+               resume_pc |= 0x1;
+       }
        LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
        buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
                                armv4_5->core_mode, 15).value,
@@ -593,7 +601,6 @@ int cortex_a8_debug_entry(target_t *target)
        retval = mem_ap_write_atomic_u32(swjdp,
                        OMAP3530_DEBUG_BASE + CPUDBG_DSCR, dscr);
 
-
        /* Examine debug reason */
        switch ((cortex_a8->cpudbg_dscr >> 2)&0xF)
        {
@@ -638,7 +645,8 @@ int cortex_a8_debug_entry(target_t *target)
        dap_ap_select(swjdp, swjdp_debugap);
        LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
 
-       armv4_5->core_mode = cpsr & 0x3F;
+       armv4_5->core_mode = cpsr & 0x1F;
+       armv7a->core_state = (cpsr & 0x20)?ARMV7A_STATE_THUMB:ARMV7A_STATE_ARM;
 
        for (i = 0; i <= ARM_PC; i++)
        {
@@ -657,8 +665,7 @@ int cortex_a8_debug_entry(target_t *target)
        ARMV7A_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0;
 
        /* Fixup PC Resume Address */
-       /* TODO Her we should use arch->core_state */
-       if (cortex_a8->cpudbg_dscr & (1 << 5))
+       if (armv7a->core_state == ARMV7A_STATE_THUMB)
        {
                // T bit set for Thumb or ThumbEE state
                regfile[ARM_PC] -= 4;
@@ -743,7 +750,6 @@ int cortex_a8_step(struct target_s *target, int current, uint32_t address,
        /* get pointers to arch-specific information */
        armv4_5_common_t *armv4_5 = target->arch_info;
        armv7a_common_t *armv7a = armv4_5->arch_info;
-       cortex_a8_common_t *cortex_a8 = armv7a->arch_info;
        breakpoint_t *breakpoint = NULL;
        breakpoint_t stepbreakpoint;
 
@@ -785,7 +791,7 @@ int cortex_a8_step(struct target_s *target, int current, uint32_t address,
 
        /* Setup single step breakpoint */
        stepbreakpoint.address = address;
-       stepbreakpoint.length = (cortex_a8->cpudbg_dscr & (1 << 5)) ? 2 : 4;
+       stepbreakpoint.length = (armv7a->core_state == ARMV7A_STATE_THUMB) ? 2 : 4;
        stepbreakpoint.type = BKPT_HARD;
        stepbreakpoint.set = 0;
 
@@ -1251,6 +1257,24 @@ int cortex_a8_write_memory(struct target_s *target, uint32_t address,
                        exit(-1);
        }
 
+       /* The Cache handling will NOT work with MMU active, the wrong addresses will be invalidated */
+       /* invalidate I-Cache */
+       if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+       {
+               /* Invalidate ICache single entry with MVA, repeat this for all cache
+                  lines in the address range, Cortex-A8 has fixed 64 byte line length */
+               /* Invalidate Cache single entry with MVA to PoU */
+               for (uint32_t cacheline=address; cacheline<address+size*count; cacheline+=64)
+                       armv7a->write_cp15(target, 0, 1, 7, 5, cacheline); /* I-Cache to PoU */
+       }
+       /* invalidate D-Cache */
+       if (armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+       {
+               /* Invalidate Cache single entry with MVA to PoC */
+               for (uint32_t cacheline=address; cacheline<address+size*count; cacheline+=64)
+                       armv7a->write_cp15(target, 0, 1, 7, 6, cacheline); /* U/D cache to PoC */
+       }
+
        return retval;
 }