This is an automated email from Gerrit.

"Michael Schwingen <[email protected]>" just uploaded a new 
patch set to Gerrit, which you can find at 
https://review.openocd.org/c/openocd/+/6543

-- gerrit

commit 88c3b55d30f2cbf4dbb05b6ba8a2187c3e1a6d55
Author: Michael Schwingen <[email protected]>
Date:   Sun Sep 5 20:33:38 2021 +0200

    add GigaDevice GD32Exxx flash driver
    
    GigaDevice parts are quite similar to STM32, so they can use most of the
    STM32F1 flash driver unmodified.  However, even when GD32 uses different
    cores (CM23 on GD32E230) and core revisions for now, collisions in device
    IDs are inevitable (as seen on GD32F1x0).  Since auto-detection is not
    possible, the best way is to add that knowledge to the config files by
    adding a GD32 flash driver that knows about the GD32 parts.
    
    Patch: split STM32F1 driver into a common core and a thin wrapper for STM32
    and GD32 variants.  This makes it possible to separate device IDs used for
    flash size detection without risking collisions between STM32 and GD32
    parts.
    
    The current GD32F1x0/GD32F3x0 quick-hack is left as-is in the STM32 driver,
    as I don't have hardware to test those parts.
    
    Signed-off-by: Michael Schwingen <[email protected]>
    Change-Id: Ib847a9c702604cdda60477d50ca8e9e13d6c1f6e

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 9c94c7168..c2ed2d0c2 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -6335,6 +6335,22 @@ flash bank $@{_FLASHNAME@}1 fm4 0x00100000 0 0 0 \
 nor is Chip Erase (only Sector Erase is implemented).}
 @end deffn
 
+@deffn {Flash Driver} {gd32}
+@cindex gd32
+The GigaDevice GD32E23x family combines an ARM Cortex-M23 core with
+internal flash and peripherals that are quite similar to their
+STM32F1xx counterparts. The GD32 flash driver re-uses most of the
+stm32f1x flash driver internally, and only adds detection logic for
+the GD32 variants. Currently, only the GD32E230 is supported.
+
+@example
+flash bank $_FLASHNAME gd32 0 0 0 0 $_TARGETNAME
+@end example
+
+All the documentation of the stm32f1x flash driver applies, as well as
+the special stm32f1x commands.
+@end deffn
+
 @deffn {Flash Driver} {kinetis}
 @cindex kinetis
 Kx, KLx, KVx and KE1x members of the Kinetis microcontroller family
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 3e35c0954..6e3b1db5b 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -44,6 +44,7 @@ extern const struct flash_driver faux_flash;
 extern const struct flash_driver fm3_flash;
 extern const struct flash_driver fm4_flash;
 extern const struct flash_driver fespi_flash;
+extern const struct flash_driver gd32_flash;
 extern const struct flash_driver jtagspi_flash;
 extern const struct flash_driver kinetis_flash;
 extern const struct flash_driver kinetis_ke_flash;
@@ -119,6 +120,7 @@ static const struct flash_driver * const flash_drivers[] = {
        &fm3_flash,
        &fm4_flash,
        &fespi_flash,
+       &gd32_flash,
        &jtagspi_flash,
        &kinetis_flash,
        &kinetis_ke_flash,
diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c
index 3bda9bc20..650b771fd 100644
--- a/src/flash/nor/stm32f1x.c
+++ b/src/flash/nor/stm32f1x.c
@@ -7,7 +7,10 @@
  *                                                                         *
  *   Copyright (C) 2011 by Andreas Fritiofson                              *
  *   [email protected]                                          *
- *
+ *                                                                         *
+ *   Copyright (C) 2021 by Michael Schwingen                               *
+ *   [email protected]                                                 *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -113,10 +116,13 @@ struct stm32x_options {
        uint32_t protection;
 };
 
+enum dev_vendor { VENDOR_ST, VENDOR_GD};
+
 struct stm32x_flash_bank {
        struct stm32x_options option_bytes;
        int ppage_size;
        bool probed;
+       enum dev_vendor vendor;
 
        bool has_dual_banks;
        /* used to access dual flash bank stm32xl */
@@ -126,10 +132,14 @@ struct stm32x_flash_bank {
        int user_data_offset;
        int option_offset;
        uint32_t user_bank_size;
+
+       uint32_t flash_size_reg;
+       uint32_t device_id_reg;
+       uint32_t device_id;
 };
 
 static int stm32x_mass_erase(struct flash_bank *bank);
-static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id);
+static int stm32x_detect(struct flash_bank *bank);
 static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer,
                uint32_t address, uint32_t count);
 
@@ -619,11 +629,11 @@ cleanup:
        return retval;
 }
 
-static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
+static int stm32x_detect(struct flash_bank *bank)
 {
        struct target *target = bank->target;
        struct cortex_m_common *cortex_m = target_to_cm(target);
-       uint32_t device_id_register = 0;
+       struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
 
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
@@ -632,32 +642,30 @@ static int stm32x_get_device_id(struct flash_bank *bank, 
uint32_t *device_id)
 
        switch (cortex_m->core_info->partno) {
        case CORTEX_M0_PARTNO: /* STM32F0x devices */
-               device_id_register = 0x40015800;
+               stm32x_info->device_id_reg = 0x40015800;
+               stm32x_info->flash_size_reg = 0x1FFFF7CC;
                break;
        case CORTEX_M3_PARTNO: /* STM32F1x devices */
-               device_id_register = 0xE0042000;
+               stm32x_info->device_id_reg = 0xE0042000;
+               stm32x_info->flash_size_reg = 0x1FFFF7E0;
                break;
        case CORTEX_M4_PARTNO: /* STM32F3x devices */
-               device_id_register = 0xE0042000;
+               stm32x_info->device_id_reg = 0xE0042000;
+               stm32x_info->flash_size_reg = 0x1FFFF7CC;
                break;
        default:
                LOG_ERROR("Cannot identify target as a stm32x");
                return ERROR_FAIL;
        }
 
-       /* read stm32 device id register */
-       int retval = target_read_u32(target, device_id_register, device_id);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return retval;
+       return ERROR_OK;
 }
 
-static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t 
*flash_size_in_kb)
+static int gd32_detect(struct flash_bank *bank)
 {
        struct target *target = bank->target;
        struct cortex_m_common *cortex_m = target_to_cm(target);
-       uint32_t flash_size_reg;
+       struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
 
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
@@ -665,36 +673,34 @@ static int stm32x_get_flash_size(struct flash_bank *bank, 
uint16_t *flash_size_i
        }
 
        switch (cortex_m->core_info->partno) {
-       case CORTEX_M0_PARTNO: /* STM32F0x devices */
-               flash_size_reg = 0x1FFFF7CC;
+       case CORTEX_M3_PARTNO:
+               stm32x_info->device_id_reg = 0xE0042000;
+               stm32x_info->flash_size_reg = 0x1FFFF7E0;
                break;
-       case CORTEX_M3_PARTNO: /* STM32F1x devices */
-               flash_size_reg = 0x1FFFF7E0;
-               break;
-       case CORTEX_M4_PARTNO: /* STM32F3x devices */
-               flash_size_reg = 0x1FFFF7CC;
+       case CORTEX_M23_PARTNO:
+               stm32x_info->device_id_reg = 0x40015800;
+               stm32x_info->flash_size_reg = 0x1FFFF7E0;
                break;
        default:
-               LOG_ERROR("Cannot identify target as a stm32x");
+               LOG_ERROR("Cannot identify GD32 target");
                return ERROR_FAIL;
        }
 
-       int retval = target_read_u16(target, flash_size_reg, flash_size_in_kb);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return retval;
+       return ERROR_OK;
 }
 
-static int stm32x_probe(struct flash_bank *bank)
+
+static int stm32f1xx_probe_common(struct flash_bank *bank, enum dev_vendor 
vendor)
 {
        struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
+       struct target *target = bank->target;
        uint16_t flash_size_in_kb;
        uint16_t max_flash_size_in_kb;
-       uint32_t dbgmcu_idcode;
        int page_size;
        uint32_t base_address = 0x08000000;
+       int retval;
 
+       stm32x_info->vendor = vendor;
        stm32x_info->probed = false;
        stm32x_info->register_base = FLASH_REG_BASE_B0;
        stm32x_info->user_data_offset = 10;
@@ -703,160 +709,194 @@ static int stm32x_probe(struct flash_bank *bank)
        /* default factory read protection level 0 */
        stm32x_info->default_rdp = 0xA5;
 
-       /* read stm32 device id register */
-       int retval = stm32x_get_device_id(bank, &dbgmcu_idcode);
+       /* setup device id register and setup device-dependent variables */
+       switch(vendor) {
+       case VENDOR_ST:
+               retval = stm32x_detect(bank);
+               break;
+       case VENDOR_GD:
+               retval = gd32_detect(bank);
+               break;
+       default:
+               retval = ERROR_FAIL;
+       }
+
        if (retval != ERROR_OK)
                return retval;
 
-       LOG_INFO("device id = 0x%08" PRIx32 "", dbgmcu_idcode);
+       /* read device id register */
+       retval = target_read_u32(target, stm32x_info->device_id_reg, 
&stm32x_info->device_id);
+       if (retval != ERROR_OK)
+               return retval;
 
-       uint16_t device_id = dbgmcu_idcode & 0xfff;
-       uint16_t rev_id = dbgmcu_idcode >> 16;
+       LOG_INFO("vendor %s, device id = 0x%08" PRIx32 "", (vendor == 
VENDOR_ST) ? "ST":"GD", stm32x_info->device_id);
 
-       /* set page size, protection granularity and max flash size depending 
on family */
-       switch (device_id) {
-       case 0x440: /* stm32f05x */
-               page_size = 1024;
-               stm32x_info->ppage_size = 4;
-               max_flash_size_in_kb = 64;
-               stm32x_info->user_data_offset = 16;
-               stm32x_info->option_offset = 6;
-               stm32x_info->default_rdp = 0xAA;
-               stm32x_info->can_load_options = true;
-               break;
-       case 0x444: /* stm32f03x */
-       case 0x445: /* stm32f04x */
-               page_size = 1024;
-               stm32x_info->ppage_size = 4;
-               max_flash_size_in_kb = 32;
-               stm32x_info->user_data_offset = 16;
-               stm32x_info->option_offset = 6;
-               stm32x_info->default_rdp = 0xAA;
-               stm32x_info->can_load_options = true;
-               break;
-       case 0x448: /* stm32f07x */
-               page_size = 2048;
-               stm32x_info->ppage_size = 4;
-               max_flash_size_in_kb = 128;
-               stm32x_info->user_data_offset = 16;
-               stm32x_info->option_offset = 6;
-               stm32x_info->default_rdp = 0xAA;
-               stm32x_info->can_load_options = true;
-               break;
-       case 0x442: /* stm32f09x */
-               page_size = 2048;
-               stm32x_info->ppage_size = 4;
-               max_flash_size_in_kb = 256;
-               stm32x_info->user_data_offset = 16;
-               stm32x_info->option_offset = 6;
-               stm32x_info->default_rdp = 0xAA;
-               stm32x_info->can_load_options = true;
-               break;
-       case 0x410: /* stm32f1x medium-density */
-               page_size = 1024;
-               stm32x_info->ppage_size = 4;
-               max_flash_size_in_kb = 128;
-               /* GigaDevice GD32F1x0 & GD32F3x0 series devices share DEV_ID
-                  with STM32F101/2/3 medium-density line,
-                  however they use a REV_ID different from any STM32 device.
-                  The main difference is another offset of user option bits
-                  (like WDG_SW, nRST_STOP, nRST_STDBY) in option byte register
-                  (FLASH_OBR/FMC_OBSTAT 0x4002201C).
-                  This caused problems e.g. during flash block programming
-                  because of unexpected active hardware watchog. */
-               switch (rev_id) {
-               case 0x1303: /* gd32f1x0 */
+       uint16_t device_id = stm32x_info->device_id & 0xfff;
+       uint16_t rev_id = stm32x_info->device_id >> 16;
+
+       if (vendor == VENDOR_ST)
+       {
+               /* set page size, protection granularity and max flash size 
depending on family */
+               switch (device_id) {
+               case 0x440: /* stm32f03x8 / stm32f05x */
+                       page_size = 1024;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 64;
                        stm32x_info->user_data_offset = 16;
                        stm32x_info->option_offset = 6;
-                       max_flash_size_in_kb = 64;
+                       stm32x_info->default_rdp = 0xAA;
+                       stm32x_info->can_load_options = true;
                        break;
-               case 0x1704: /* gd32f3x0 */
+               case 0x444: /* stm32f03x4 / stm32f03x6 */
+               case 0x445: /* stm32f04x / stm32f07x6 */
+                       page_size = 1024;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 32;
+                       stm32x_info->user_data_offset = 16;
+                       stm32x_info->option_offset = 6;
+                       stm32x_info->default_rdp = 0xAA;
+                       stm32x_info->can_load_options = true;
+                       break;
+               case 0x448: /* stm32f07x */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 128;
+                       stm32x_info->user_data_offset = 16;
+                       stm32x_info->option_offset = 6;
+                       stm32x_info->default_rdp = 0xAA;
+                       stm32x_info->can_load_options = true;
+                       break;
+               case 0x442: /* stm32f09x */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 256;
+                       stm32x_info->user_data_offset = 16;
+                       stm32x_info->option_offset = 6;
+                       stm32x_info->default_rdp = 0xAA;
+                       stm32x_info->can_load_options = true;
+                       break;
+               case 0x410: /* stm32f1x medium-density */
+                       page_size = 1024;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 128;
+                       /* GigaDevice GD32F1x0 & GD32F3x0 series devices share 
DEV_ID
+                          with STM32F101/2/3 medium-density line,
+                          however they use a REV_ID different from any STM32 
device.
+                          The main difference is another offset of user option 
bits
+                          (like WDG_SW, nRST_STOP, nRST_STDBY) in option byte 
register
+                          (FLASH_OBR/FMC_OBSTAT 0x4002201C).
+                          This caused problems e.g. during flash block 
programming
+                          because of unexpected active hardware watchog. */
+                       switch (rev_id) {
+                       case 0x1303: /* gd32f1x0 */
+                               stm32x_info->user_data_offset = 16;
+                               stm32x_info->option_offset = 6;
+                               max_flash_size_in_kb = 64;
+                               break;
+                       case 0x1704: /* gd32f3x0 */
+                               stm32x_info->user_data_offset = 16;
+                               stm32x_info->option_offset = 6;
+                               break;
+                       }
+                       break;
+               case 0x412: /* stm32f1x low-density */
+                       page_size = 1024;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 32;
+                       break;
+               case 0x414: /* stm32f1x high-density */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 2;
+                       max_flash_size_in_kb = 512;
+                       break;
+               case 0x418: /* stm32f1x connectivity */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 2;
+                       max_flash_size_in_kb = 256;
+                       break;
+               case 0x430: /* stm32f1 XL-density (dual flash banks) */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 2;
+                       max_flash_size_in_kb = 1024;
+                       stm32x_info->has_dual_banks = true;
+                       break;
+               case 0x420: /* stm32f100xx low- and medium-density value line */
+                       page_size = 1024;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 128;
+                       break;
+               case 0x428: /* stm32f100xx high-density value line */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 512;
+                       break;
+               case 0x422: /* stm32f302/3xb/c */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 2;
+                       max_flash_size_in_kb = 256;
                        stm32x_info->user_data_offset = 16;
                        stm32x_info->option_offset = 6;
+                       stm32x_info->default_rdp = 0xAA;
+                       stm32x_info->can_load_options = true;
                        break;
+               case 0x446: /* stm32f303xD/E */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 2;
+                       max_flash_size_in_kb = 512;
+                       stm32x_info->user_data_offset = 16;
+                       stm32x_info->option_offset = 6;
+                       stm32x_info->default_rdp = 0xAA;
+                       stm32x_info->can_load_options = true;
+                       break;
+               case 0x432: /* stm32f37x */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 2;
+                       max_flash_size_in_kb = 256;
+                       stm32x_info->user_data_offset = 16;
+                       stm32x_info->option_offset = 6;
+                       stm32x_info->default_rdp = 0xAA;
+                       stm32x_info->can_load_options = true;
+                       break;
+               case 0x438: /* stm32f33x */
+               case 0x439: /* stm32f302x6/8 */
+                       page_size = 2048;
+                       stm32x_info->ppage_size = 2;
+                       max_flash_size_in_kb = 64;
+                       stm32x_info->user_data_offset = 16;
+                       stm32x_info->option_offset = 6;
+                       stm32x_info->default_rdp = 0xAA;
+                       stm32x_info->can_load_options = true;
+                       break;
+               default:
+                       LOG_WARNING("Cannot identify target as a STM32 
family.");
+                       return ERROR_FAIL;
+               }
+       } else if (vendor == VENDOR_GD) {
+               /* set page size, protection granularity and max flash size 
depending on family */
+               switch (stm32x_info->device_id & 0xfff) {
+               case 0x410: /* GD32E230x8 */
+                       page_size = 1024;
+                       stm32x_info->ppage_size = 4;
+                       max_flash_size_in_kb = 128;
+                       break;
+               default:
+                       LOG_WARNING("Cannot identify GD32 variant.");
+                       return ERROR_FAIL;
                }
-               break;
-       case 0x412: /* stm32f1x low-density */
-               page_size = 1024;
-               stm32x_info->ppage_size = 4;
-               max_flash_size_in_kb = 32;
-               break;
-       case 0x414: /* stm32f1x high-density */
-               page_size = 2048;
-               stm32x_info->ppage_size = 2;
-               max_flash_size_in_kb = 512;
-               break;
-       case 0x418: /* stm32f1x connectivity */
-               page_size = 2048;
-               stm32x_info->ppage_size = 2;
-               max_flash_size_in_kb = 256;
-               break;
-       case 0x430: /* stm32f1 XL-density (dual flash banks) */
-               page_size = 2048;
-               stm32x_info->ppage_size = 2;
-               max_flash_size_in_kb = 1024;
-               stm32x_info->has_dual_banks = true;
-               break;
-       case 0x420: /* stm32f100xx low- and medium-density value line */
-               page_size = 1024;
-               stm32x_info->ppage_size = 4;
-               max_flash_size_in_kb = 128;
-               break;
-       case 0x428: /* stm32f100xx high-density value line */
-               page_size = 2048;
-               stm32x_info->ppage_size = 4;
-               max_flash_size_in_kb = 512;
-               break;
-       case 0x422: /* stm32f302/3xb/c */
-               page_size = 2048;
-               stm32x_info->ppage_size = 2;
-               max_flash_size_in_kb = 256;
-               stm32x_info->user_data_offset = 16;
-               stm32x_info->option_offset = 6;
-               stm32x_info->default_rdp = 0xAA;
-               stm32x_info->can_load_options = true;
-               break;
-       case 0x446: /* stm32f303xD/E */
-               page_size = 2048;
-               stm32x_info->ppage_size = 2;
-               max_flash_size_in_kb = 512;
-               stm32x_info->user_data_offset = 16;
-               stm32x_info->option_offset = 6;
-               stm32x_info->default_rdp = 0xAA;
-               stm32x_info->can_load_options = true;
-               break;
-       case 0x432: /* stm32f37x */
-               page_size = 2048;
-               stm32x_info->ppage_size = 2;
-               max_flash_size_in_kb = 256;
-               stm32x_info->user_data_offset = 16;
-               stm32x_info->option_offset = 6;
-               stm32x_info->default_rdp = 0xAA;
-               stm32x_info->can_load_options = true;
-               break;
-       case 0x438: /* stm32f33x */
-       case 0x439: /* stm32f302x6/8 */
-               page_size = 2048;
-               stm32x_info->ppage_size = 2;
-               max_flash_size_in_kb = 64;
-               stm32x_info->user_data_offset = 16;
-               stm32x_info->option_offset = 6;
-               stm32x_info->default_rdp = 0xAA;
-               stm32x_info->can_load_options = true;
-               break;
-       default:
-               LOG_WARNING("Cannot identify target as a STM32 family.");
-               return ERROR_FAIL;
        }
+       else
+               return ERROR_FAIL;
 
        /* get flash size from target. */
-       retval = stm32x_get_flash_size(bank, &flash_size_in_kb);
+       retval = target_read_u16(target, stm32x_info->flash_size_reg, 
&flash_size_in_kb);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* failed reading flash size or flash size invalid (early silicon),
         * default to max target family */
        if (retval != ERROR_OK || flash_size_in_kb == 0xffff || 
flash_size_in_kb == 0) {
                LOG_WARNING("STM32 flash size failed, probe inaccurate - 
assuming %dk flash",
-                       max_flash_size_in_kb);
+                                       max_flash_size_in_kb);
                flash_size_in_kb = max_flash_size_in_kb;
        }
 
@@ -923,6 +963,17 @@ static int stm32x_probe(struct flash_bank *bank)
        return ERROR_OK;
 }
 
+
+static int stm32x_probe(struct flash_bank *bank)
+{
+       return stm32f1xx_probe_common(bank, VENDOR_ST);
+}
+
+static int gd32_probe(struct flash_bank *bank)
+{
+       return stm32f1xx_probe_common(bank, VENDOR_GD);
+}
+
 static int stm32x_auto_probe(struct flash_bank *bank)
 {
        struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
@@ -931,6 +982,14 @@ static int stm32x_auto_probe(struct flash_bank *bank)
        return stm32x_probe(bank);
 }
 
+static int gd32_auto_probe(struct flash_bank *bank)
+{
+       struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
+       if (stm32x_info->probed)
+               return ERROR_OK;
+       return gd32_probe(bank);
+}
+
 #if 0
 COMMAND_HANDLER(stm32x_handle_part_id_command)
 {
@@ -955,15 +1014,10 @@ static const char *get_stm32f0_revision(uint16_t rev_id)
 
 static int get_stm32x_info(struct flash_bank *bank, struct command_invocation 
*cmd)
 {
-       uint32_t dbgmcu_idcode;
-
-       /* read stm32 device id register */
-       int retval = stm32x_get_device_id(bank, &dbgmcu_idcode);
-       if (retval != ERROR_OK)
-               return retval;
+       struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
 
-       uint16_t device_id = dbgmcu_idcode & 0xfff;
-       uint16_t rev_id = dbgmcu_idcode >> 16;
+       uint16_t device_id = stm32x_info->device_id & 0xfff;
+       uint16_t rev_id = stm32x_info->device_id >> 16;
        const char *device_str;
        const char *rev_str = NULL;
 
@@ -1185,6 +1239,32 @@ static int get_stm32x_info(struct flash_bank *bank, 
struct command_invocation *c
        return ERROR_OK;
 }
 
+static int get_gd32_info(struct flash_bank *bank, struct command_invocation 
*cmd)
+{
+       struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
+
+       uint16_t device_id = stm32x_info->device_id & 0xfff;
+       uint16_t rev_id = stm32x_info->device_id >> 16;
+       const char *device_str;
+       const char *rev_str = NULL;
+
+       switch (device_id) {
+       case 0x410:
+               device_str = "GD32Exxx";
+               break;
+       default:
+               command_print_sameline(cmd, "Cannot identify target as a 
GD32\n");
+               device_str = 0;
+               break;
+       }
+
+       if (rev_str)
+               command_print_sameline(cmd, "%s - Rev: %s", device_str, 
rev_str);
+       else
+               command_print_sameline(cmd, "%s - Rev: unknown (0x%04x)", 
device_str, rev_id);
+       return ERROR_OK;
+}
+
 COMMAND_HANDLER(stm32x_handle_lock_command)
 {
        struct target *target = NULL;
@@ -1604,3 +1684,19 @@ const struct flash_driver stm32f1x_flash = {
        .info = get_stm32x_info,
        .free_driver_priv = default_flash_free_driver_priv,
 };
+
+const struct flash_driver gd32_flash = {
+       .name = "gd32",
+       .commands = stm32x_command_handlers,
+       .flash_bank_command = stm32x_flash_bank_command,
+       .erase = stm32x_erase,
+       .protect = stm32x_protect,
+       .write = stm32x_write,
+       .read = default_flash_read,
+       .probe = gd32_probe,
+       .auto_probe = gd32_auto_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = stm32x_protect_check,
+       .info = get_gd32_info,
+       .free_driver_priv = default_flash_free_driver_priv,
+};
diff --git a/tcl/board/gd32e230-start.cfg b/tcl/board/gd32e230-start.cfg
new file mode 100644
index 000000000..1d3a00b6b
--- /dev/null
+++ b/tcl/board/gd32e230-start.cfg
@@ -0,0 +1,7 @@
+source [find interface/cmsis-dap.cfg]
+
+transport select swd
+
+source [find target/gd32e23x.cfg]
+
+reset_config srst_only
diff --git a/tcl/target/gd32e23x.cfg b/tcl/target/gd32e23x.cfg
new file mode 100644
index 000000000..9983c3491
--- /dev/null
+++ b/tcl/target/gd32e23x.cfg
@@ -0,0 +1,94 @@
+# script for GD32E23x family
+
+#
+# gd32 devices support SWD transports only.
+#
+source [find target/swj-dp.tcl]
+source [find mem_helper.tcl]
+
+if { [info exists CHIPNAME] } {
+   set _CHIPNAME $CHIPNAME
+} else {
+   set _CHIPNAME gd32e23x
+}
+
+set _ENDIAN little
+
+# Work-area is a space in RAM used for flash programming
+# By default use 4kB
+if { [info exists WORKAREASIZE] } {
+   set _WORKAREASIZE $WORKAREASIZE
+} else {
+   set _WORKAREASIZE 0x1000
+}
+
+# Allow overriding the Flash bank size
+if { [info exists FLASH_SIZE] } {
+       set _FLASH_SIZE $FLASH_SIZE
+} else {
+       # autodetect size
+       set _FLASH_SIZE 0
+}
+
+#jtag scan chain
+if { [info exists CPUTAPID] } {
+   set _CPUTAPID $CPUTAPID
+} else {
+   set _CPUTAPID 0x0bb11477
+}
+
+swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 
$_CPUTAPID
+dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
+
+$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 
$_WORKAREASIZE -work-area-backup 0
+
+# flash size will be probed
+set _FLASHNAME $_CHIPNAME.flash
+flash bank $_FLASHNAME gd32 0x08000000 $_FLASH_SIZE 0 0 $_TARGETNAME
+
+# adapter speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG 
= 1MHz
+adapter speed 1000
+
+adapter srst delay 100
+
+reset_config srst_nogate
+
+if {![using_hla]} {
+       # if srst is not fitted use SYSRESETREQ to
+       # perform a soft reset
+       cortex_m reset_config sysresetreq
+}
+
+proc gd32e23x_default_reset_start {} {
+       # Reset clock is IRC8M (8 MHz)
+       adapter speed 1000
+}
+
+proc gd32e23x_default_examine_end {} {
+       # Enable debug during low power modes (uses more power), stop watchdog 
counters during halt
+       mmw 0x40015804 0x00000037 0 ;# DBG_CTL0 |= WWDGT_HOLD | FWDGT_HOLD | 
STB_HOLD | DSLP_HOLD | SLP_HOLD
+
+       #mmw 0x40015808 0x00000000 0 ;# DBG_CTL1 |= ...
+}
+
+proc gd32e23x_default_reset_init {} {
+       # Configure PLL to boost clock to IRC8M x 9 (72 MHz)
+       # PLLMF = 00111 (x9) ->  RCU_CFG0 0000 0000 0001 1100 0000 0000 0000 
0000
+       mww 0x40021004 0x001c0000   ;# RCU_CFG0
+       mmw 0x40021000 0x01000000 0 ;# RCU_CTL0[24] = PLLON
+
+       mww 0x40022000 0x00000012   ;# FMC_WS: set PFEN, WSCNT = 2
+       sleep 10                    ;# Wait for PLL to lock
+       mmw 0x40021004 0x00000002 0 ;# RCU_CFG0[1:0] = SCS(2)
+
+       # Boost JTAG frequency
+       adapter speed 8000
+}
+
+# Default hooks
+$_TARGETNAME configure -event examine-end { gd32e23x_default_examine_end }
+$_TARGETNAME configure -event reset-start { gd32e23x_default_reset_start }
+$_TARGETNAME configure -event reset-init { gd32e23x_default_reset_init }

-- 

Reply via email to