Added correct endianess treatment for big endian targets. Now it is possible to use...
[fw/openocd] / src / target / mips_m4k.c
index e258b714e44dfbd0b4ac9db5d26867a09d941e76..74d0d5031d746d2a4bbc2708c185a99f8b9c65fc 100644 (file)
 #include "target_type.h"
 #include "register.h"
 
-int mips_m4k_examine_debug_reason(struct target *target)
+static void mips_m4k_enable_breakpoints(struct target *target);
+static void mips_m4k_enable_watchpoints(struct target *target);
+static int mips_m4k_set_breakpoint(struct target *target,
+               struct breakpoint *breakpoint);
+static int mips_m4k_unset_breakpoint(struct target *target,
+               struct breakpoint *breakpoint);
+
+static int mips_m4k_examine_debug_reason(struct target *target)
 {
        uint32_t break_status;
        int retval;
@@ -66,7 +73,7 @@ int mips_m4k_examine_debug_reason(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_debug_entry(struct target *target)
+static int mips_m4k_debug_entry(struct target *target)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -104,7 +111,7 @@ int mips_m4k_debug_entry(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_poll(struct target *target)
+static int mips_m4k_poll(struct target *target)
 {
        int retval;
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -113,7 +120,9 @@ int mips_m4k_poll(struct target *target)
 
        /* read ejtag control reg */
        mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
-       mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
+       retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* clear this bit before handling polling
         * as after reset registers will read zero */
@@ -124,7 +133,9 @@ int mips_m4k_poll(struct target *target)
                ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_ROCC;
 
                mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
-               mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
+               retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
+               if (retval != ERROR_OK)
+                       return retval;
                LOG_DEBUG("Reset Detected");
        }
 
@@ -162,7 +173,7 @@ int mips_m4k_poll(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_halt(struct target *target)
+static int mips_m4k_halt(struct target *target)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -207,7 +218,7 @@ int mips_m4k_halt(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_assert_reset(struct target *target)
+static int mips_m4k_assert_reset(struct target *target)
 {
        struct mips_m4k_common *mips_m4k = target_to_m4k(target);
        struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info;
@@ -247,18 +258,14 @@ int mips_m4k_assert_reset(struct target *target)
        {
                if (mips_m4k->is_pic32mx)
                {
-                       uint32_t mchip_cmd;
-
                        LOG_DEBUG("Using MTAP reset to reset processor...");
 
                        /* use microchip specific MTAP reset */
                        mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP);
                        mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
 
-                       mchip_cmd = MCHP_ASERT_RST;
-                       mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
-                       mchip_cmd = MCHP_DE_ASSERT_RST;
-                       mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
+                       mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
+                       mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
                        mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
                }
                else
@@ -286,7 +293,7 @@ int mips_m4k_assert_reset(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_deassert_reset(struct target *target)
+static int mips_m4k_deassert_reset(struct target *target)
 {
        LOG_DEBUG("target->state: %s",
                target_state_name(target));
@@ -297,13 +304,13 @@ int mips_m4k_deassert_reset(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_soft_reset_halt(struct target *target)
+static int mips_m4k_soft_reset_halt(struct target *target)
 {
        /* TODO */
        return ERROR_OK;
 }
 
-int mips_m4k_single_step_core(struct target *target)
+static int mips_m4k_single_step_core(struct target *target)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -322,7 +329,8 @@ int mips_m4k_single_step_core(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
+static int mips_m4k_resume(struct target *target, int current,
+               uint32_t address, int handle_breakpoints, int debug_execution)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -397,7 +405,8 @@ int mips_m4k_resume(struct target *target, int current, uint32_t address, int ha
        return ERROR_OK;
 }
 
-int mips_m4k_step(struct target *target, int current, uint32_t address, int handle_breakpoints)
+static int mips_m4k_step(struct target *target, int current,
+               uint32_t address, int handle_breakpoints)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -412,7 +421,11 @@ int mips_m4k_step(struct target *target, int current, uint32_t address, int hand
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
        if (!current)
+       {
                buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
+               mips32->core_cache->reg_list[MIPS32_PC].dirty = 1;
+               mips32->core_cache->reg_list[MIPS32_PC].valid = 1;
+       }
 
        /* the front-end may request us not to handle breakpoints */
        if (handle_breakpoints) {
@@ -452,7 +465,7 @@ int mips_m4k_step(struct target *target, int current, uint32_t address, int hand
        return ERROR_OK;
 }
 
-void mips_m4k_enable_breakpoints(struct target *target)
+static void mips_m4k_enable_breakpoints(struct target *target)
 {
        struct breakpoint *breakpoint = target->breakpoints;
 
@@ -465,7 +478,8 @@ void mips_m4k_enable_breakpoints(struct target *target)
        }
 }
 
-int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int mips_m4k_set_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips32_comparator * comparator_list = mips32->inst_break_list;
@@ -487,7 +501,7 @@ int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint
                {
                        LOG_ERROR("Can not find free FP Comparator(bpid: %d)",
                                          breakpoint->unique_id );
-                       return ERROR_FAIL;
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
                breakpoint->set = bp_num + 1;
                comparator_list[bp_num].used = 1;
@@ -557,7 +571,8 @@ int mips_m4k_set_breakpoint(struct target *target, struct breakpoint *breakpoint
        return ERROR_OK;
 }
 
-int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int mips_m4k_unset_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -636,7 +651,7 @@ int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoi
        return ERROR_OK;
 }
 
-int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
 
@@ -651,12 +666,11 @@ int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *breakpoint
                mips32->num_inst_bpoints_avail--;
        }
 
-       mips_m4k_set_breakpoint(target, breakpoint);
-
-       return ERROR_OK;
+       return mips_m4k_set_breakpoint(target, breakpoint);
 }
 
-int mips_m4k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int mips_m4k_remove_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -678,7 +692,8 @@ int mips_m4k_remove_breakpoint(struct target *target, struct breakpoint *breakpo
        return ERROR_OK;
 }
 
-int mips_m4k_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int mips_m4k_set_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips32_comparator *comparator_list = mips32->data_break_list;
@@ -745,7 +760,8 @@ int mips_m4k_set_watchpoint(struct target *target, struct watchpoint *watchpoint
        return ERROR_OK;
 }
 
-int mips_m4k_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int mips_m4k_unset_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -771,7 +787,7 @@ int mips_m4k_unset_watchpoint(struct target *target, struct watchpoint *watchpoi
        return ERROR_OK;
 }
 
-int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
 
@@ -787,7 +803,8 @@ int mips_m4k_add_watchpoint(struct target *target, struct watchpoint *watchpoint
        return ERROR_OK;
 }
 
-int mips_m4k_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int mips_m4k_remove_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
        /* get pointers to arch-specific information */
        struct mips32_common *mips32 = target_to_mips32(target);
@@ -808,7 +825,7 @@ int mips_m4k_remove_watchpoint(struct target *target, struct watchpoint *watchpo
        return ERROR_OK;
 }
 
-void mips_m4k_enable_watchpoints(struct target *target)
+static void mips_m4k_enable_watchpoints(struct target *target)
 {
        struct watchpoint *watchpoint = target->watchpoints;
 
@@ -821,7 +838,8 @@ void mips_m4k_enable_watchpoints(struct target *target)
        }
 }
 
-int mips_m4k_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+static int mips_m4k_read_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -850,11 +868,33 @@ int mips_m4k_read_memory(struct target *target, uint32_t address, uint32_t size,
        if (ERROR_OK != retval)
                return retval;
 
+       /* TAP data register is loaded LSB first (little endian) */
+       if (target->endianness == TARGET_BIG_ENDIAN)
+       {
+               uint32_t i, t32;
+               uint16_t t16;
+
+               for(i = 0; i < (count*size); i += size)
+               {
+                       switch(size)
+                       {
+                               case 4:
+                                       t32 = le_to_h_u32(&buffer[i]);
+                                       h_u32_to_be(&buffer[i], t32);
+                                       break;
+                               case 2:
+                                       t16 = le_to_h_u16(&buffer[i]);
+                                       h_u16_to_be(&buffer[i], t16);
+                                       break;
+                       }
+               }
+       }
+
        return ERROR_OK;
 }
 
-int mips_m4k_write_memory(struct target *target, uint32_t address, uint32_t size,
-               uint32_t count, uint8_t *buffer)
+static int mips_m4k_write_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
@@ -875,22 +915,62 @@ int mips_m4k_write_memory(struct target *target, uint32_t address, uint32_t size
        if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
                return ERROR_TARGET_UNALIGNED_ACCESS;
 
+       uint8_t * t = NULL;
+
+       /* TAP data register is loaded LSB first (little endian) */
+       if (target->endianness == TARGET_BIG_ENDIAN)
+       {
+               t = malloc(count * sizeof(uint32_t));
+               if (t == NULL)
+               {
+                       LOG_ERROR("Out of memory");
+                       return ERROR_FAIL;
+               }
+
+               uint32_t i, t32, t16;
+               for(i = 0; i < (count*size); i += size)
+               {
+                       switch(size)
+                       {
+                               case 4:
+                                       t32 = be_to_h_u32((uint8_t *) &buffer[i]);
+                                       h_u32_to_le(&t[i], t32);
+                                       break;
+                               case 2:
+                                       t16 = be_to_h_u16((uint8_t *) &buffer[i]);
+                                       h_u16_to_le(&t[i], t16);
+                                       break;
+                       }
+               }
+
+               buffer = t;
+       }
+
        /* if noDMA off, use DMAACC mode for memory write */
+       int retval;
        if (ejtag_info->impcode & EJTAG_IMP_NODMA)
-               return mips32_pracc_write_mem(ejtag_info, address, size, count, (void *)buffer);
+               retval = mips32_pracc_write_mem(ejtag_info, address, size, count, (void *)buffer);
        else
-               return mips32_dmaacc_write_mem(ejtag_info, address, size, count, (void *)buffer);
+               retval = mips32_dmaacc_write_mem(ejtag_info, address, size, count, (void *)buffer);
+       if (ERROR_OK != retval)
+               return retval;
+
+       if (t != NULL)
+               free(t);
+
+       return ERROR_OK;
 }
 
-int mips_m4k_init_target(struct command_context *cmd_ctx, struct target *target)
+static int mips_m4k_init_target(struct command_context *cmd_ctx,
+               struct target *target)
 {
        mips32_build_reg_cache(target);
 
        return ERROR_OK;
 }
 
-int mips_m4k_init_arch_info(struct target *target, struct mips_m4k_common *mips_m4k,
-               struct jtag_tap *tap)
+static int mips_m4k_init_arch_info(struct target *target,
+               struct mips_m4k_common *mips_m4k, struct jtag_tap *tap)
 {
        struct mips32_common *mips32 = &mips_m4k->mips32;
 
@@ -903,7 +983,7 @@ int mips_m4k_init_arch_info(struct target *target, struct mips_m4k_common *mips_
        return ERROR_OK;
 }
 
-int mips_m4k_target_create(struct target *target, Jim_Interp *interp)
+static int mips_m4k_target_create(struct target *target, Jim_Interp *interp)
 {
        struct mips_m4k_common *mips_m4k = calloc(1, sizeof(struct mips_m4k_common));
 
@@ -912,7 +992,7 @@ int mips_m4k_target_create(struct target *target, Jim_Interp *interp)
        return ERROR_OK;
 }
 
-int mips_m4k_examine(struct target *target)
+static int mips_m4k_examine(struct target *target)
 {
        int retval;
        struct mips_m4k_common *mips_m4k = target_to_m4k(target);
@@ -921,7 +1001,9 @@ int mips_m4k_examine(struct target *target)
 
        if (!target_was_examined(target))
        {
-               mips_ejtag_get_idcode(ejtag_info, &idcode);
+               retval = mips_ejtag_get_idcode(ejtag_info, &idcode);
+               if (retval != ERROR_OK)
+                       return retval;
                ejtag_info->idcode = idcode;
 
                if (((idcode >> 1) & 0x7FF) == 0x29)
@@ -944,12 +1026,11 @@ int mips_m4k_examine(struct target *target)
        return ERROR_OK;
 }
 
-int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
-               uint32_t count, uint8_t *buffer)
+static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
+               uint32_t count, const uint8_t *buffer)
 {
        struct mips32_common *mips32 = target_to_mips32(target);
        struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
-       struct working_area *source;
        int retval;
        int write_t = 1;
 
@@ -965,27 +1046,54 @@ int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
        if (address & 0x3u)
                return ERROR_TARGET_UNALIGNED_ACCESS;
 
-       /* Get memory for block write handler */
-       retval = target_alloc_working_area(target, MIPS32_FASTDATA_HANDLER_SIZE, &source);
-       if (retval != ERROR_OK)
+       if (mips32->fast_data_area == NULL)
        {
-               LOG_WARNING("No working area available, falling back to non-bulk write");
-               return mips_m4k_write_memory(target, address, 4, count, buffer);
+               /* Get memory for block write handler
+                * we preserve this area between calls and gain a speed increase
+                * of about 3kb/sec when writing flash
+                * this will be released/nulled by the system when the target is resumed or reset */
+               retval = target_alloc_working_area(target,
+                               MIPS32_FASTDATA_HANDLER_SIZE,
+                               &mips32->fast_data_area);
+               if (retval != ERROR_OK)
+               {
+                       LOG_WARNING("No working area available, falling back to non-bulk write");
+                       return mips_m4k_write_memory(target, address, 4, count, buffer);
+               }
+
+               /* reset fastadata state so the algo get reloaded */
+               ejtag_info->fast_access_save = -1;
        }
 
+       uint8_t * t = NULL;
+       const uint8_t *ec_buffer = buffer;      /* endian-corrected buffer */
+
        /* TAP data register is loaded LSB first (little endian) */
        if (target->endianness == TARGET_BIG_ENDIAN)
        {
+               t = malloc(count * sizeof(uint32_t));
+               if (t == NULL)
+               {
+                       LOG_ERROR("Out of memory");
+                       return ERROR_FAIL;
+               }
+
                uint32_t i, t32;
                for(i = 0; i < (count * 4); i += 4)
                {
                        t32 = be_to_h_u32((uint8_t *) &buffer[i]);
-                       h_u32_to_le(&buffer[i], t32);
+                       h_u32_to_le(&t[i], t32);
                }
+
+               ec_buffer = t;
        }
 
-       retval = mips32_pracc_fastdata_xfer(ejtag_info, source, write_t, address,
-                       count, (uint32_t*) buffer);
+       retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address,
+                       count, (uint32_t*) (void *)ec_buffer);
+
+       if (t != NULL)
+               free(t);
+
        if (retval != ERROR_OK)
        {
                /* FASTDATA access failed, try normal memory write */
@@ -993,9 +1101,6 @@ int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
                retval = mips_m4k_write_memory(target, address, 4, count, buffer);
        }
 
-       if (source)
-               target_free_working_area(target, source);
-
        return retval;
 }