This is an automated email from Gerrit. Salvador Arroyo ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/760
-- gerrit commit b96a03938f640e5c65897d5fd01cbcd483778705 Author: Salvador Arroyo <[email protected]> Date: Mon Jul 23 01:05:01 2012 +0200 Pic32mx_1_2: speed up fast data transfer Until now fast data transfer works up to 300Khz. Adding the new functions that scans to the all register the code works up to 600Khz. Adding some delay by clocking in TAP/IDLE state with the function jtag_add_clocks() it works up to 2000Khz. To test fast data trasfer for reading purposes the function mips_m4k_fast_read_memory() is added. The fuction mips_m4k_read_memory() is modified to use fast data transfer for reading words if count > 128. Reading works at any scan frequency up to 15Mhz. For testing purposes a mips_m4k_fast_blank_check_memory() and mips_m4k_fast_checksum_memory() are added. To make mips32_pracc_fastdata_xfer() work at any scan frecuency for writing, an additional delay must be added after the proccessor begin to scan at fastdada area. Another delay is added after proccessor leaves fast data area. If not pracc bit takes about 50 ms to becomes 1, at 3000Khz or more. The new variable clk_delay is used as clock count to generate the delay. With clk_delay = 20 it is possible to scan up to 7500 khz with the proccessor working at 4Mhz and up to 15000 if the proccessor works at 8Mhz. With this settings fastdata transfer works up to 500Kbyte/s at 8Mhz. Reading only works with ftdi driver for me. This code is much for testing than a real patch. Change-Id: I76a5bdf80320115fa09f685d5ff81b110de5f692 Signed-off-by: Salvador Arroyo <[email protected]> diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index abd658c..0a763e2 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -115,7 +115,7 @@ static int mips32_pracc_sync_cache(struct mips_ejtag *ejtag_info, uint32_t start_addr, uint32_t end_addr); static int mips32_pracc_clean_invalidate_cache(struct mips_ejtag *ejtag_info, uint32_t start_addr, uint32_t end_addr); - +#if 0 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) { uint32_t ejtag_ctrl; @@ -145,6 +145,7 @@ static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) *ctrl = ejtag_ctrl; return ERROR_OK; } +#endif static int wait_for_pracc_rw_all(struct mips_ejtag *ejtag_info, uint32_t *ctrl, uint32_t *data, uint32_t *addr) { @@ -1297,7 +1298,10 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are }; int retval, i; - uint32_t val, ejtag_ctrl, address; + uint32_t ejtag_ctrl, val, address; + + /*Delay in scan clocks*/ + unsigned int clk_delay = 20; if (source->size < MIPS32_FASTDATA_HANDLER_SIZE) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -1323,48 +1327,45 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are jmp_code[2] |= LOWER16(source->address); for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) { - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); + retval = wait_for_pracc_rw_all(ejtag_info, &ejtag_ctrl, &jmp_code[i], &address); if (retval != ERROR_OK) return retval; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); - mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]); - /* Clear the access pending bit (let the processor eat!) */ ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl); } - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); - if (retval != ERROR_OK) - return retval; + /* needed to work for full range of scan frequencies in Pic32mx_1_2 */ + jtag_add_clocks(2 * clk_delay); - /* next fetch to dmseg should be in FASTDATA_AREA, check */ - address = 0; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); - retval = mips_ejtag_drscan_32(ejtag_info, &address); + val = 0; + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); + retval = wait_for_pracc_rw_all(ejtag_info, &ejtag_ctrl, &val, &address); if (retval != ERROR_OK) return retval; + /* next fetch to dmseg should be in FASTDATA_AREA, check */ if (address != MIPS32_PRACC_FASTDATA_AREA) return ERROR_FAIL; - /* wait PrAcc pending bit for FASTDATA write */ - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); - if (retval != ERROR_OK) - return retval; + LOG_DEBUG("start...."); /* Send the load start address */ val = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); mips_ejtag_fastdata_scan(ejtag_info, 1, &val); + jtag_add_clocks(clk_delay); + /* Send the load end address */ val = addr + (count - 1) * 4; mips_ejtag_fastdata_scan(ejtag_info, 1, &val); for (i = 0; i < count; i++) { + jtag_add_clocks(clk_delay); retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++); if (retval != ERROR_OK) return retval; @@ -1376,13 +1377,14 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are return retval; } - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); - if (retval != ERROR_OK) - return retval; + LOG_DEBUG(".....end"); - address = 0; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); - retval = mips_ejtag_drscan_32(ejtag_info, &address); + /* EJTAG_CTRL_PRACC becomes "1" faster in Pic32mx_1_2 */ + jtag_add_clocks(2 * clk_delay); + + val = 0; + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); + retval = wait_for_pracc_rw_all(ejtag_info, &ejtag_ctrl, &val, &address); if (retval != ERROR_OK) return retval; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 1a10d5a..5666960 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -35,6 +35,7 @@ #include "mips32_dmaacc.h" #include "target_type.h" #include "register.h" +#include "image.h" static void mips_m4k_enable_breakpoints(struct target *target); static void mips_m4k_enable_watchpoints(struct target *target); @@ -782,6 +783,34 @@ static void mips_m4k_enable_watchpoints(struct target *target) } } +static int mips_m4k_fast_read_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; + int retval; + int write_t = 0; + + if (mips32->fast_data_area == NULL) { + /* 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-fast read"); + return ERROR_FAIL; + } + + /* reset fastadata state so the algo get reloaded */ + ejtag_info->fast_access_save = -1; + } + + return mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address, count, (uint32_t *)buffer); +} + static int mips_m4k_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { @@ -817,9 +846,14 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address, /* if noDMA off, use DMAACC mode for memory read */ int retval; - if (ejtag_info->impcode & EJTAG_IMP_NODMA) - retval = mips32_pracc_read_mem(ejtag_info, address, size, count, t); - else + if (ejtag_info->impcode & EJTAG_IMP_NODMA) { + if (size == 4 && count > 128) { + retval = mips_m4k_fast_read_memory(target, address, count, t); + if (retval != ERROR_OK) + retval = mips32_pracc_read_mem(ejtag_info, address, size, count, t); + } else + retval = mips32_pracc_read_mem(ejtag_info, address, size, count, t); + } else retval = mips32_dmaacc_read_mem(ejtag_info, address, size, count, t); /* mips32_..._read_mem with size 4/2 returns uint32_t/uint16_t in host */ @@ -1027,6 +1061,117 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, return retval; } +static int mips_m4k_fast_blank_check_memory(struct target *target, uint32_t address, + uint32_t count, uint32_t *blank) +{ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + int retval; + int write_t = 0; + + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* check alignment */ + if ((address & 0x3u) || count%4) + return ERROR_TARGET_UNALIGNED_ACCESS; + + count /= 4; + if (mips32->fast_data_area == NULL) { + retval = target_alloc_working_area(target, + MIPS32_FASTDATA_HANDLER_SIZE, + &mips32->fast_data_area); + if (retval != ERROR_OK) { + LOG_WARNING("No working area available"); + return ERROR_FAIL; + } + + /* reset fastadata state so the algo get reloaded */ + ejtag_info->fast_access_save = -1; + } + + uint32_t *t = NULL; + t = malloc(count * sizeof(uint32_t)); + if (t == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address, + count, t); + uint32_t *val = t; + uint32_t check = 0xffffffff; + for (uint32_t i = 0; i != count; i++) + check &= *val++; + + *blank = (check == 0xffffffff) ? 0xff : 0; + + if (t != NULL) + free(t); + + return retval; +} + +static int mips_m4k_fast_checksum_memory(struct target *target, uint32_t address, + uint32_t count, uint32_t *checksum) +{ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + int retval; + int write_t = 0; + + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* check alignment */ + if ((address & 0x3u) || count%4) + return ERROR_TARGET_UNALIGNED_ACCESS; + + count /= 4; + + if (mips32->fast_data_area == NULL) { + retval = target_alloc_working_area(target, + MIPS32_FASTDATA_HANDLER_SIZE, + &mips32->fast_data_area); + if (retval != ERROR_OK) { + LOG_WARNING("No working area available"); + return ERROR_FAIL; + } + + /* reset fastadata state so the algo get reloaded */ + ejtag_info->fast_access_save = -1; + } + + /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */ + /* but byte array represents target endianness */ + uint32_t *t = NULL; + t = malloc(count * sizeof(uint32_t)); + if (t == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address, + count, t); + if (retval != ERROR_OK) + goto exit; + + for (uint32_t i = 0; i < count; i++) + target_buffer_set_u32(target, (uint8_t *)&t[i], t[i]); + + retval = image_calculate_checksum((uint8_t *)t, count * 4, checksum); + +exit: + if (t != NULL) + free(t); + + return retval; +} + static int mips_m4k_verify_pointer(struct command_context *cmd_ctx, struct mips_m4k_common *mips_m4k) { @@ -1141,8 +1286,8 @@ struct target_type mips_m4k_target = { .read_memory = mips_m4k_read_memory, .write_memory = mips_m4k_write_memory, .bulk_write_memory = mips_m4k_bulk_write_memory, - .checksum_memory = mips32_checksum_memory, - .blank_check_memory = mips32_blank_check_memory, + .checksum_memory = mips_m4k_fast_checksum_memory, + .blank_check_memory = mips_m4k_fast_blank_check_memory, .run_algorithm = mips32_run_algorithm, -- ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
