This is an automated email from Gerrit.

nh minus ([email protected]) just uploaded a new patch set to Gerrit, which you 
can find at http://openocd.zylin.com/5597

-- gerrit

commit 1e494caaac21543ed45f850e86853b0157e749a3
Author: Jimmy <[email protected]>
Date:   Thu Apr 23 21:03:37 2020 +0800

    flash/nor/stm32lx: speed up erases
    
    The flash program time is dominated by a slow erase,
    so we move the tight erase loop onto the target for
    a 40% reduction in programming time.
    
    Change-Id: I3a07937c9001451c3bb59bf41991ee89ea6170d3
    Signed-off-by: Jimmy <[email protected]>

diff --git a/contrib/loaders/flash/stm32/Makefile 
b/contrib/loaders/flash/stm32/Makefile
index b58b412..f9e07a8 100644
--- a/contrib/loaders/flash/stm32/Makefile
+++ b/contrib/loaders/flash/stm32/Makefile
@@ -8,7 +8,7 @@ OBJDUMP=$(CROSS_COMPILE)objdump
 
 CFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL
 
-all: stm32f1x.inc stm32f2x.inc stm32h7x.inc stm32l4x.inc stm32lx.inc
+all: stm32f1x.inc stm32f2x.inc stm32h7x.inc stm32l4x.inc stm32lx.inc 
stm32lx_erase.inc
 
 .PHONY: clean
 
diff --git a/contrib/loaders/flash/stm32/stm32lx_erase.S 
b/contrib/loaders/flash/stm32/stm32lx_erase.S
new file mode 100644
index 0000000..eb4d27b
--- /dev/null
+++ b/contrib/loaders/flash/stm32/stm32lx_erase.S
@@ -0,0 +1,69 @@
+/***************************************************************************
+ *   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     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+       .text
+       .syntax unified
+       .cpu cortex-m0
+       .thumb
+
+/*
+Parameters
+       r0 - destination base address
+       r1 - pages
+       r2 - bytes per page
+       r3 - flash base
+Variables
+       r0 - destination erase pointer
+       r1 - destination limit pointer
+       r2 - bytes per page
+       r3 - flash base
+       r4 - temporary r/w
+       r5 - erase command
+       r6 - 0
+*/
+
+/* offsets of registers from flash reg base */
+#define STM32_FLASH_PECR               0x04
+#define STM32_FLASH_SR_OFFSET  0x18
+
+       .thumb_func
+       .global _start
+_start:
+       movs    r5, #0x41                                                       
/* set bits 3 and 9 (program and erase) */
+       lsls    r5, 3
+       movs    r6, #0                                                          
/* zero for the erase command */
+       muls    r1, r1, r2                                                      
/* calculate limit = base + pages * pagesize */
+       add             r1, r1, r0
+       b               test_done                                               
        /* check loop condition */
+arm_erase:
+       str             r5, [r3, #STM32_FLASH_PECR]
+wait_busy1:
+       ldr             r4, [r3, #STM32_FLASH_SR_OFFSET]
+       lsls    r4, r4, #31
+       bne             wait_busy1
+       str             r6, [r0]                                                
        /* start the erase */
+       add             r0, r0, r2                                              
        /* calc next erase address */
+wait_busy2:
+       ldr             r4, [r3, #STM32_FLASH_SR_OFFSET]
+       lsls    r4, r4, #31
+       bne             wait_busy2
+test_done:
+       cmp             r0, r1
+       bne             arm_erase
+
+exit:
+       bkpt    #0x00
diff --git a/contrib/loaders/flash/stm32/stm32lx_erase.inc 
b/contrib/loaders/flash/stm32/stm32lx_erase.inc
new file mode 100644
index 0000000..011a4de
--- /dev/null
+++ b/contrib/loaders/flash/stm32/stm32lx_erase.inc
@@ -0,0 +1,4 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0x41,0x25,0xed,0x00,0x00,0x26,0x51,0x43,0x01,0x44,0x08,0xe0,0x5d,0x60,0x9c,0x69,
+0xe4,0x07,0xfc,0xd1,0x06,0x60,0x10,0x44,0x9c,0x69,0xe4,0x07,0xfc,0xd1,0x88,0x42,
+0xf4,0xd1,0x00,0xbe,
diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c
index c3f9c72..fb594cd 100644
--- a/src/flash/nor/stm32lx.c
+++ b/src/flash/nor/stm32lx.c
@@ -99,7 +99,6 @@
 static int stm32lx_unlock_program_memory(struct flash_bank *bank);
 static int stm32lx_lock_program_memory(struct flash_bank *bank);
 static int stm32lx_enable_write_half_page(struct flash_bank *bank);
-static int stm32lx_erase_sector(struct flash_bank *bank, int sector);
 static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank);
 static int stm32lx_lock(struct flash_bank *bank);
 static int stm32lx_unlock(struct flash_bank *bank);
@@ -399,26 +398,88 @@ static int stm32lx_protect_check(struct flash_bank *bank)
 static int stm32lx_erase(struct flash_bank *bank, int first, int last)
 {
        int retval;
+       struct target *target = bank->target;
+       struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
+       struct working_area *erase_algorithm;
+       struct reg_param reg_params[4];
+       struct armv7m_algorithm armv7m_info;
+       static const uint8_t stm32lx_flash_erase_code[] = {
+#include "../../../contrib/loaders/flash/stm32/stm32lx_erase.inc"
+       };
 
        /*
         * It could be possible to do a mass erase if all sectors must be
         * erased, but it is not implemented yet.
         */
 
-       if (bank->target->state != TARGET_HALTED) {
+       if (target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       /*
-        * Loop over the selected sectors and erase them
-        */
-       for (int i = first; i <= last; i++) {
-               retval = stm32lx_erase_sector(bank, i);
-               if (retval != ERROR_OK)
-                       return retval;
-               bank->sectors[i].is_erased = 1;
+       /* Allocate the erase code */
+       if (target_alloc_working_area(target, sizeof(stm32lx_flash_erase_code),
+                       &erase_algorithm) != ERROR_OK) {
+               LOG_DEBUG("no working area for block memory writes");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       /* Write the erase code */
+       retval = target_write_buffer(target,
+                       erase_algorithm->address,
+                       sizeof(stm32lx_flash_erase_code),
+                       stm32lx_flash_erase_code);
+       if (retval != ERROR_OK) {
+               target_free_working_area(target, erase_algorithm);
+               return retval;
+       }
+
+       armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+       armv7m_info.core_mode = ARM_MODE_THREAD;
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
+
+       retval = stm32lx_unlock_program_memory(bank);
+       if (retval != ERROR_OK) {
+               target_free_working_area(target, erase_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]);
+               return retval;
        }
+
+       /* Pass parameters */
+       uint32_t totalBytes = bank->sectors[last].offset + 
bank->sectors[last].size - bank->sectors[first].offset;
+       uint32_t totalPages = totalBytes / stm32lx_info->part_info.page_size;
+       buf_set_u32(reg_params[0].value, 0, 32, bank->base + 
bank->sectors[first].offset);
+       buf_set_u32(reg_params[1].value, 0, 32, totalPages);
+       buf_set_u32(reg_params[2].value, 0, 32, 
stm32lx_info->part_info.page_size);
+       buf_set_u32(reg_params[3].value, 0, 32, stm32lx_info->flash_base);
+
+       /* Execute the erase code */
+       retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params)
+                       / sizeof(*reg_params), reg_params,
+                       erase_algorithm->address, 0, 5000 + totalPages * 8, 
&armv7m_info);
+
+       target_free_working_area(target, erase_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]);
+       
+       if (retval != ERROR_OK)
+               return retval;
+       
+       retval = stm32lx_lock_program_memory(bank);
+       if (retval != ERROR_OK)
+               return retval;
+       
+       for (int i = first; i <= last; i++)
+               bank->sectors[i].is_erased = 1;
+
        return ERROR_OK;
 }
 
@@ -1094,53 +1155,6 @@ static int stm32lx_lock_program_memory(struct flash_bank 
*bank)
        return ERROR_OK;
 }
 
-static int stm32lx_erase_sector(struct flash_bank *bank, int sector)
-{
-       struct target *target = bank->target;
-       struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
-       int retval;
-       uint32_t reg32;
-
-       /*
-        * To erase a sector (i.e. stm32lx_info->part_info.pages_per_sector 
pages),
-        * first unlock the memory, loop over the pages of this sector
-        * and write 0x0 to its first word.
-        */
-
-       retval = stm32lx_unlock_program_memory(bank);
-       if (retval != ERROR_OK)
-               return retval;
-
-       for (int page = 0; page < (int)stm32lx_info->part_info.pages_per_sector;
-                       page++) {
-               reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE;
-               retval = target_write_u32(target,
-                               stm32lx_info->flash_base + FLASH_PECR, reg32);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               retval = stm32lx_wait_until_bsy_clear(bank);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               uint32_t addr = bank->base + bank->sectors[sector].offset + 
(page
-                               * stm32lx_info->part_info.page_size);
-               retval = target_write_u32(target, addr, 0x0);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               retval = stm32lx_wait_until_bsy_clear(bank);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
-       retval = stm32lx_lock_program_memory(bank);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return ERROR_OK;
-}
-
 static inline int stm32lx_get_flash_status(struct flash_bank *bank, uint32_t 
*status)
 {
        struct target *target = bank->target;

-- 


_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to