This is an automated email from Gerrit.

"Name of user not set <[email protected]>" 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 <[email protected]>
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 <[email protected]>
    Signed-off-by: DineshArasu-Microchip <[email protected]>

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 - [email protected]                         
        *
+ *                                                                             
        *
+ *   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, &param);
+
+    /* 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 ([email protected])
+
+# --- 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 ([email protected])
+
+# --- 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 ([email protected])
+
+# --- 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 ([email protected])
+
+# --- 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

-- 

Reply via email to