diff --git a/doc/openocd.texi b/doc/openocd.texi index 98fc69007..da2782b13 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4523,10 +4523,10 @@ flash bank ocl 0 0 0 0 $_TARGETNAME @deffn {Flash Driver} pic32mx The PIC32MX microcontrollers are based on the MIPS 4K cores, and integrate flash memory. -@emph{The current implementation is incomplete.} @example -flash bank pix32mx 0 0 0 0 $_TARGETNAME +flash bank pix32mx 0x1fc00000 0 0 0 $_TARGETNAME +flash bank pix32mx 0x1d000000 0 0 0 $_TARGETNAME @end example @comment numerous *disabled* commands are defined: @@ -4538,6 +4538,10 @@ Some pic32mx-specific commands are defined: Programs the specified 32-bit @var{value} at the given @var{address} in the specified chip @var{bank}. @end deffn +@deffn Command {pic32mx unlock} bank +Unlock and erase specified chip @var{bank}. +This will remove any Code Protection. +@end deffn @end deffn @deffn {Flash Driver} stellaris diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index c46264c55..36744e6f7 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -31,6 +31,7 @@ #include "pic32mx.h" #include #include +#include static const struct pic32mx_devs_s { uint8_t devid; @@ -664,6 +665,73 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command) return ERROR_OK; } +COMMAND_HANDLER(pic32mx_handle_unlock_command) +{ + uint32_t mchip_cmd; + struct target *target = NULL; + struct mips_m4k_common *mips_m4k; + struct mips_ejtag *ejtag_info; + int timeout = 10; + + if (CMD_ARGC < 1) + { + command_print(CMD_CTX, "pic32mx unlock "); + return ERROR_OK; + } + + struct flash_bank *bank; + int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + target = bank->target; + mips_m4k = target_to_m4k(target); + ejtag_info = &mips_m4k->mips32.ejtag_info; + + /* we have to use the MTAP to perform a full erase */ + mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP); + mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND); + + /* first check status of device */ + mchip_cmd = MCHP_STATUS; + mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); + if (mchip_cmd & (1 << 7)) + { + /* device is not locked */ + command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway"); + } + + /* unlock/erase device */ + mchip_cmd = MCHP_ASERT_RST; + mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); + + mchip_cmd = MCHP_ERASE; + mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); + + do { + mchip_cmd = MCHP_STATUS; + mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); + if (timeout-- == 0) + { + LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd); + break; + } + alive_sleep(1); + } while ((mchip_cmd & (1 << 2)) || (!(mchip_cmd & (1 << 3)))); + + mchip_cmd = MCHP_DE_ASSERT_RST; + mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); + + /* select ejtag tap */ + mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP); + + command_print(CMD_CTX, "pic32mx unlocked.\n" + "INFO: a reset or power cycle is required " + "for the new settings to take effect."); + + return ERROR_OK; +} + static const struct command_registration pic32mx_exec_command_handlers[] = { { .name = "pgm_word", @@ -671,6 +739,13 @@ static const struct command_registration pic32mx_exec_command_handlers[] = { .mode = COMMAND_EXEC, .help = "program a word", }, + { + .name = "unlock", + .handler = pic32mx_handle_unlock_command, + .mode = COMMAND_EXEC, + .usage = "[bank_id]", + .help = "Unlock/Erase entire device.", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 164edd010..f302a7067 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -48,6 +48,8 @@ /* microchip specific cmds */ #define MCHP_ASERT_RST 0xd1 #define MCHP_DE_ASSERT_RST 0xd0 +#define MCHP_ERASE 0xfc +#define MCHP_STATUS 0x00 /* ejtag control register bits ECR */ #define EJTAG_CTRL_TOF (1 << 1)