Added correct endianess treatment for big endian targets. Now it is possible to use...
[fw/openocd] / src / target / mips_m4k.c
index c0adc066e81d7c9ad7f6093ebbeaf2978fde5659..74d0d5031d746d2a4bbc2708c185a99f8b9c65fc 100644 (file)
@@ -120,7 +120,9 @@ static 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 */
@@ -131,7 +133,9 @@ static 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");
        }
 
@@ -254,18 +258,14 @@ static 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
@@ -421,7 +421,11 @@ static int mips_m4k_step(struct target *target, int current,
 
        /* 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) {
@@ -864,11 +868,33 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address,
        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;
 }
 
 static int mips_m4k_write_memory(struct target *target, uint32_t address,
-               uint32_t size, uint32_t count, uint8_t *buffer)
+               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;
@@ -889,11 +915,50 @@ static int mips_m4k_write_memory(struct target *target, uint32_t address,
        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;
 }
 
 static int mips_m4k_init_target(struct command_context *cmd_ctx,
@@ -936,7 +1001,9 @@ static 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)
@@ -960,11 +1027,10 @@ static int mips_m4k_examine(struct target *target)
 }
 
 static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address,
-               uint32_t count, uint8_t *buffer)
+               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;
 
@@ -980,27 +1046,54 @@ static 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*) (void *)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 */
@@ -1008,9 +1101,6 @@ static 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;
 }