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/804
-- gerrit commit c943d180ef6eec817e83bc64006bdc5818d8d275 Author: Salvador Arroyo <[email protected]> Date: Fri Aug 31 17:38:43 2012 +0200 Pic32mx: speed up flashing by running flash code in debug mode. This will save all the work needed to run the code in kernel mode. New functions are added to pracc code to load or read registers for parameters, or to jump to the flashing code. Pracc address is used for checking. The content of the registers are not restored. Expected: -With ft2232 at 1000khz ~30Kb/s -With ftdi at 15000Khz ~75Kb/s This code is mostly for testing purposes. Change-Id: I64ca548d2faa29bad1587209c5a72a22d2e34693 Signed-off-by: Salvador Arroyo <[email protected]> diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index 788a3b9..ebb7bd6 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -28,6 +28,7 @@ #include "config.h" #endif +#include <jtag/jtag.h> #include "imp.h" #include <target/algorithm.h> #include <target/mips32.h> @@ -418,11 +419,12 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t buffer_size = 16384; struct working_area *source; uint32_t address = bank->base + offset; - struct reg_param reg_params[3]; + uint32_t row_size; int retval = ERROR_OK; struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv; - struct mips32_algorithm mips32_info; + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; /* flash write code */ if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), @@ -438,12 +440,14 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, pic32mx_flash_write_code[14] = 0x24840080; pic32mx_flash_write_code[15] = 0x24A50080; pic32mx_flash_write_code[17] = 0x24C6FFE0; + row_size = 128; } else { /* 512 byte row */ pic32mx_flash_write_code[8] = 0x2CD30080; pic32mx_flash_write_code[14] = 0x24840200; pic32mx_flash_write_code[15] = 0x24A50200; pic32mx_flash_write_code[17] = 0x24C6FF80; + row_size = 512; } retval = target_write_buffer(target, pic32mx_info->write_algorithm->address, @@ -463,39 +467,79 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - }; - - mips32_info.common_magic = MIPS32_COMMON_MAGIC; - mips32_info.isa_mode = MIPS32_ISA_MIPS32; + } - init_reg_param(®_params[0], "a0", 32, PARAM_IN_OUT); - init_reg_param(®_params[1], "a1", 32, PARAM_OUT); - init_reg_param(®_params[2], "a2", 32, PARAM_OUT); + int row_offset = offset % row_size; + uint8_t *new_buffer = NULL; + if (row_offset && (count >= (row_size / 4))) { + new_buffer = malloc(buffer_size); + if (new_buffer == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + memset(new_buffer, 0xff, row_offset); + address -= row_offset; + } else + row_offset = 0; while (count > 0) { uint32_t status; - uint32_t thisrun_count = (count > (buffer_size / 4)) ? - (buffer_size / 4) : count; + uint32_t thisrun_count; + + if (row_offset) { + thisrun_count = (count > ((buffer_size - row_offset) / 4)) ? + ((buffer_size - row_offset) / 4) : count; + + memcpy(new_buffer + row_offset, buffer, thisrun_count * 4); + + retval = target_write_buffer(target, source->address, + row_offset + thisrun_count * 4, new_buffer); + if (retval != ERROR_OK) + break; + } else { + thisrun_count = (count > (buffer_size / 4)) ? + (buffer_size / 4) : count; + + retval = target_write_buffer(target, source->address, + thisrun_count * 4, buffer); + if (retval != ERROR_OK) + break; + } + + /* Processor waiting for instruction at PRACC TEXT, as usual */ + ejtag_info->fetch_address = 0xff200200; + + /* Load registers 4, 5 and 6 with parameters */ + retval = mips32_pracc_write_register(ejtag_info, 4, Virt2Phys(source->address)); + if (retval != ERROR_OK) + break; + retval = mips32_pracc_write_register(ejtag_info, 5, Virt2Phys(address)); + if (retval != ERROR_OK) + break; + retval = mips32_pracc_write_register(ejtag_info, 6, thisrun_count + row_offset / 4); + if (retval != ERROR_OK) + break; - retval = target_write_buffer(target, source->address, - thisrun_count * 4, buffer); + /* Jump to flashing code, flashing begins */ + retval = mips32_pracc_jump(ejtag_info, pic32mx_info->write_algorithm->address); if (retval != ERROR_OK) break; - buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address)); - buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address)); - buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); + /* wait_for_pracc_rw() is expected to wait up to 125 mSec */ + /* Previous code waits up to 10 Sec., is 1 Second enough ?, problems ? */ - retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - pic32mx_info->write_algorithm->address, - 0, 10000, &mips32_info); - if (retval != ERROR_OK) { - LOG_ERROR("error executing pic32mx flash write algorithm"); - retval = ERROR_FLASH_OPERATION_FAILED; + /* Flash code ends with sdbbp instruction, re-enter debug mode */ + ejtag_info->fetch_address = 0xff200200; + + /* Read status from register 4 */ + retval = mips32_pracc_read_register(ejtag_info, 4, &status); + if (retval != ERROR_OK) break; - } - status = buf_get_u32(reg_params[0].value, 0, 32); + /* Jump to PRACC TEXT, pracc code need it */ + retval = mips32_pracc_jump(ejtag_info, 0xff200200); + if (retval != ERROR_OK) + break; if (status & NVMCON_NVMERR) { LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status); @@ -512,15 +556,17 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, buffer += thisrun_count * 4; address += thisrun_count * 4; count -= thisrun_count; + if (row_offset) { + address += row_offset; + row_offset = 0; + } } target_free_working_area(target, source); target_free_working_area(target, pic32mx_info->write_algorithm); - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - + if (new_buffer != NULL) + free(new_buffer); return retval; } @@ -828,6 +874,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command) /* unlock/erase device */ mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST); + jtag_add_sleep(200); mips_ejtag_drscan_8_out(ejtag_info, MCHP_ERASE); diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 167eae3..be3ad23 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -1404,3 +1404,166 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are return retval; } + +/* A processor fetch is expected */ +static int mips32_pracc_fetch(struct mips_ejtag *ejtag_info, uint32_t *instr) +{ + uint32_t ejtag_ctrl, address; + int retval; + + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); + retval = wait_for_pracc_rw_all(ejtag_info, &ejtag_ctrl, instr, &address); + if (retval != ERROR_OK) + return retval; + + if (ejtag_ctrl & EJTAG_CTRL_PRNW) { + LOG_ERROR("not a fetch/read access"); + return ERROR_FAIL; + } + + if (ejtag_info->fetch_address != address) { + LOG_ERROR("expected address do not match"); + return ERROR_FAIL; + } + + 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); + + ejtag_info->fetch_address += 4; + + return ERROR_OK; +} + +/* A processor store is expected */ +static int mips32_pracc_store(struct mips_ejtag *ejtag_info, uint32_t *data, uint32_t exp_addr) +{ + uint32_t ejtag_ctrl, address; + int retval; + + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); + retval = wait_for_pracc_rw_all(ejtag_info, &ejtag_ctrl, data, &address); + if (retval != ERROR_OK) + return retval; + + if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) { + LOG_ERROR("not a store/write access"); + return ERROR_FAIL; + } + + if (exp_addr != address) { + LOG_ERROR("expected address do not match"); + return ERROR_FAIL; + } + + 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); + + return ERROR_OK; +} + +/* A processor load is expected */ +/* +static int mips32_pracc_load(struct mips_ejtag *ejtag_info, uint32_t *data, uint32_t exp_addr) +{ + uint32_t ejtag_ctrl, address; + int retval; + + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); + retval = wait_for_pracc_rw_all(ejtag_info, &ejtag_ctrl, data, &address); + if (retval != ERROR_OK) + return retval; + + if (ejtag_ctrl & EJTAG_CTRL_PRNW){ + LOG_ERROR("not a load/read access"); + return ERROR_FAIL; + } + + if (exp_addr != address){ + LOG_ERROR("expected address do not match"); + return ERROR_FAIL; + } + + 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); + + return ERROR_OK; +} +*/ + +int mips32_pracc_write_register(struct mips_ejtag *ejtag_info, int num_reg, uint32_t value) +{ + uint32_t instruction; + int retval; + + instruction = MIPS32_LUI(num_reg, UPPER16(value)); + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + instruction = MIPS32_ORI(num_reg, num_reg, LOWER16(value)); + retval = mips32_pracc_fetch(ejtag_info, &instruction); + return retval; +} + +int mips32_pracc_read_register(struct mips_ejtag *ejtag_info, int num_reg, uint32_t *value) +{ + uint32_t instruction; + int retval; + + instruction = MIPS32_MTC0(15, 31, 0); /* move $15 to COP0 DeSave */ + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + instruction = MIPS32_LUI(15, 0xff20); /* Load upper 16 in register 15 */ + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + instruction = MIPS32_SW(num_reg, 0x100, 15); /* Store at 0xff200100 ((15) + 0x100) */ + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + instruction = MIPS32_MFC0(15, 31, 0); /* move COP0 DeSave to $15 */ + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + /* Store access at dmseg from previous store instruction, it's mips */ + retval = mips32_pracc_store(ejtag_info, value, 0xff200100); + return retval; +} + +int mips32_pracc_jump(struct mips_ejtag *ejtag_info, uint32_t jump_addr) +{ + uint32_t instruction; + int retval; + + instruction = MIPS32_MTC0(16, 31, 0); /* move $16 to COP0 DeSave */ + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + instruction = MIPS32_LUI(16, UPPER16(jump_addr)); + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + instruction = MIPS32_ORI(16, 16, LOWER16(jump_addr)); + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + instruction = MIPS32_JR(16); + retval = mips32_pracc_fetch(ejtag_info, &instruction); + if (retval != ERROR_OK) + return retval; + + instruction = MIPS32_MFC0(16, 31, 0); /* move COP0 DeSave to $16 */ + retval = mips32_pracc_fetch(ejtag_info, &instruction); + return retval; +} diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index c200e93..847a4a5 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -58,6 +58,10 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_ int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle); +int mips32_pracc_read_register(struct mips_ejtag *ejtag_info, int num_reg, uint32_t *value); +int mips32_pracc_write_register(struct mips_ejtag *ejtag_info, int num_reg, uint32_t value); +int mips32_pracc_jump(struct mips_ejtag *ejtag_info, uint32_t jump_addr); + /** * \b mips32_cp0_read * diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 7e78238..50e092f 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -128,6 +128,7 @@ struct mips_ejtag { uint32_t idcode; uint32_t ejtag_ctrl; int fast_access_save; + uint32_t fetch_address; }; void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, -- ------------------------------------------------------------------------------ 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
