This is an automated email from Gerrit.

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

-- gerrit

commit 3533940f4dd488bc94b582f38dd5434e86f8be81
Author: Tomas Vanek <[email protected]>
Date:   Thu Nov 23 11:17:53 2017 +0100

    target armv7m: multi-block erase check
    
    Tested on PSoC6 (Cortex-M0+ core), onboard KitProg2 in CMSIS-DAP mode,
    adapter_khz=1000.
    Plain read:
        flash read_bank 0 /dev/null
    takes 48 seconds.
    
    erase_check without this change:
        flash erase_check 0
    takes horrible 149 seconds!!
    
    And the same command with the change applied takes 1.8 seconds.
    Quite a difference.
    
    Remove the erase-value=0 version of algorithm as the new one can check
    for any value.
    
    Change-Id: Ic0899011256d2114112e67c0b51fab4f6230d9cd
    Signed-off-by: Tomas Vanek <[email protected]>

diff --git a/contrib/loaders/erase_check/Makefile 
b/contrib/loaders/erase_check/Makefile
index 01e62de..157f8c0 100644
--- a/contrib/loaders/erase_check/Makefile
+++ b/contrib/loaders/erase_check/Makefile
@@ -6,7 +6,7 @@ ARM_OBJCOPY ?= $(ARM_CROSS_COMPILE)objcopy
 
 ARM_AFLAGS = -EL
 
-arm: armv4_5_erase_check.inc armv7m_erase_check.inc armv7m_0_erase_check.inc
+arm: armv4_5_erase_check.inc armv7m_erase_check.inc
 
 armv4_5_%.elf: armv4_5_%.s
        $(ARM_AS) $(ARM_AFLAGS) $< -o $@
diff --git a/contrib/loaders/erase_check/armv7m_0_erase_check.inc 
b/contrib/loaders/erase_check/armv7m_0_erase_check.inc
deleted file mode 100644
index 76115ec..0000000
--- a/contrib/loaders/erase_check/armv7m_0_erase_check.inc
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Autogenerated with ../../../src/helper/bin2char.sh */
-0x03,0x78,0x01,0x30,0x1a,0x43,0x01,0x39,0xfa,0xd1,0x00,0xbe,
diff --git a/contrib/loaders/erase_check/armv7m_0_erase_check.s 
b/contrib/loaders/erase_check/armv7m_0_erase_check.s
deleted file mode 100644
index 6b1e92a..0000000
--- a/contrib/loaders/erase_check/armv7m_0_erase_check.s
+++ /dev/null
@@ -1,45 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2014 by Jeff Ciesielski                                 *
- *   [email protected]                                              *
- *                                                                         *
- *   Based on the armv7m erase checker by:                                 *
- *   Copyright (C) 2010 by Spencer Oliver                                  *
- *   [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     *
- *   (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.                          *
- *                                                                         *
- ***************************************************************************/
-
-/*
-       parameters:
-       r0 - address in
-       r1 - byte count
-       r2 - mask - result out
-*/
-
-       .text
-       .syntax unified
-       .cpu cortex-m0
-       .thumb
-       .thumb_func
-
-       .align  2
-
-loop:
-       ldrb    r3, [r0]
-       adds    r0, #1
-       orrs    r2, r2, r3
-       subs    r1, r1, #1
-       bne             loop
-end:
-       bkpt    #0
-
-       .end
diff --git a/contrib/loaders/erase_check/armv7m_erase_check.inc 
b/contrib/loaders/erase_check/armv7m_erase_check.inc
index 1fe25cd..4ee96e1 100644
--- a/contrib/loaders/erase_check/armv7m_erase_check.inc
+++ b/contrib/loaders/erase_check/armv7m_erase_check.inc
@@ -1,2 +1,4 @@
 /* Autogenerated with ../../../src/helper/bin2char.sh */
-0x03,0x78,0x01,0x30,0x1a,0x40,0x01,0x39,0xfa,0xd1,0x00,0xbe,
+0x02,0x68,0x12,0x42,0x0d,0xd0,0x43,0x68,0x1c,0x68,0x04,0x33,0x8c,0x42,0x05,0xd1,
+0x01,0x3a,0xf9,0xd1,0x01,0x24,0x04,0x60,0x08,0x30,0xf1,0xe7,0x00,0x24,0xfa,0xe7,
+0x00,0x00,0x00,0xbe,
diff --git a/contrib/loaders/erase_check/armv7m_erase_check.s 
b/contrib/loaders/erase_check/armv7m_erase_check.s
index 886e3e2..3303c87 100644
--- a/contrib/loaders/erase_check/armv7m_erase_check.s
+++ b/contrib/loaders/erase_check/armv7m_erase_check.s
@@ -20,9 +20,8 @@
 
 /*
        parameters:
-       r0 - address in
-       r1 - byte count
-       r2 - mask - result out
+       r0 - pointer to struct { uint32_t size_in_result_out, uint32_t addr }
+       r1 - value to check
 */
 
        .text
@@ -33,13 +32,42 @@
 
        .align  2
 
-loop:
-       ldrb    r3, [r0]
-       adds    r0, #1
-       ands    r2, r2, r3
-       subs    r1, r1, #1
-       bne             loop
-end:
+BLOCK_SIZE_RESULT      = 0
+BLOCK_ADDRESS          = 4
+SIZEOF_STRUCT_BLOCK    = 8
+
+start:
+block_loop:
+       ldr     r2, [r0, #BLOCK_SIZE_RESULT]    /* get size */
+       tst     r2, r2
+       beq     done
+
+       ldr     r3, [r0, #BLOCK_ADDRESS]        /* get address */
+
+word_loop:
+       ldr     r4, [r3]        /* read word */
+       adds    r3, #4
+
+       cmp     r4, r1
+       bne     not_erased
+
+       subs    r2, #1
+       bne     word_loop
+
+       movs    r4, #1          /* block is erased */
+save_result:
+       str     r4, [r0, #BLOCK_SIZE_RESULT]
+       adds    r0, #SIZEOF_STRUCT_BLOCK
+       b       block_loop
+
+not_erased:
+       movs    r4, #0
+       b       save_result
+
+/* Avoid padding at .text segment end. Otherwise exit point check fails. */
+        .skip   ( . - start + 2) & 2, 0
+
+done:
        bkpt    #0
 
        .end
diff --git a/src/target/armv7m.c b/src/target/armv7m.c
index 61ed09d..5a7ca74 100644
--- a/src/target/armv7m.c
+++ b/src/target/armv7m.c
@@ -731,34 +731,21 @@ cleanup:
        return retval;
 }
 
-/** Checks whether a memory region is erased. */
+/** Checks an array of memory regions if they are erased. */
 int armv7m_blank_check_memory(struct target *target,
        struct target_memory_check_block *blocks, int num_blocks, uint8_t 
erased_value)
 {
        struct working_area *erase_check_algorithm;
-       struct reg_param reg_params[3];
+       struct working_area *erase_check_params;
+       struct reg_param reg_params[2];
        struct armv7m_algorithm armv7m_info;
-       const uint8_t *code;
-       uint32_t code_size;
        int retval;
 
        static const uint8_t erase_check_code[] = {
 #include "../../contrib/loaders/erase_check/armv7m_erase_check.inc"
        };
-       static const uint8_t zero_erase_check_code[] = {
-#include "../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
-       };
 
-       switch (erased_value) {
-       case 0x00:
-               code = zero_erase_check_code;
-               code_size = sizeof(zero_erase_check_code);
-               break;
-       case 0xff:
-       default:
-               code = erase_check_code;
-               code_size = sizeof(erase_check_code);
-       }
+       const uint32_t code_size = sizeof(erase_check_code);
 
        /* make sure we have a working area */
        if (target_alloc_working_area(target, code_size,
@@ -766,46 +753,100 @@ int armv7m_blank_check_memory(struct target *target,
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
        retval = target_write_buffer(target, erase_check_algorithm->address,
-                       code_size, code);
+                       code_size, erase_check_code);
        if (retval != ERROR_OK)
-               goto cleanup;
+               goto cleanup1;
+
+       /* prepare blocks array for algo */
+       struct algo_block {
+               union {
+                       uint32_t size;
+                       uint32_t result;
+               };
+               uint32_t address;
+       };
+
+       uint32_t avail = target_get_working_area_avail(target);
+       int max_blocks = avail / sizeof(struct algo_block) - 1;
+       if (num_blocks > max_blocks)
+               num_blocks = max_blocks;
+
+       struct algo_block *params = malloc((num_blocks+1)*sizeof(struct 
algo_block));
+       if (params == NULL) {
+               retval = ERROR_FAIL;
+               goto cleanup1;
+       }
+
+       int i;
+       for (i = 0; i < num_blocks; i++) {
+               target_buffer_set_u32(target, (uint8_t *)&(params[i].size),
+                                               blocks[i].size / 
sizeof(uint32_t));
+               target_buffer_set_u32(target, (uint8_t *)&(params[i].address),
+                                               blocks[i].address);
+       }
+       target_buffer_set_u32(target, (uint8_t *)&(params[num_blocks].size), 0);
+
+       uint32_t param_size = (num_blocks + 1) * sizeof(struct algo_block);
+       if (target_alloc_working_area(target, param_size,
+                       &erase_check_params) != ERROR_OK) {
+               retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               goto cleanup2;
+       }
+
+       retval = target_write_buffer(target, erase_check_params->address,
+                               param_size, (uint8_t *)params);
+       if (retval != ERROR_OK)
+               goto cleanup3;
+
+       uint32_t erased_word = erased_value | (erased_value << 8)
+                              | (erased_value << 16) | (erased_value << 24);
+
+       LOG_DEBUG("Starting erase check of %d blocks, parameters@0x%"
+                TARGET_PRIxADDR, num_blocks, erase_check_params->address);
 
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
        armv7m_info.core_mode = ARM_MODE_THREAD;
 
        init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
-       buf_set_u32(reg_params[0].value, 0, 32, blocks->address);
+       buf_set_u32(reg_params[0].value, 0, 32, erase_check_params->address);
 
        init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
-       buf_set_u32(reg_params[1].value, 0, 32, blocks->size);
-
-       init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
-       buf_set_u32(reg_params[2].value, 0, 32, erased_value);
+       buf_set_u32(reg_params[1].value, 0, 32, erased_word);
 
        retval = target_run_algorithm(target,
-                       0,
-                       NULL,
-                       3,
-                       reg_params,
-                       erase_check_algorithm->address,
-                       erase_check_algorithm->address + (code_size - 2),
-                       10000,
-                       &armv7m_info);
+                               0, NULL,
+                               ARRAY_SIZE(reg_params), reg_params,
+                               erase_check_algorithm->address,
+                               erase_check_algorithm->address + (code_size - 
2),
+                               10000,
+                               &armv7m_info);
 
-       if (retval == ERROR_OK)
-               blocks->result = buf_get_u32(reg_params[2].value, 0, 32);
+       if (retval != ERROR_OK)
+               goto cleanup4;
+
+       retval = target_read_buffer(target, erase_check_params->address,
+                               param_size, (uint8_t *)params);
+       if (retval != ERROR_OK)
+               goto cleanup4;
 
+       for (i = 0; i < num_blocks; i++)
+               blocks[i].result = target_buffer_get_u32(target,
+                                       (uint8_t *)&(params[i].result));
+
+       retval = num_blocks; /* return number of blocks really checked */
+
+cleanup4:
        destroy_reg_param(&reg_params[0]);
        destroy_reg_param(&reg_params[1]);
-       destroy_reg_param(&reg_params[2]);
 
-cleanup:
+cleanup3:
+       target_free_working_area(target, erase_check_params);
+cleanup2:
+       free(params);
+cleanup1:
        target_free_working_area(target, erase_check_algorithm);
 
-       if (retval != ERROR_OK)
-               return retval;
-
-       return 1;       /* only one block checked */
+       return retval;
 }
 
 int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)

-- 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to