X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fpic32mx.c;h=5ad4cb7e5b267a3ad2d83a5ce7bc0d5b4915c7c1;hp=b718c98ffddbce613f934853940b76fa94783fc4;hb=b61e454869c988e7fafc1c16982ccfec04415b51;hpb=a25e61ecd364eae32e45d0903f241bfd62b82782 diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index b718c98ffd..5ad4cb7e5b 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -52,7 +50,7 @@ /* pic32mx configuration register locations */ -#define PIC32MX_DEVCFG0_1_2 0xBFC00BFC +#define PIC32MX_DEVCFG0_1xx_2xx 0xBFC00BFC #define PIC32MX_DEVCFG0 0xBFC02FFC #define PIC32MX_DEVCFG1 0xBFC02FF8 #define PIC32MX_DEVCFG2 0xBFC02FF4 @@ -93,16 +91,16 @@ #define NVMKEY1 0xAA996655 #define NVMKEY2 0x556699AA -#define MX_1_2 1 /* PIC32mx1xx/2xx */ +#define MX_1xx_2xx 1 /* PIC32mx1xx/2xx */ +#define MX_17x_27x 2 /* PIC32mx17x/27x */ struct pic32mx_flash_bank { - struct working_area *write_algorithm; int probed; int dev_type; /* Default 0. 1 for Pic32MX1XX/2XX variant */ }; /* - * DEVID values as per PIC32MX Flash Programming Specification Rev J + * DEVID values as per PIC32MX Flash Programming Specification Rev N */ static const struct pic32mx_devs_s { @@ -121,6 +119,8 @@ static const struct pic32mx_devs_s { {0x04D06053, "150F128B"}, {0x04D08053, "150F128C"}, {0x04D0A053, "150F128D"}, + {0x06610053, "170F256B"}, + {0x0661A053, "170F256D"}, {0x04A01053, "210F016B"}, {0x04A03053, "210F016C"}, {0x04A05053, "210F016D"}, @@ -133,6 +133,24 @@ static const struct pic32mx_devs_s { {0x04D00053, "250F128B"}, {0x04D02053, "250F128C"}, {0x04D04053, "250F128D"}, + {0x06600053, "270F256B"}, + {0x0660A053, "270F256D"}, + {0x05600053, "330F064H"}, + {0x05601053, "330F064L"}, + {0x05602053, "430F064H"}, + {0x05603053, "430F064L"}, + {0x0570C053, "350F128H"}, + {0x0570D053, "350F128L"}, + {0x0570E053, "450F128H"}, + {0x0570F053, "450F128L"}, + {0x05704053, "350F256H"}, + {0x05705053, "350F256L"}, + {0x05706053, "450F256H"}, + {0x05707053, "450F256L"}, + {0x05808053, "370F512H"}, + {0x05809053, "370F512L"}, + {0x0580A053, "470F512H"}, + {0x0580B053, "470F512L"}, {0x00938053, "360F512L"}, {0x00934053, "360F256L"}, {0x0092D053, "340F128L"}, @@ -193,7 +211,6 @@ FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command) pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank)); bank->driver_priv = pic32mx_info; - pic32mx_info->write_algorithm = NULL; pic32mx_info->probed = 0; pic32mx_info->dev_type = 0; @@ -262,10 +279,15 @@ static int pic32mx_protect_check(struct flash_bank *bank) return ERROR_TARGET_NOT_HALTED; } - if (pic32mx_info->dev_type == MX_1_2) - config0_address = PIC32MX_DEVCFG0_1_2; - else + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: + config0_address = PIC32MX_DEVCFG0_1xx_2xx; + break; + default: config0_address = PIC32MX_DEVCFG0; + break; + } target_read_u32(target, config0_address, &devcfg0); @@ -278,10 +300,17 @@ static int pic32mx_protect_check(struct flash_bank *bank) num_pages = 0xffff; /* All pages protected */ } else { /* pgm flash */ - if (pic32mx_info->dev_type == MX_1_2) - num_pages = (~devcfg0 >> 10) & 0x3f; - else + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + num_pages = (~devcfg0 >> 10) & 0x7f; + break; + case MX_17x_27x: + num_pages = (~devcfg0 >> 10) & 0x1ff; + break; + default: num_pages = (~devcfg0 >> 12) & 0xff; + break; + } } for (s = 0; s < bank->num_sectors && s < num_pages; s++) @@ -412,14 +441,16 @@ static uint32_t pic32mx_flash_write_code[] = { 0x00000000 /* nop */ }; -static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, +static int pic32mx_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t buffer_size = 16384; + struct working_area *write_algorithm; 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; @@ -427,28 +458,36 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, /* flash write code */ if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), - &pic32mx_info->write_algorithm) != ERROR_OK) { + &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } /* Change values for counters and row size, depending on variant */ - if (pic32mx_info->dev_type == MX_1_2) { + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: /* 128 byte row */ pic32mx_flash_write_code[8] = 0x2CD30020; pic32mx_flash_write_code[14] = 0x24840080; pic32mx_flash_write_code[15] = 0x24A50080; pic32mx_flash_write_code[17] = 0x24C6FFE0; - } else { + row_size = 128; + break; + default: /* 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; + break; } - retval = target_write_buffer(target, pic32mx_info->write_algorithm->address, - sizeof(pic32mx_flash_write_code), (uint8_t *)pic32mx_flash_write_code); + uint8_t code[sizeof(pic32mx_flash_write_code)]; + target_buffer_set_u32_array(target, code, ARRAY_SIZE(pic32mx_flash_write_code), + pic32mx_flash_write_code); + retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code); if (retval != ERROR_OK) return retval; @@ -456,39 +495,65 @@ static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) { - /* if we already allocated the writing code, but failed to get a + /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ - if (pic32mx_info->write_algorithm) - target_free_working_area(target, pic32mx_info->write_algorithm); + target_free_working_area(target, write_algorithm); 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); + init_reg_param(®_params[0], "r4", 32, PARAM_IN_OUT); + init_reg_param(®_params[1], "r5", 32, PARAM_OUT); + init_reg_param(®_params[2], "r6", 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; - retval = target_write_buffer(target, source->address, - thisrun_count * 4, buffer); - if (retval != ERROR_OK) - break; + 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; + } 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); + buf_set_u32(reg_params[2].value, 0, 32, thisrun_count + row_offset / 4); retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - pic32mx_info->write_algorithm->address, + write_algorithm->address, 0, 10000, &mips32_info); if (retval != ERROR_OK) { LOG_ERROR("error executing pic32mx flash write algorithm"); @@ -513,15 +578,21 @@ 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); + target_free_working_area(target, 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; } @@ -535,7 +606,7 @@ static int pic32mx_write_word(struct flash_bank *bank, uint32_t address, uint32_ return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5); } -static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) +static int pic32mx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { uint32_t words_remaining = (count / 4); uint32_t bytes_remaining = (count & 0x00000003); @@ -549,7 +620,7 @@ static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs return ERROR_TARGET_NOT_HALTED; } - LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 + LOG_DEBUG("writing to flash at address " TARGET_ADDR_FMT " at offset 0x%8.8" PRIx32 " count: 0x%8.8" PRIx32 "", bank->base, offset, count); if (offset & 0x3) { @@ -646,17 +717,21 @@ static int pic32mx_probe(struct flash_bank *bank) /* Check for PIC32mx1xx/2xx */ for (i = 0; pic32mx_devs[i].name != NULL; i++) { if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) { - if ((*(pic32mx_devs[i].name) == '1') || (*(pic32mx_devs[i].name) == '2')) - pic32mx_info->dev_type = MX_1_2; + if ((pic32mx_devs[i].name[0] == '1') || (pic32mx_devs[i].name[0] == '2')) + pic32mx_info->dev_type = (pic32mx_devs[i].name[1] == '7') ? MX_17x_27x : MX_1xx_2xx; break; } } - if (pic32mx_info->dev_type == MX_1_2) + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: page_size = 1024; - else + break; + default: page_size = 4096; - + break; + } if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) { /* 0x1FC00000: Boot flash size */ @@ -670,20 +745,29 @@ static int pic32mx_probe(struct flash_bank *bank) } #else /* fixed 12k boot bank - see comments above */ - if (pic32mx_info->dev_type == MX_1_2) + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: num_pages = (3 * 1024); - else + break; + default: num_pages = (12 * 1024); + break; + } #endif } else { /* read the flash size from the device */ if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) { - if (pic32mx_info->dev_type == MX_1_2) { + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 32k flash"); num_pages = (32 * 1024); - } else { + break; + default: LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash"); num_pages = (512 * 1024); + break; } } } @@ -795,7 +879,6 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command) 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; @@ -820,7 +903,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command) mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND); /* first check status of device */ - mchip_cmd = MCHP_STATUS; + uint8_t mchip_cmd = MCHP_STATUS; mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); if (mchip_cmd & (1 << 7)) { /* device is not locked */ @@ -884,7 +967,7 @@ static const struct command_registration pic32mx_command_handlers[] = { COMMAND_REGISTRATION_DONE }; -struct flash_driver pic32mx_flash = { +const struct flash_driver pic32mx_flash = { .name = "pic32mx", .commands = pic32mx_command_handlers, .flash_bank_command = pic32mx_flash_bank_command, @@ -897,4 +980,5 @@ struct flash_driver pic32mx_flash = { .erase_check = default_flash_blank_check, .protect_check = pic32mx_protect_check, .info = pic32mx_info, + .free_driver_priv = default_flash_free_driver_priv, };