This is an automated email from Gerrit.

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

-- gerrit

commit 6eac39503d0b012bfa8cbcc18aff0f3bef0d9a5a
Author: Tomas Vanek <[email protected]>
Date:   Tue Nov 16 12:23:48 2021 +0100

    flash/stm32f1x: add support for RISC-V GigaDevice GD32VF103 [WIP]
    
    The device has compatible flash macro with STM32F1 family, reuse
    stm32f1x driver code.
    
    Detect non-ARM target - for simplicy test target type name 'riscv'
    TODO: add a magic number to riscv_info structure to make detection
    possible.
    
    In case of RISC-V CPU use block write algo - async algo cannot be used
    as RISC-V doesn't allow memory access when target is running.
    TODO: optimize xx_write_block() routines, branch 
ERROR_FLASH_OPERATION_FAILED
    is common to both Cortex-M and RISC-V and should be run also after
    host controlled write fallback.
    
    stm32x_write_options() does not work on RICS-V because directly calls
    stm32x_write_block() - it is inefficient for 8 words, no fallback is 
possible.
    TODO: refactor host controlled write code to a new procedure, call it
    from stm32x_write_options()
    
    TODO: This change does not contain contrib/loaders/flash/gd32vf103/*
    For testing use with #5839: flash/nor: Add GigaDevice GD32VF103 driver
    
    TODO: doc
    
    tcl/target/gd32vf103.cfg: redirect to stm32f1 driver, bigger work area size.
    
    Change-Id: Ie3886fbd8573652691f91a02335812a7300689f7
    Signed-off-by: Tomas Vanek <[email protected]>

diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c
index 6744779e9..7011402ef 100644
--- a/src/flash/nor/stm32f1x.c
+++ b/src/flash/nor/stm32f1x.c
@@ -26,6 +26,8 @@
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "imp.h"
 #include <helper/binarybuffer.h>
 #include <target/algorithm.h>
@@ -537,6 +539,159 @@ static int stm32x_write_block(struct flash_bank *bank, 
const uint8_t *buffer,
        return retval;
 }
 
+static int gd32vf103_write_block(struct flash_bank *bank, const uint8_t 
*buffer,
+               uint32_t offset, uint32_t count)
+{
+       struct target *target = bank->target;
+       struct working_area *write_algorithm;
+       static const uint8_t gd32vf103_flash_write_code[] = {
+#include "../../../contrib/loaders/flash/gd32vf103/gd32vf103.inc"
+       };
+
+       /* flash write code */
+       if (target_alloc_working_area(target, 
sizeof(gd32vf103_flash_write_code),
+                       &write_algorithm) != ERROR_OK) {
+               LOG_WARNING("no working area available, can't do block memory 
writes");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       int retval = target_write_buffer(target, write_algorithm->address,
+                       sizeof(gd32vf103_flash_write_code), 
gd32vf103_flash_write_code);
+       if (retval != ERROR_OK) {
+               target_free_working_area(target, write_algorithm);
+               return retval;
+       }
+
+       uint32_t buffer_size = 16384;
+       struct working_area *source;
+
+       /* memory buffer */
+       while (target_alloc_working_area_try(target, buffer_size, &source) != 
ERROR_OK) {
+               buffer_size /= 2;
+               buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
+               if (buffer_size <= 256) {
+                       /* we already allocated the writing code, but failed to 
get a
+                        * buffer, free the algorithm */
+                       target_free_working_area(target, write_algorithm);
+
+                       LOG_WARNING("no large enough working area available, 
can't do block memory writes");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+       }
+
+       struct reg_param reg_params[5];
+
+       init_reg_param(&reg_params[0], "a0", 32, PARAM_IN_OUT); /* flash base 
(in), status (out) */
+       init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT);    /* count 
(halfword-16bit) */
+       init_reg_param(&reg_params[2], "a2", 32, PARAM_OUT);    /* buffer start 
*/
+       init_reg_param(&reg_params[3], "a3", 32, PARAM_OUT);    /* buffer end */
+       init_reg_param(&reg_params[4], "a4", 32, PARAM_IN_OUT); /* target 
address */
+
+       uint32_t wp_addr = source->address;
+       uint32_t rp_addr = source->address + 4;
+       uint32_t fifo_start_addr = source->address + 8;
+       uint32_t fifo_end_addr = source->address + source->size;
+
+       uint32_t wp = fifo_start_addr;
+       uint32_t rp = fifo_start_addr;
+
+       retval = target_write_u32(target, rp_addr, rp);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* (2:block size) */
+       uint32_t thisrun_bytes = fifo_end_addr-fifo_start_addr - 2;
+       uint32_t address = bank->base + offset;
+
+       while (count > 0) {
+               const struct stm32x_flash_bank *gd32vf103_info = 
bank->driver_priv;
+
+               retval = target_read_u32(target, rp_addr, &rp);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("failed to get read pointer");
+                       break;
+               }
+
+               if (wp != rp) {
+                       LOG_ERROR("Failed to write flash ;;  rp = 0x%x ;;; wp = 
0x%x", rp, wp);
+                       break;
+               }
+               wp = fifo_start_addr;
+               rp = fifo_start_addr;
+               retval = target_write_u32(target, rp_addr, rp);
+               if (retval != ERROR_OK)
+                       break;
+               /* Limit to the amount of data we actually want to write */
+               if (thisrun_bytes > count * 2)
+                       thisrun_bytes = count * 2;
+
+               /* Write data to fifo */
+               retval = target_write_buffer(target, wp, thisrun_bytes, buffer);
+               if (retval != ERROR_OK)
+                       break;
+
+               /* Update counters and wrap write pointer */
+               buffer += thisrun_bytes;
+               count -= thisrun_bytes / 2;
+               rp = fifo_start_addr;
+               wp = fifo_start_addr+thisrun_bytes;
+
+               /* Store updated write pointer to target */
+               retval = target_write_u32(target, wp_addr, wp);
+               if (retval != ERROR_OK)
+                       break;
+               retval = target_write_u32(target, rp_addr, rp);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               buf_set_u32(reg_params[0].value, 0, 32, 
gd32vf103_info->register_base);
+               buf_set_u32(reg_params[1].value, 0, 32, thisrun_bytes/2);
+               buf_set_u32(reg_params[2].value, 0, 32, source->address);
+               buf_set_u32(reg_params[3].value, 0, 32, source->address + 
source->size);
+               buf_set_u32(reg_params[4].value, 0, 32, address);
+
+               retval = target_run_algorithm(target, 0, NULL, 5, reg_params,
+                               write_algorithm->address, 
write_algorithm->address+4,
+                               10000, NULL);
+
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Failed to execute algorithm at 0x%" 
TARGET_PRIxADDR ": %d",
+                                       write_algorithm->address, retval);
+                       return retval;
+               }
+
+               address += thisrun_bytes;
+       }
+
+       if (retval == ERROR_FLASH_OPERATION_FAILED) {
+               LOG_ERROR("flash write failed at address 0x%"PRIx32,
+                               buf_get_u32(reg_params[4].value, 0, 32));
+
+               if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_PGERR) {
+                       LOG_ERROR("flash memory not erased before writing");
+                       /* Clear but report errors */
+                       target_write_u32(target, stm32x_get_flash_reg(bank, 
STM32_FLASH_SR), FLASH_PGERR);
+               }
+
+               if (buf_get_u32(reg_params[0].value, 0, 32) & FLASH_WRPRTERR) {
+                       LOG_ERROR("flash memory write protected");
+                       /* Clear but report errors */
+                       target_write_u32(target, stm32x_get_flash_reg(bank, 
STM32_FLASH_SR), FLASH_WRPRTERR);
+               }
+       }
+
+       target_free_working_area(target, source);
+       target_free_working_area(target, write_algorithm);
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+       destroy_reg_param(&reg_params[3]);
+       destroy_reg_param(&reg_params[4]);
+
+       return retval;
+}
+
 static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
                uint32_t offset, uint32_t count)
 {
@@ -583,8 +738,14 @@ static int stm32x_write(struct flash_bank *bank, const 
uint8_t *buffer,
        if (retval != ERROR_OK)
                goto cleanup;
 
-       /* try using a block write */
-       retval = stm32x_write_block(bank, buffer, bank->base + offset, 
words_remaining);
+       struct arm *arm = target_to_arm(target);
+       if (is_arm(arm)) {
+               /* try using a block write - on ARM architecture or... */
+               retval = stm32x_write_block(bank, buffer, bank->base + offset, 
words_remaining);
+       } else {
+               /* ... RiscV architecture */
+               retval = gd32vf103_write_block(bank, buffer, offset, 
words_remaining);
+       }
 
        if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
                /* if block write failed (no sufficient working area),
@@ -619,10 +780,32 @@ cleanup:
        return retval;
 }
 
+/* Extension to enum cortex_m_partno */
+enum {
+       TARGET_TYPE_UNKNOWN,
+       TARGET_TYPE_RISCV,
+};
+
+static unsigned int stm32x_get_cm_partno(struct target *target)
+{
+       struct arm *arm = target_to_arm(target);
+       if (is_arm(arm)) {
+               struct cortex_m_common *cortex_m = target_to_cm(target);
+               if (cortex_m->common_magic == CORTEX_M_COMMON_MAGIC)
+                       return cortex_m->core_info->partno;
+
+       } else if (strcmp(target_type_name(target), "riscv") == 0) {
+               /* There is nothing like arm common_magic in riscv_info_t
+                * check text name of target
+                */
+               return TARGET_TYPE_RISCV;
+       }
+       return TARGET_TYPE_UNKNOWN;
+}
+
 static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
 {
        struct target *target = bank->target;
-       struct cortex_m_common *cortex_m = target_to_cm(target);
        uint32_t device_id_register = 0;
 
        if (!target_was_examined(target)) {
@@ -630,11 +813,12 @@ static int stm32x_get_device_id(struct flash_bank *bank, 
uint32_t *device_id)
                return ERROR_FAIL;
        }
 
-       switch (cortex_m->core_info->partno) {
+       switch (stm32x_get_cm_partno(target)) {
        case CORTEX_M0_PARTNO: /* STM32F0x devices */
                device_id_register = 0x40015800;
                break;
        case CORTEX_M3_PARTNO: /* STM32F1x devices */
+       case TARGET_TYPE_RISCV: /* GD32VF103 with RiscV CPU */
                device_id_register = 0xE0042000;
                break;
        case CORTEX_M4_PARTNO: /* STM32F3x devices */
@@ -659,7 +843,6 @@ static int stm32x_get_device_id(struct flash_bank *bank, 
uint32_t *device_id)
 static int stm32x_get_flash_size(struct flash_bank *bank, uint16_t 
*flash_size_in_kb)
 {
        struct target *target = bank->target;
-       struct cortex_m_common *cortex_m = target_to_cm(target);
        uint32_t flash_size_reg;
 
        if (!target_was_examined(target)) {
@@ -667,11 +850,12 @@ static int stm32x_get_flash_size(struct flash_bank *bank, 
uint16_t *flash_size_i
                return ERROR_FAIL;
        }
 
-       switch (cortex_m->core_info->partno) {
+       switch (stm32x_get_cm_partno(target)) {
        case CORTEX_M0_PARTNO: /* STM32F0x devices */
                flash_size_reg = 0x1FFFF7CC;
                break;
        case CORTEX_M3_PARTNO: /* STM32F1x devices */
+       case TARGET_TYPE_RISCV: /* GD32VF103 with RiscV CPU */
                flash_size_reg = 0x1FFFF7E0;
                break;
        case CORTEX_M4_PARTNO: /* STM32F3x devices */
@@ -777,6 +961,7 @@ static int stm32x_probe(struct flash_bank *bank)
                        max_flash_size_in_kb = 64;
                        break;
                case 0x1704: /* gd32f3x0 */
+               case 0x1906: /* gd32vf103 */
                        stm32x_info->user_data_offset = 16;
                        stm32x_info->option_offset = 6;
                        break;
@@ -995,6 +1180,10 @@ static int get_stm32x_info(struct flash_bank *bank, 
struct command_invocation *c
                        device_str = "GD32F3x0";
                        break;
 
+               case 0x1906:
+                       device_str = "GD32VF103";
+                       break;
+
                case 0x1909: /* gd32e23x */
                        device_str = "GD32E23x";
                        break;
diff --git a/tcl/target/gd32vf103.cfg b/tcl/target/gd32vf103.cfg
index 0a43f0079..949f15929 100644
--- a/tcl/target/gd32vf103.cfg
+++ b/tcl/target/gd32vf103.cfg
@@ -12,10 +12,11 @@ if { [info exists CHIPNAME] } {
    set _CHIPNAME gd32vf103
 }
 
+# The smallest RAM size 6kB (GD32VF103C4/T4/R4)
 if { [info exists WORKAREASIZE] } {
    set _WORKAREASIZE $WORKAREASIZE
 } else {
-   set _WORKAREASIZE 0x800
+   set _WORKAREASIZE 0x1800
 }
 
 jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1000563d
@@ -26,4 +27,4 @@ target create $_TARGETNAME riscv -chain-position $_TARGETNAME
 $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 
$_WORKAREASIZE -work-area-backup 0
 
 set _FLASHNAME $_CHIPNAME.flash
-flash bank $_FLASHNAME gd32vf103 0x08000000 0 0 0 $_TARGETNAME
+flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME

-- 

Reply via email to