From: <ge...@op...> - 2025-10-13 14:09:32
|
This is an automated email from Gerrit. "Name of user not set <din...@mi...>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9025 -- gerrit commit 04da9013f3457813bb2c1e33a719edb295a26015 Author: DineshArasu-Microchip <din...@mi...> Date: Mon Oct 13 19:32:51 2025 +0530 Adding WBZ451, WBZ450, PIC32WM_BZ and WBZ351 microchip flash drivers support Change-Id: I491341d2c2d50d4976ea454a4f7e477033db92eb Signed-off-by: Dinesh Arasu <din...@mi...> Signed-off-by: DineshArasu-Microchip <din...@mi...> diff --git a/doc/openocd.texi b/doc/openocd.texi index 7f7c8892fe..b3493b5795 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7064,6 +7064,32 @@ the appropriate at91sam7 target. @end deffn @end deffn +@anchor{pic32cx_bz} +@deffn {Flash Driver} {pic32cx_bz} +@cindex wbz451 +All members of the WBZ45x, PIC32CX_BZ2, PIC32WM_BZ6 microcontroller +families from Microchip include internal flash and use ARM's Cortex-M4 core. + +This driver supports: +@itemize +@item Row programming (1024 bytes per row) +@item Page erase (1024 bytes per row) +@item Skipping @code{0xFF}-only regions for faster flashing +@end itemize + +The driver is located at: @file{src/flash/nor/pic32cx_bz.c}. + +@example +flash bank $_FLASHNAME pic32cx_bz 0x01000000 0x00100000 0 0 $_TARGETNAME +@end example + +@deffn {Command} {pic32cx_bz dsu_reset_deassert} +This command releases internal reset held by DSU +and prepares reset vector catch in case of reset halt. +Command is used internally in event reset-deassert-post. +@end deffn +@end deffn + @deffn {Flash Driver} {avr} The AVR 8-bit microcontrollers from Atmel integrate flash memory. @emph{The current implementation is incomplete.} diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index f408559004..f64df62ff9 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -83,7 +83,8 @@ NOR_DRIVERS = \ %D%/w600.c \ %D%/xcf.c \ %D%/xmc1xxx.c \ - %D%/xmc4xxx.c + %D%/xmc4xxx.c \ + %D%/pic32cx_bz.c NORHEADERS = \ %D%/artery.h \ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 2bd2043633..bd467c4e5e 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -313,5 +313,6 @@ extern const struct flash_driver w600_flash; extern const struct flash_driver xcf_flash; extern const struct flash_driver xmc1xxx_flash; extern const struct flash_driver xmc4xxx_flash; +extern const struct flash_driver pic32cx_bz_flash; #endif /* OPENOCD_FLASH_NOR_DRIVER_H */ diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 6b0def6810..d4e3068e8a 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -92,6 +92,7 @@ static const struct flash_driver * const flash_drivers[] = { &xcf_flash, &xmc1xxx_flash, &xmc4xxx_flash, + &pic32cx_bz_flash, }; const struct flash_driver *flash_driver_find_by_name(const char *name) diff --git a/src/flash/nor/pic32cx_bz.c b/src/flash/nor/pic32cx_bz.c new file mode 100644 index 0000000000..a1748f3bb2 --- /dev/null +++ b/src/flash/nor/pic32cx_bz.c @@ -0,0 +1,570 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/************************************************************************************** + * Copyright (C) 2025 by Microchip Technologies Inc * + * Author: Dinesh Arasu - din...@mi... * + * * + * Description: Flash driver for WBZ and PIC32CX_BZx Microchip Curiosity Board * + **************************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include "helper/binarybuffer.h" +#include <helper/time_support.h> +#include <jtag/jtag.h> +#include <target/cortex_m.h> +#include <stdbool.h> +#include <string.h> +#include <target/target_type.h> +#include <stdlib.h> +#include <inttypes.h> + +#define DSU_DID_REG 0x41000018U + +/* Generic NVM operation bits */ +#define NVMCON_NVMWREN (1 << 14) +#define NVMCON_NVMWR (1 << 15) +#define NVMCON_OP_WORD_PROG 0x4001 +#define NVMCON_OP_ROW_PROG 0x4003 +#define NVMCON_OP_PAGE_ERASE 0x4004 +#define NVMCON_OP_PBC 0x4007 +#define NVMCON_OP_MASK 0x7FFF + +/* RAM staging buffer address used across drivers */ +#define RAM_BUF_ADDR 0x20000000U + +/* default row size used by these parts */ +#define DEFAULT_ROW_SIZE 1024U + +/* NVMLBWP unlock key used in originals */ +#define NVMLBWP_UNLOCK_KEY 0x80000000U + +struct pic32cx_dev { + uint32_t device_id; + const char *name; + uint32_t flash_base; + uint32_t flash_size; + uint32_t row_size; + uint32_t page_size; + uint32_t pac_base; + uint32_t nvmcon; + uint32_t nvmkey; + uint32_t nvmaddr; + uint32_t nvmsrcaddr; + uint32_t nvmdata; + uint32_t nvmconset; + uint32_t nvmconclr; + uint32_t nvmlbwp; + uint32_t nvm_param; + uint32_t nvm_err_mask; +}; + +static const struct pic32cx_dev device_table[] = { + { + .device_id = 0x00009B8F, /* WBZ451 */ + .name = "WBZ451", + .flash_base = 0x01000000U, + .flash_size = 0x00100000U, /* 1 MB */ + .row_size = DEFAULT_ROW_SIZE, + .page_size = DEFAULT_ROW_SIZE, + .pac_base = 0x40000000U, + .nvmcon = 0x44000600U, + .nvmkey = 0x44000620U, + .nvmaddr = 0x44000630U, + .nvmsrcaddr = 0x440006C0U, + .nvmdata = 0x44000640U, + .nvmconset = 0x44000608U, + .nvmconclr = 0x44000604U, + .nvmlbwp = 0x440006F0U, + .nvm_param = 0x44000610U, + .nvm_err_mask = 0x3F00U + }, + { + .device_id = 0x00009B0B, /* WBZ450 */ + .name = "WBZ450", + .flash_base = 0x01000000U, + .flash_size = 0x00100000U, /* 1 MB */ + .row_size = DEFAULT_ROW_SIZE, + .page_size = DEFAULT_ROW_SIZE, + .pac_base = 0x40000000U, + .nvmcon = 0x44000600U, + .nvmkey = 0x44000620U, + .nvmaddr = 0x44000630U, + .nvmsrcaddr = 0x440006C0U, + .nvmdata = 0x44000640U, + .nvmconset = 0x44000608U, + .nvmconclr = 0x44000604U, + .nvmlbwp = 0x440006F0U, + .nvm_param = 0x44000610U, + .nvm_err_mask = 0x3F00U + }, + { + .device_id = 0x00009E03, /* WBZ351 */ + .name = "WBZ351", + .flash_base = 0x01000000U, + .flash_size = 0x00080000U, /* 512 KB */ + .row_size = DEFAULT_ROW_SIZE, + .page_size = DEFAULT_ROW_SIZE, + .pac_base = 0x40000000U, + .nvmcon = 0x44000600U, + .nvmkey = 0x44000620U, + .nvmaddr = 0x44000630U, + .nvmsrcaddr = 0x440006C0U, + .nvmdata = 0x44000640U, + .nvmconset = 0x44000608U, + .nvmconclr = 0x44000604U, + .nvmlbwp = 0x440006F0U, + .nvm_param = 0x44000610U, + .nvm_err_mask = 0x3F00U + }, + { + .device_id = 0x0001A800, /* PIC32WM_BZ6204 */ + .name = "PIC32WM", + .flash_base = 0x01000000U, + .flash_size = 0x00200000U, /* 2 MB */ + .row_size = DEFAULT_ROW_SIZE, + .page_size = DEFAULT_ROW_SIZE, + .pac_base = 0x40000000U, + .nvmcon = 0x44000600U, + .nvmkey = 0x44000620U, + .nvmaddr = 0x44000630U, + .nvmsrcaddr = 0x440006C0U, + .nvmdata = 0x44000640U, + .nvmconset = 0x44000608U, + .nvmconclr = 0x44000604U, + .nvmlbwp = 0x440006F0U, + .nvm_param = 0x44000610U, + .nvm_err_mask = 0x3F00U + } +}; + +struct pic32cx_priv { + struct target *target; + bool probed; + const struct pic32cx_dev *dev; + uint32_t page_size; + uint32_t num_pages; +}; + +static const struct pic32cx_dev *find_device_by_did(uint32_t did) +{ + for (size_t i = 0; i < ARRAY_SIZE(device_table); ++i) + if (device_table[i].device_id != 0 && device_table[i].device_id == did) + return &device_table[i]; + return NULL; +} + +static const struct pic32cx_dev *find_device_by_name(const char *name) +{ + if (!name) return NULL; + for (size_t i = 0; i < ARRAY_SIZE(device_table); ++i) + if (strstr(name, device_table[i].name) != NULL) + return &device_table[i]; + return NULL; +} + +/* unlock via PAC if locked (same as originals) */ +static int pic32cx_unlock_flash(const struct pic32cx_dev *dev, struct target *t) +{ + uint32_t status; + int res = target_read_u32(t, dev->pac_base + 0x18U, &status); + if (res != ERROR_OK) return res; + + if (status & (1 << 1)) { + LOG_INFO("PAC indicates NVMCTRL is locked. Attempting to unlock..."); + res = target_write_u32(t, dev->pac_base + 0x20U, (1 << 1)); + if (res != ERROR_OK) return res; + } + return target_read_u32(t, dev->pac_base + 0x18U, &status); +} + +/* Generic NVM command issuer derived from wbz451_issue_nvmcmd */ +static int pic32cx_issue_nvmcmd(const struct pic32cx_dev *dev, struct target *t, + uint32_t flash_addr, uint16_t cmd, uint32_t src_addr) +{ + int res; + + /* For boot/alias region operations we must write NVMLBWP */ + if (flash_addr < dev->flash_base) { + if (dev->nvmlbwp) { + res = target_write_u32(t, dev->nvmlbwp, NVMLBWP_UNLOCK_KEY); + if (res != ERROR_OK) return res; + } + } else { + res = pic32cx_unlock_flash(dev, t); + if (res != ERROR_OK) return res; + } + + /* Clear previous error flags */ + if (dev->nvmconclr) { + res = target_write_u32(t, dev->nvmconclr, dev->nvm_err_mask); + if (res != ERROR_OK) return res; + } + + /* Align dest to row */ + flash_addr &= ~(dev->row_size - 1U); + + /* Set NVMSRCADDR if ROW_PROGRAM */ + if (cmd == NVMCON_OP_ROW_PROG && dev->nvmsrcaddr) { + res = target_write_u32(t, dev->nvmsrcaddr, src_addr); + if (res != ERROR_OK) return res; + } + + /* Set NVMADDR */ + res = target_write_u32(t, dev->nvmaddr, flash_addr); + if (res != ERROR_OK) return res; + + /* Set WREN and operation */ + res = target_write_u32(t, dev->nvmcon, NVMCON_NVMWREN | (cmd & NVMCON_OP_MASK)); + if (res != ERROR_OK) return res; + + /* NVMKEY sequence */ + res = target_write_u32(t, dev->nvmkey, 0x00000000U); if (res != ERROR_OK) return res; + res = target_write_u32(t, dev->nvmkey, 0xAA996655U); if (res != ERROR_OK) return res; + res = target_write_u32(t, dev->nvmkey, 0x556699AAU); if (res != ERROR_OK) return res; + + /* Start operation */ + res = target_write_u32(t, dev->nvmconset, NVMCON_NVMWR); + if (res != ERROR_OK) return res; + + /* Wait for NVMWR to clear */ + uint32_t val; + int timeout = 10000; + do { + res = target_read_u32(t, dev->nvmcon, &val); + if (res != ERROR_OK) return res; + if (!--timeout) { + LOG_ERROR("Timeout waiting for NVMWR clear (addr: 0x%08" PRIx32 ", cmd: 0x%X)", flash_addr, cmd); + return ERROR_FAIL; + } + alive_sleep(1); + } while (val & NVMCON_NVMWR); + + if (val & dev->nvm_err_mask) { + LOG_ERROR("NVM error detected (NVMCON=0x%08" PRIx32 ")", val); + return ERROR_FAIL; + } + + /* Clear NVMWREN */ + return target_write_u32(t, dev->nvmconclr, NVMCON_NVMWREN); +} + +/* Probe: uses per-device probe logic (keeps original region checks) */ +static int pic32cx_probe(struct flash_bank *bank) +{ + struct pic32cx_priv *priv = bank->driver_priv; + if (!priv) return ERROR_FAIL; + if (priv->probed) return ERROR_OK; + + struct target *t = bank->target; + uint32_t did = 0; + int res = target_read_u32(t, DSU_DID_REG, &did); + + const struct pic32cx_dev *dev = NULL; + if (res == ERROR_OK) { + dev = find_device_by_did(did); + if (dev) + LOG_INFO("Detected device by DSU DID: %s (DID 0x%08" PRIx32 ")", dev->name, did); + } else { + LOG_WARNING("Failed to read DSU DID at 0x%08" PRIx32 ". Will try name-based detection.", DSU_DID_REG); + } + + /* name fallback */ + if (!dev) + dev = find_device_by_name(bank->name); + + if (!dev) { + LOG_WARNING("No device matched by DID or name. Falling back to WBZ451 defaults."); + dev = &device_table[0]; + } + + priv->dev = dev; + priv->target = t; + + /* Use device-specific probe ranges — reuse logic from original files */ + uint32_t base = bank->base; + uint32_t param = 0; + if (dev->nvm_param) + target_read_u32(t, dev->nvm_param, ¶m); + + /* Apply device-specific mapping (copied/adapted from originals) */ + if ((strcmp(dev->name, "WBZ451") == 0) || (strcmp(dev->name, "WBZ450") == 0)) { + if (base < 0x00005000U) { + priv->page_size = dev->row_size; + priv->num_pages = 20; /* 20 kB BootFlash */ + } else if (base >= 0x00005000U && base < 0x00006000U) { + priv->page_size = dev->row_size; priv->num_pages = 4; + } else if (base >= 0x00006000U && base < 0x00007000U) { + priv->page_size = dev->row_size; priv->num_pages = 4; + } else if (base >= 0x00045000U && base < 0x00047000U) { + priv->page_size = dev->row_size; priv->num_pages = 8; + } else if (base >= dev->flash_base && base < (dev->flash_base + dev->flash_size)) { + priv->page_size = dev->row_size; priv->num_pages = dev->flash_size / dev->row_size; + } else if (bank->base == 0xE000ED10U) { + priv->page_size = dev->row_size; priv->num_pages = 1; + } + } else if ((strcmp(dev->name, "WBZ351") == 0) || (strcmp(dev->name, "WBZ350") == 0)) { + /* mapping from wbz351.c */ + if (base < 0x00010000U) { + priv->page_size = dev->row_size; priv->num_pages = 64; + } else if (bank->base >= 0x00800000U && base < 0x00805000U) { + priv->page_size = dev->row_size; priv->num_pages = 20; + } else if (bank->base >= 0x00805000U && bank->base < 0x00806000U) { + priv->page_size = dev->row_size; priv->num_pages = 4; + } else if (bank->base >= 0x00806000U && bank->base < 0x00827000U) { + priv->page_size = dev->row_size; priv->num_pages = 132; + } else if (bank->base >= dev->flash_base && bank->base < (dev->flash_base + dev->flash_size)) { + priv->page_size = dev->row_size; priv->num_pages = dev->flash_size / dev->row_size; + } else if (bank->base == 0xE000ED10U) { + priv->page_size = dev->row_size; priv->num_pages = 1; + } + } else if (strcmp(dev->name, "PIC32WM") == 0) { /* PIC32WM_BZ6204 mapping similar to pic32wm.c */ + if (base < 0x00010000U) { + priv->page_size = dev->row_size; priv->num_pages = 64; + } else if (bank->base >= 0x00800000U && bank->base < 0x00810000U) { + priv->page_size = dev->row_size; priv->num_pages = 64; + } else if (bank->base >= 0x00810000U && bank->base < 0x00811000U) { + priv->page_size = dev->row_size; priv->num_pages = 4; + } else if (bank->base >= 0x00811000U && bank->base < 0x00812000U) { + priv->page_size = dev->row_size; priv->num_pages = 4; + } else if (bank->base >= dev->flash_base && bank->base < (dev->flash_base + dev->flash_size)) { + priv->page_size = dev->row_size; priv->num_pages = dev->flash_size / dev->row_size; + } else if (bank->base == 0xE000ED10U) { + priv->page_size = dev->row_size; priv->num_pages = 1; + } + } + + /* if not set above, fall back to a single page of row_size */ + if (priv->page_size == 0) { + priv->page_size = dev->row_size; + priv->num_pages = (dev->flash_size / dev->row_size); + } + + bank->size = priv->page_size * priv->num_pages; + bank->num_sectors = priv->num_pages; + + if (bank->sectors) { + free(bank->sectors); + bank->sectors = NULL; + } + + bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector)); + if (!bank->sectors) return ERROR_FAIL; + + for (unsigned int i = 0; i < bank->num_sectors; ++i) { + bank->sectors[i].offset = i * priv->page_size; + bank->sectors[i].size = priv->page_size; + bank->sectors[i].is_protected = 0; + } + + priv->probed = true; + LOG_INFO("%s: probe complete. base=0x%08" PRIx64 " size=0x%08" PRIx32 " pages=%" PRIu32, + dev->name, (uint64_t)bank->base, bank->size, priv->num_pages); + + return ERROR_OK; +} + +/* Erase: page erase (acts on sectors) */ +static int pic32cx_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +{ + struct pic32cx_priv *p = bank->driver_priv; + if (!p) return ERROR_FAIL; + + struct target *t = bank->target; + if (t->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; + + const struct pic32cx_dev *dev = p->dev; + + for (unsigned int i = first; i <= last; ++i) { + uint32_t addr = bank->base + i * p->page_size; + int res = pic32cx_issue_nvmcmd(dev, t, addr, NVMCON_OP_PAGE_ERASE, 0); + if (res != ERROR_OK) return res; + } + return ERROR_OK; +} + +/* Write: row-by-row write (same pattern as originals) */ +static int pic32cx_write(struct flash_bank *bank, const uint8_t *buf, uint32_t offset, uint32_t count) +{ + struct pic32cx_priv *p = bank->driver_priv; + if (!p) return ERROR_FAIL; + + struct target *target = bank->target; + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + const struct pic32cx_dev *dev = p->dev; + uint32_t row_size = dev->row_size; + uint32_t addr = bank->base + offset; + const uint32_t end = addr + count; + + for (uint32_t row_addr = addr & ~(row_size - 1U); row_addr < end; row_addr += row_size) { + uint8_t *row_buf = malloc(row_size); + if (!row_buf) { + LOG_ERROR("Out of memory allocating row buffer"); + return ERROR_FAIL; + } + + int res = target_read_memory(target, row_addr, 4, row_size / 4, row_buf); + if (res != ERROR_OK) { + LOG_ERROR("Failed to read flash row at 0x%08" PRIx32, row_addr); + free(row_buf); + return res; + } + + for (uint32_t i = 0; i < row_size; ++i) { + uint32_t abs_addr = row_addr + i; + if (abs_addr >= addr && abs_addr < end) row_buf[i] = buf[abs_addr - addr]; + } + + res = target_write_buffer(target, RAM_BUF_ADDR, row_size, row_buf); + if (res != ERROR_OK) { + LOG_ERROR("Failed to write row buffer to RAM at 0x%08" PRIx32, (uint32_t)RAM_BUF_ADDR); + free(row_buf); + return res; + } + + res = pic32cx_issue_nvmcmd(dev, target, row_addr, NVMCON_OP_ROW_PROG, RAM_BUF_ADDR); + if (res != ERROR_OK) { + LOG_ERROR("Failed to program row at 0x%08" PRIx32, row_addr); + free(row_buf); + return res; + } + + alive_sleep(2); + free(row_buf); + } + + LOG_INFO("%s: Write completed", p->dev->name); + return ERROR_OK; +} + +/* dsu_reset_deassert - tries to find a bank name (keeps compatibility) */ +COMMAND_HANDLER(pic32cx_handle_dsu_reset_deassert) +{ + struct target *target = get_current_target(CMD_CTX); + if (!target) + return ERROR_FAIL; + + struct flash_bank *bank = get_flash_bank_by_num_noprobe(0); + if (!bank) + return ERROR_FAIL; + + target_write_u8(target, 0x44000001U, 0x02U); + target_write_u32(target, 0x44000100U, 0x8000U); + target_write_u32(target, 0xE000ED0CU, 0x05FA0004U); + target_write_u32(target, 0xE000ED0CU, 0x05FA0000U); + alive_sleep(100); + return ERROR_OK; +} + +/* flash bank attach handler */ +FLASH_BANK_COMMAND_HANDLER(pic32cx_flash_bank_command) +{ + struct pic32cx_priv *chip = calloc(1, sizeof(*chip)); + if (!chip) return ERROR_FAIL; + chip->target = bank->target; + chip->probed = false; + chip->dev = &device_table[0]; /* default */ + chip->page_size = device_table[0].page_size; + bank->driver_priv = chip; + return ERROR_OK; +} + +/* erase_page and write_word wrappers that operate using first table device (manual exec) */ +COMMAND_HANDLER(pic32cx_handle_erase_page_command) +{ + struct target *target = get_current_target(CMD_CTX); + if (!target || CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + uint32_t addr; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + + struct flash_bank *bank = get_flash_bank_by_num_noprobe(0); + if (!bank) + return ERROR_FAIL; + + struct pic32cx_priv *p = bank->driver_priv; + const struct pic32cx_dev *dev = (p && p->dev) ? p->dev : &device_table[0]; + + return pic32cx_issue_nvmcmd(dev, target, addr, NVMCON_OP_PAGE_ERASE, 0); +} + +COMMAND_HANDLER(pic32cx_handle_write_word_command) +{ + struct target *target = get_current_target(CMD_CTX); + if (!target || CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + uint32_t addr, value; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + + struct flash_bank *bank = get_flash_bank_by_num_noprobe(0); + if (!bank) + return ERROR_FAIL; + + struct pic32cx_priv *p = bank->driver_priv; + const struct pic32cx_dev *dev = (p && p->dev) ? p->dev : &device_table[0]; + + target_write_u32(target, dev->nvmdata, value); + return pic32cx_issue_nvmcmd(dev, target, addr, NVMCON_OP_WORD_PROG, 0); +} + +/* command array registration */ +static const struct command_registration pic32cx_exec_command_handlers[] = { + { + .name = "erase_page", + .handler = pic32cx_handle_erase_page_command, + .mode = COMMAND_EXEC, + .usage = "<address>", + .help = "Erase a flash page at the given address", + }, + { + .name = "write_word", + .handler = pic32cx_handle_write_word_command, + .mode = COMMAND_EXEC, + .usage = "<address> <32bit_hex_value>", + .help = "Write a 32-bit word to flash at the given address", + }, + { + .name = "dsu_reset_deassert", + .handler = pic32cx_handle_dsu_reset_deassert, + .mode = COMMAND_EXEC, + .usage = "", + .help = "Device-specific DSU reset deassert sequence", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration pic32cx_command_handlers[] = { + { + .name = "pic32cx_bz", + .mode = COMMAND_ANY, + .help = "pic32cx_bz flash command group", + .usage = "", + .chain = pic32cx_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +const struct flash_driver pic32cx_bz_flash = { + .name = "pic32cx_bz", + .commands = pic32cx_command_handlers, + .flash_bank_command = pic32cx_flash_bank_command, + .erase = pic32cx_erase, + .protect = NULL, + .write = pic32cx_write, + .read = default_flash_read, + .probe = pic32cx_probe, + .auto_probe = pic32cx_probe, + .erase_check = default_flash_blank_check, + .protect_check = NULL, + .free_driver_priv = default_flash_free_driver_priv, +}; diff --git a/src/target/image.h b/src/target/image.h index 03bc068d62..ac42870be7 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -25,7 +25,7 @@ #endif #define IMAGE_MAX_ERROR_STRING (256) -#define IMAGE_MAX_SECTIONS (512) +#define IMAGE_MAX_SECTIONS (2048) #define IMAGE_MEMORY_CACHE_SIZE (2048) diff --git a/tcl/board/microchip/pic32wm_bz6204_curiosity.cfg b/tcl/board/microchip/pic32wm_bz6204_curiosity.cfg new file mode 100644 index 0000000000..25081e3ea6 --- /dev/null +++ b/tcl/board/microchip/pic32wm_bz6204_curiosity.cfg @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Microchip pic32wm_bz6204_curiosity. +# https://www.microchip.com/en-us/development-tool/ea81w68a +# + +source [find interface/cmsis-dap.cfg] + +set CHIPNAME pic32wm + +source [find target/pic32wm.cfg] + +reset_config srst_only diff --git a/tcl/board/microchip/wbz351_curiosity.cfg b/tcl/board/microchip/wbz351_curiosity.cfg new file mode 100644 index 0000000000..54606ea5e2 --- /dev/null +++ b/tcl/board/microchip/wbz351_curiosity.cfg @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Microchip WBZ351 Xplained Pro evaluation kit. +# https://www.microchip.com/en-us/development-tool/ev19j06a +# + +source [find interface/cmsis-dap.cfg] + +set CHIPNAME wbz351 + +source [find target/wbz351.cfg] + +reset_config srst_only diff --git a/tcl/board/microchip/wbz450_curiosity.cfg b/tcl/board/microchip/wbz450_curiosity.cfg new file mode 100644 index 0000000000..a92f930c9e --- /dev/null +++ b/tcl/board/microchip/wbz450_curiosity.cfg @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Microchip (former Atmel) WBZ451 Xplained Pro evaluation kit. +# https://www.microchip.com/en-us/development-tool/ev22l65a +# + +source [find interface/cmsis-dap.cfg] + +set CHIPNAME wbz450 + +source [find target/wbz450.cfg] + +reset_config srst_only diff --git a/tcl/board/microchip/wbz451_curiosity.cfg b/tcl/board/microchip/wbz451_curiosity.cfg new file mode 100644 index 0000000000..abf2f09f2f --- /dev/null +++ b/tcl/board/microchip/wbz451_curiosity.cfg @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# +# Microchip (former Atmel) WBZ451 Xplained Pro evaluation kit. +# https://www.microchip.com/en-us/development-tool/ev96b94a +# + +source [find interface/cmsis-dap.cfg] + +set CHIPNAME wbz451 + +source [find target/wbz451.cfg] + +reset_config srst_only diff --git a/tcl/target/pic32wm.cfg b/tcl/target/pic32wm.cfg new file mode 100644 index 0000000000..86ef611c1d --- /dev/null +++ b/tcl/target/pic32wm.cfg @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# OpenOCD Target Config for Microchip PIC32WM_BZ6 +# Author: Dinesh Arasu (din...@mi...) + +# --- Setup DAP and CPU --- +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME pic32wm +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x04D8810B +} + +transport select swd + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_DAP_TAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap + +# --- Work Area in RAM --- +$_TARGETNAME configure -work-area-phys 0x20000000 \ + -work-area-size 0x80000 \ + -work-area-backup 0 + +# --- Reset Behavior --- +$_TARGETNAME configure -event reset-deassert-post { + pic32cx_bz dsu_reset_deassert +} + +reset_config srst_only srst_nogate + +adapter speed 2000 + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +# --- Flash Banks --- +flash bank pic32wm_flash pic32cx_bz 0x01000000 0x00200000 0 0 $_TARGETNAME + +flash bank pic32wm_Secure_boot pic32cx_bz 0x00000000 0x10000 0 0 $_TARGETNAME + +flash bank pic32wm_boot pic32cx_bz 0x00800000 0x10000 0 0 $_TARGETNAME + +flash bank pic32wm_device_config pic32cx_bz 0x00810000 0x1000 0 0 $_TARGETNAME + +flash bank pic32wm_otp_config pic32cx_bz 0x00811000 0x1000 0 0 $_TARGETNAME + +flash bank pic32wm_config_CM4F pic32cx_bz 0xE000ed10 0x100 0 0 $_TARGETNAME \ No newline at end of file diff --git a/tcl/target/wbz351.cfg b/tcl/target/wbz351.cfg new file mode 100644 index 0000000000..25965c629b --- /dev/null +++ b/tcl/target/wbz351.cfg @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# OpenOCD Target Config for Microchip WBZ351 +# Author: Dinesh Arasu (din...@mi...) + +# --- Setup DAP and CPU --- +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME wbz351 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x04D8810B +} + +transport select swd + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_DAP_TAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap + +# --- Work Area in RAM --- +$_TARGETNAME configure -work-area-phys 0x20000000 \ + -work-area-size 0x18000 \ + -work-area-backup 0 + +# --- Reset Behavior --- +$_TARGETNAME configure -event reset-deassert-post { + pic32cx_bz dsu_reset_deassert +} + +reset_config srst_only srst_nogate + +adapter speed 2000 + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +# --- Flash Banks --- +flash bank wbz351_flash pic32cx_bz 0x01000000 0x00080000 0 0 $_TARGETNAME + +flash bank wbz351_Secure_boot pic32cx_bz 0x00000000 0x10000 0 0 $_TARGETNAME + +flash bank wbz351_boot pic32cx_bz 0x00800000 0x5000 0 0 $_TARGETNAME + +flash bank wbz351_device_config pic32cx_bz 0x00805000 0x1000 0 0 $_TARGETNAME + +flash bank wbz351_otp_config pic32cx_bz 0x00806000 0x21000 0 0 $_TARGETNAME + +flash bank wbz351_config_CM4F pic32cx_bz 0xE000ed10 0x100 0 0 $_TARGETNAME + diff --git a/tcl/target/wbz450.cfg b/tcl/target/wbz450.cfg new file mode 100644 index 0000000000..efcc16f8a7 --- /dev/null +++ b/tcl/target/wbz450.cfg @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# OpenOCD Target Config for Microchip WBZ450 +# Author: Dinesh Arasu (din...@mi...) + +# --- Setup DAP and CPU --- +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME wbz450 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x04D8810B +} + +transport select swd + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_DAP_TAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap + +# --- Work Area in RAM --- +$_TARGETNAME configure -work-area-phys 0x20000000 \ + -work-area-size 0x20000 \ + -work-area-backup 0 + +# --- Reset Behavior --- +$_TARGETNAME configure -event reset-deassert-post { + pic32cx_bz dsu_reset_deassert +} + +reset_config srst_only srst_nogate + +adapter speed 2000 + +if {![using_hla]} { + cortex_m reset_config sysresetreq +} + +# --- Flash Banks --- +flash bank wbz450_flash pic32cx_bz 0x01000000 0x00100000 0 0 $_TARGETNAME + +flash bank wbz450_boot pic32cx_bz 0x00000000 0x5000 0 0 $_TARGETNAME + +flash bank wbz450_device_config pic32cx_bz 0x00005000 0x1000 0 0 $_TARGETNAME + +flash bank wbz450_otp pic32cx_bz 0x00006000 0x1000 0 0 $_TARGETNAME + +flash bank wbz450_configbits pic32cx_bz 0x00045000 0x2000 0 0 $_TARGETNAME + +flash bank wbz450_config_CM4F pic32cx_bz 0xE000ed10 0x100 0 0 $_TARGETNAME \ No newline at end of file diff --git a/tcl/target/wbz451.cfg b/tcl/target/wbz451.cfg new file mode 100644 index 0000000000..53e6bb5c5e --- /dev/null +++ b/tcl/target/wbz451.cfg @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# OpenOCD Target Config for Microchip WBZ451 +# Author: Dinesh Arasu (din...@mi...) + +# --- Setup DAP and CPU --- +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME wbz451 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x04D8810B +} + +transport select swd + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_DAP_TAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap + +# --- Work Area in RAM --- +$_TARGETNAME configure -work-area-phys 0x20000000 \ + -work-area-size 0x20000 \ + -work-area-backup 0 + +# --- Reset Behavior --- +$_TARGETNAME configure -event reset-deassert-post { + pic32cx_bz dsu_reset_deassert +} + +reset_config srst_only srst_nogate + +adapter speed 2000 + +if {![using_hla]} { + cortex_m reset_config sysresetreq +} + +# --- Flash Banks --- +flash bank wbz451_flash pic32cx_bz 0x01000000 0x00100000 0 0 $_TARGETNAME + +flash bank wbz451_boot pic32cx_bz 0x00000000 0x5000 0 0 $_TARGETNAME + +flash bank wbz451_device_config pic32cx_bz 0x00005000 0x1000 0 0 $_TARGETNAME + +flash bank wbz451_otp pic32cx_bz 0x00006000 0x1000 0 0 $_TARGETNAME + +flash bank wbz451_configbits pic32cx_bz 0x00045000 0x2000 0 0 $_TARGETNAME + +flash bank wbz451_config_CM4F pic32cx_bz 0xE000ed10 0x100 0 0 $_TARGETNAME \ No newline at end of file -- |