This is an automated email from Gerrit.

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

-- gerrit

commit 5d7c534668292800f9bc2a209b9c0002a2f6e1cf
Author: Rick Foos <[email protected]>
Date:   Tue Dec 26 09:58:44 2017 -0600

    flash/nor: Add new ECM35xx driver support.
    
    Change-Id: I4e529ed064f36ef9301e7476f71ad5d56102e44b
    Signed-off-by: Rick Foos <[email protected]>

diff --git a/contrib/loaders/flash/etacorem3/Makefile 
b/contrib/loaders/flash/etacorem3/Makefile
new file mode 100644
index 0000000..8b6154f
--- /dev/null
+++ b/contrib/loaders/flash/etacorem3/Makefile
@@ -0,0 +1,36 @@
+BIN2C = ../../../../src/helper/bin2char.sh
+
+CROSS_COMPILE ?= arm-none-eabi-
+
+CC=$(CROSS_COMPILE)gcc
+OBJCOPY=$(CROSS_COMPILE)objcopy
+OBJDUMP=$(CROSS_COMPILE)objdump
+
+LINKER_SCRIPT := etacorem3.ld
+LINKER_OPTS := -mcpu=cortex-m3 -mthumb
+LINKER_OPTS += -mlittle-endian -O0 -fmessage-length=0 -fsigned-char
+LINKER_OPTS += -ffunction-sections -fdata-sections -gc-sections
+LINKER_OPTS += -nostartfiles -nostdlib --specs=nosys.specs
+
+all: erase.inc write.inc
+
+.PHONY: clean
+
+.INTERMEDIATE: erase.elf write.elf
+
+erase.elf write.elf:
+
+%.elf: %.s
+       $(CC) $(LINKER_OPTS) -T $(LINKER_SCRIPT) "$<" -o "$@"
+
+%.lst: %.elf
+       $(OBJDUMP) -S -d $< > $@
+
+%.bin: %.elf
+       $(OBJCOPY) -Obinary $< $@
+
+%.inc: %.bin
+       $(BIN2C) < $< > $@
+
+clean:
+       -rm -f *.elf *.lst *.bin *.inc
diff --git a/contrib/loaders/flash/etacorem3/erase.inc 
b/contrib/loaders/flash/etacorem3/erase.inc
new file mode 100644
index 0000000..8e00f5e
--- /dev/null
+++ b/contrib/loaders/flash/etacorem3/erase.inc
@@ -0,0 +1,15 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0x90,0xb5,0x89,0xb0,0x02,0xaf,0x4f,0xf0,0x10,0x23,0x3b,0x61,0x3b,0x69,0x1b,0x68,
+0x7b,0x61,0x3b,0x69,0x5b,0x68,0xfb,0x60,0x7a,0x69,0xfb,0x68,0x13,0x44,0xbb,0x60,
+0x7b,0x69,0xb3,0xf1,0x80,0x7f,0x03,0xd2,0x3b,0x69,0x01,0x22,0x1a,0x61,0x4c,0xe0,
+0x7b,0x69,0xb3,0xf1,0x84,0x7f,0x03,0xd3,0x3b,0x69,0x02,0x22,0x1a,0x61,0x44,0xe0,
+0xbb,0x68,0xb3,0xf1,0x84,0x7f,0x03,0xd9,0x3b,0x69,0x03,0x22,0x1a,0x61,0x3c,0xe0,
+0x3b,0x69,0xdb,0x68,0x00,0x2b,0x09,0xd0,0x3b,0x69,0xdb,0x68,0x1a,0x46,0x1e,0x4b,
+0x1a,0x60,0x3b,0x69,0x9b,0x68,0x01,0x2b,0x28,0xd1,0x03,0xe0,0x3b,0x69,0x04,0x22,
+0x1a,0x61,0x2a,0xe0,0x18,0x4b,0x1c,0x68,0x30,0x23,0x01,0x93,0x4f,0xf4,0x40,0x73,
+0x00,0x93,0x30,0x23,0x10,0x22,0x01,0x21,0x4f,0xf0,0x80,0x70,0xa0,0x47,0x19,0xe0,
+0x7b,0x69,0x23,0xf4,0x7f,0x63,0x23,0xf0,0x0f,0x03,0x7b,0x60,0x0e,0x4b,0x1c,0x68,
+0x30,0x23,0x01,0x93,0x4f,0xf4,0x40,0x73,0x00,0x93,0x30,0x23,0x10,0x22,0x00,0x21,
+0x78,0x68,0xa0,0x47,0x7b,0x69,0x03,0xf5,0x80,0x53,0x7b,0x61,0x7a,0x69,0xbb,0x68,
+0x9a,0x42,0xe5,0xd3,0x3b,0x69,0x00,0x22,0x1a,0x61,0x00,0xbe,0x00,0x23,0x18,0x46,
+0x1c,0x37,0xbd,0x46,0x90,0xbd,0x00,0xbf,0xdc,0x00,0x00,0x10,
diff --git a/contrib/loaders/flash/etacorem3/erase.s 
b/contrib/loaders/flash/etacorem3/erase.s
new file mode 100644
index 0000000..64d7a27
--- /dev/null
+++ b/contrib/loaders/flash/etacorem3/erase.s
@@ -0,0 +1,152 @@
+@
+@ Eta Compute ECM35xx flash sector write algorithm.
+@
+@ Copyright (C) 2017-2018 Rick Foos <[email protected]>.
+@
+@ Copyright (C) 2017-2018 Eta Compute www.etacompute.com.
+@
+@ All rights reserved.
+@
+       .syntax unified
+       .cpu cortex-m3
+       .fpu softvfp
+       .eabi_attribute 20, 1
+       .eabi_attribute 21, 1
+       .eabi_attribute 23, 3
+       .eabi_attribute 24, 1
+       .eabi_attribute 25, 1
+       .eabi_attribute 26, 1
+       .eabi_attribute 30, 6
+       .eabi_attribute 34, 1
+       .eabi_attribute 18, 4
+       .thumb
+       .syntax unified
+       .file   "erase.c"
+       .comm   BootROM_flash_erase,4,4
+       .section        .text.main,"ax",%progbits
+       .align  2
+       .global main
+       .thumb
+       .thumb_func
+       .type   main, %function
+main:
+       @ args = 0, pretend = 0, frame = 24
+       @ frame_needed = 1, uses_anonymous_args = 0
+       push    {r4, r7, lr}
+       sub     sp, sp, #36
+       add     r7, sp, #8
+       mov     r3, #268439552
+       str     r3, [r7, #16]
+       ldr     r3, [r7, #16]
+       ldr     r3, [r3]
+       str     r3, [r7, #20]
+       ldr     r3, [r7, #16]
+       ldr     r3, [r3, #4]
+       str     r3, [r7, #12]
+       ldr     r2, [r7, #20]
+       ldr     r3, [r7, #12]
+       add     r3, r3, r2
+       str     r3, [r7, #8]
+       ldr     r3, [r7, #20]
+       cmp     r3, #16777216
+       bcs     .L2
+       ldr     r3, [r7, #16]
+       movs    r2, #1
+       str     r2, [r3, #16]
+       b       .L3
+.L2:
+       ldr     r3, [r7, #20]
+       cmp     r3, #17301504
+       bcc     .L4
+       ldr     r3, [r7, #16]
+       movs    r2, #2
+       str     r2, [r3, #16]
+       b       .L3
+.L4:
+       ldr     r3, [r7, #8]
+       cmp     r3, #17301504
+       bls     .L5
+       ldr     r3, [r7, #16]
+       movs    r2, #3
+       str     r2, [r3, #16]
+       b       .L3
+.L5:
+       ldr     r3, [r7, #16]
+       ldr     r3, [r3, #12]
+       cmp     r3, #0
+       beq     .L6
+       ldr     r3, [r7, #16]
+       ldr     r3, [r3, #12]
+       mov     r2, r3
+       ldr     r3, .L14
+       str     r2, [r3]
+       ldr     r3, [r7, #16]
+       ldr     r3, [r3, #8]
+       cmp     r3, #1
+       bne     .L10
+       b       .L13
+.L6:
+       ldr     r3, [r7, #16]
+       movs    r2, #4
+       str     r2, [r3, #16]
+       b       .L3
+.L13:
+       ldr     r3, .L14
+       ldr     r4, [r3]
+       movs    r3, #48
+       str     r3, [sp, #4]
+       mov     r3, #768
+       str     r3, [sp]
+       movs    r3, #48
+       movs    r2, #16
+       movs    r1, #1
+       mov     r0, #16777216
+       blx     r4
+       b       .L9
+.L11:
+       ldr     r3, [r7, #20]
+       bic     r3, r3, #4080
+       bic     r3, r3, #15
+       str     r3, [r7, #4]
+       ldr     r3, .L14
+       ldr     r4, [r3]
+       movs    r3, #48
+       str     r3, [sp, #4]
+       mov     r3, #768
+       str     r3, [sp]
+       movs    r3, #48
+       movs    r2, #16
+       movs    r1, #0
+       ldr     r0, [r7, #4]
+       blx     r4
+       ldr     r3, [r7, #20]
+       add     r3, r3, #4096
+       str     r3, [r7, #20]
+.L10:
+       ldr     r2, [r7, #20]
+       ldr     r3, [r7, #8]
+       cmp     r2, r3
+       bcc     .L11
+.L9:
+       ldr     r3, [r7, #16]
+       movs    r2, #0
+       str     r2, [r3, #16]
+.L3:
+       .syntax unified
+@ 110 "../src/erase.c" 1
+           BKPT      #0
+@ 0 "" 2
+       .thumb
+       .syntax unified
+       movs    r3, #0
+       mov     r0, r3
+       adds    r7, r7, #28
+       mov     sp, r7
+       @ sp needed
+       pop     {r4, r7, pc}
+.L15:
+       .align  2
+.L14:
+       .word   BootROM_flash_erase
+       .size   main, .-main
+       .ident  "GCC: (15:5.4.1+svn241155-1) 5.4.1 20160919"
diff --git a/contrib/loaders/flash/etacorem3/etacorem3.ld 
b/contrib/loaders/flash/etacorem3/etacorem3.ld
new file mode 100644
index 0000000..e073ad8
--- /dev/null
+++ b/contrib/loaders/flash/etacorem3/etacorem3.ld
@@ -0,0 +1,97 @@
+/****************************************************************************
+*  Copyright (C) 2017 by Rick Foos
+*  [email protected]
+*
+*  Copyright (C) 2017 by ETA Compute
+*  www.etacompute.com
+*
+*  Redistribution and use in source and binary forms, with or without
+*  modification, are permitted provided that the following conditions
+*  are met:
+*
+*  1. Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*  2. Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in the
+*     documentation and/or other materials provided with the distribution.
+*  3. Neither the name of the author nor the names of its contributors may
+*     be used to endorse or promote products derived from this software
+*     without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+*  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+*  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+*  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+*  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+*  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+*  SUCH DAMAGE.
+*
+****************************************************************************/
+
+
+ENTRY(ResetISR)
+SEARCH_DIR(.)
+
+/*
+ *   SRAM is at 0x10000000 of length 0x00020000
+ */
+MEMORY
+{
+    FLASH(RX) : ORIGIN = 0x01000000, LENGTH = 0x00100000
+    SRAM (RWX) : ORIGIN = 0x10000000, LENGTH = 0x00020000
+}
+
+SECTIONS
+{
+    .text :
+    {
+        _text = .;
+        KEEP(*(.vectors))
+        . = ALIGN(0x4);
+        *(.text*)
+        . = ALIGN(0x4);
+        *(.rodata*)
+        . = ALIGN(0x4);
+        _etext = .;
+    } > SRAM= 0
+
+    .data :
+    {
+        . = ALIGN(0x4);
+        _data = .;
+        *(.data*)
+        KEEP(*(.mainHeap))
+        _edata = .;
+    } > SRAM
+
+    .datax :
+    {
+        _datax = .;
+        KEEP(*(.mainStack))
+        _edatax = .;
+    } > SRAM
+    .bss :
+    {
+        . = ALIGN(0x4);
+        _bss = .;
+        *(.bss*)
+        *(COMMON)
+        _ebss = .;
+    } > SRAM
+
+    .magic  0x1001FFF0 :
+    {
+        KEEP(*(.magic))
+        magic_numbers[0]=0xc001c0de;
+        magic_numbers[1]=0xc001c0de;
+        magic_numbers[2]=0xdeadbeef;
+        magic_numbers[3]=0xc369a517;
+    } > SRAM
+
+
+}
diff --git a/contrib/loaders/flash/etacorem3/write.inc 
b/contrib/loaders/flash/etacorem3/write.inc
new file mode 100644
index 0000000..6f4df28
--- /dev/null
+++ b/contrib/loaders/flash/etacorem3/write.inc
@@ -0,0 +1,26 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0x90,0xb5,0x93,0xb0,0x04,0xaf,0x4f,0xf0,0x10,0x23,0x7b,0x62,0x7b,0x6a,0x1b,0x68,
+0x3b,0x62,0x7b,0x6a,0x5b,0x68,0xfb,0x61,0x3a,0x6a,0xfb,0x69,0x13,0x44,0xbb,0x61,
+0x7b,0x6a,0x9b,0x68,0x7b,0x63,0xfb,0x69,0x00,0x2b,0x03,0xd1,0x7b,0x6a,0x00,0x22,
+0x5a,0x61,0x9e,0xe0,0x7b,0x6b,0x00,0x2b,0x01,0xd1,0x51,0x4b,0x7b,0x63,0x3b,0x6a,
+0xb3,0xf1,0x80,0x7f,0x03,0xd2,0x7b,0x6a,0x01,0x22,0x5a,0x61,0x91,0xe0,0x3b,0x6a,
+0xb3,0xf1,0x84,0x7f,0x03,0xd3,0x7b,0x6a,0x02,0x22,0x5a,0x61,0x89,0xe0,0xbb,0x69,
+0xb3,0xf1,0x84,0x7f,0x03,0xd9,0x7b,0x6a,0x03,0x22,0x5a,0x61,0x81,0xe0,0x7b,0x6a,
+0xdb,0x68,0x00,0x2b,0x05,0xd0,0x7b,0x6a,0xdb,0x68,0x1a,0x46,0x41,0x4b,0x1a,0x60,
+0x03,0xe0,0x40,0x4b,0x40,0xf2,0xcd,0x22,0x1a,0x60,0xfb,0x69,0xdb,0x08,0x7b,0x61,
+0x7b,0x6a,0x1b,0x69,0x01,0x2b,0x59,0xd1,0x40,0x23,0x3b,0x61,0x4f,0xf4,0x00,0x73,
+0xfb,0x60,0x7b,0x69,0x3a,0x69,0xb3,0xfb,0xf2,0xf2,0x39,0x69,0x01,0xfb,0x02,0xf2,
+0x9b,0x1a,0xbb,0x60,0x7a,0x69,0x3b,0x69,0xb2,0xfb,0xf3,0xf2,0xbb,0x68,0x00,0x2b,
+0x01,0xd0,0x01,0x23,0x00,0xe0,0x00,0x23,0x13,0x44,0x7b,0x60,0x3b,0x6a,0x3b,0x63,
+0x7b,0x6b,0xfb,0x62,0x00,0x23,0xbb,0x62,0x33,0xe0,0xbb,0x68,0x00,0x2b,0x15,0xd0,
+0x7b,0x68,0x5a,0x1e,0xbb,0x6a,0x9a,0x42,0x10,0xd1,0x26,0x4b,0x1c,0x68,0x30,0x23,
+0x03,0x93,0x4f,0xf4,0x40,0x73,0x02,0x93,0x50,0x23,0x01,0x93,0x28,0x23,0x00,0x93,
+0x10,0x23,0xba,0x68,0xf9,0x6a,0x38,0x6b,0xa0,0x47,0x0f,0xe0,0x1d,0x4b,0x1c,0x68,
+0x30,0x23,0x03,0x93,0x4f,0xf4,0x40,0x73,0x02,0x93,0x50,0x23,0x01,0x93,0x28,0x23,
+0x00,0x93,0x10,0x23,0x3a,0x69,0xf9,0x6a,0x38,0x6b,0xa0,0x47,0x3a,0x6b,0xfb,0x68,
+0x13,0x44,0x3b,0x63,0xfb,0x6a,0x03,0xf5,0x00,0x73,0xfb,0x62,0xbb,0x6a,0x01,0x33,
+0xbb,0x62,0xba,0x6a,0x7b,0x68,0x9a,0x42,0xc7,0xd3,0x0f,0xe0,0x0d,0x4b,0x1c,0x68,
+0x30,0x23,0x03,0x93,0x4f,0xf4,0x40,0x73,0x02,0x93,0x50,0x23,0x01,0x93,0x28,0x23,
+0x00,0x93,0x10,0x23,0x7a,0x69,0x79,0x6b,0x38,0x6a,0xa0,0x47,0x7b,0x6a,0x00,0x22,
+0x5a,0x61,0x00,0xbe,0x00,0x23,0x18,0x46,0x3c,0x37,0xbd,0x46,0x90,0xbd,0x00,0xbf,
+0x00,0x20,0x00,0x10,0x88,0x01,0x00,0x10,
diff --git a/contrib/loaders/flash/etacorem3/write.s 
b/contrib/loaders/flash/etacorem3/write.s
new file mode 100644
index 0000000..f2ed0de
--- /dev/null
+++ b/contrib/loaders/flash/etacorem3/write.s
@@ -0,0 +1,242 @@
+@
+@ Eta Compute ECM35xx flash sector write algorithm.
+@
+@ Copyright (C) 2017-2018 Rick Foos <[email protected]>.
+@
+@ Copyright (C) 2017-2018 Eta Compute www.etacompute.com.
+@
+@ All rights reserved.
+@
+
+       .syntax unified
+       .cpu cortex-m3
+       .fpu softvfp
+       .eabi_attribute 20, 1
+       .eabi_attribute 21, 1
+       .eabi_attribute 23, 3
+       .eabi_attribute 24, 1
+       .eabi_attribute 25, 1
+       .eabi_attribute 26, 1
+       .eabi_attribute 30, 6
+       .eabi_attribute 34, 1
+       .eabi_attribute 18, 4
+       .thumb
+       .syntax unified
+       .file   "write.c"
+       .comm   BootROM_flash_program,4,4
+       .section        .text.main,"ax",%progbits
+       .align  2
+       .global main
+       .thumb
+       .thumb_func
+       .type   main, %function
+main:
+       @ args = 0, pretend = 0, frame = 56
+       @ frame_needed = 1, uses_anonymous_args = 0
+       push    {r4, r7, lr}
+       sub     sp, sp, #76
+       add     r7, sp, #16
+       mov     r3, #268439552
+       str     r3, [r7, #36]
+       ldr     r3, [r7, #36]
+       ldr     r3, [r3]
+       str     r3, [r7, #32]
+       ldr     r3, [r7, #36]
+       ldr     r3, [r3, #4]
+       str     r3, [r7, #28]
+       ldr     r2, [r7, #32]
+       ldr     r3, [r7, #28]
+       add     r3, r3, r2
+       str     r3, [r7, #24]
+       ldr     r3, [r7, #36]
+       ldr     r3, [r3, #8]
+       str     r3, [r7, #52]
+       ldr     r3, [r7, #28]
+       cmp     r3, #0
+       bne     .L2
+       ldr     r3, [r7, #36]
+       movs    r2, #0
+       str     r2, [r3, #20]
+       b       .L3
+.L2:
+       ldr     r3, [r7, #52]
+       cmp     r3, #0
+       bne     .L4
+       ldr     r3, .L19
+       str     r3, [r7, #52]
+.L4:
+       ldr     r3, [r7, #32]
+       cmp     r3, #16777216
+       bcs     .L5
+       ldr     r3, [r7, #36]
+       movs    r2, #1
+       str     r2, [r3, #20]
+       b       .L3
+.L5:
+       ldr     r3, [r7, #32]
+       cmp     r3, #17301504
+       bcc     .L6
+       ldr     r3, [r7, #36]
+       movs    r2, #2
+       str     r2, [r3, #20]
+       b       .L3
+.L6:
+       ldr     r3, [r7, #24]
+       cmp     r3, #17301504
+       bls     .L7
+       ldr     r3, [r7, #36]
+       movs    r2, #3
+       str     r2, [r3, #20]
+       b       .L3
+.L7:
+       ldr     r3, [r7, #36]
+       ldr     r3, [r3, #12]
+       cmp     r3, #0
+       beq     .L8
+       ldr     r3, [r7, #36]
+       ldr     r3, [r3, #12]
+       mov     r2, r3
+       ldr     r3, .L19+4
+       str     r2, [r3]
+       b       .L9
+.L8:
+       ldr     r3, .L19+4
+       movw    r2, #717
+       str     r2, [r3]
+.L9:
+       ldr     r3, [r7, #28]
+       lsrs    r3, r3, #3
+       str     r3, [r7, #20]
+       ldr     r3, [r7, #36]
+       ldr     r3, [r3, #16]
+       cmp     r3, #1
+       bne     .L10
+       movs    r3, #64
+       str     r3, [r7, #16]
+       mov     r3, #512
+       str     r3, [r7, #12]
+       ldr     r3, [r7, #20]
+       ldr     r2, [r7, #16]
+       udiv    r2, r3, r2
+       ldr     r1, [r7, #16]
+       mul     r2, r1, r2
+       subs    r3, r3, r2
+       str     r3, [r7, #8]
+       ldr     r2, [r7, #20]
+       ldr     r3, [r7, #16]
+       udiv    r2, r2, r3
+       ldr     r3, [r7, #8]
+       cmp     r3, #0
+       beq     .L11
+       movs    r3, #1
+       b       .L12
+.L11:
+       movs    r3, #0
+.L12:
+       add     r3, r3, r2
+       str     r3, [r7, #4]
+       ldr     r3, [r7, #32]
+       str     r3, [r7, #48]
+       ldr     r3, [r7, #52]
+       str     r3, [r7, #44]
+       movs    r3, #0
+       str     r3, [r7, #40]
+       b       .L13
+.L16:
+       ldr     r3, [r7, #8]
+       cmp     r3, #0
+       beq     .L14
+       ldr     r3, [r7, #4]
+       subs    r2, r3, #1
+       ldr     r3, [r7, #40]
+       cmp     r2, r3
+       bne     .L14
+       ldr     r3, .L19+4
+       ldr     r4, [r3]
+       movs    r3, #48
+       str     r3, [sp, #12]
+       mov     r3, #768
+       str     r3, [sp, #8]
+       movs    r3, #80
+       str     r3, [sp, #4]
+       movs    r3, #40
+       str     r3, [sp]
+       movs    r3, #16
+       ldr     r2, [r7, #8]
+       ldr     r1, [r7, #44]
+       ldr     r0, [r7, #48]
+       blx     r4
+       b       .L15
+.L14:
+       ldr     r3, .L19+4
+       ldr     r4, [r3]
+       movs    r3, #48
+       str     r3, [sp, #12]
+       mov     r3, #768
+       str     r3, [sp, #8]
+       movs    r3, #80
+       str     r3, [sp, #4]
+       movs    r3, #40
+       str     r3, [sp]
+       movs    r3, #16
+       ldr     r2, [r7, #16]
+       ldr     r1, [r7, #44]
+       ldr     r0, [r7, #48]
+       blx     r4
+.L15:
+       ldr     r2, [r7, #48]
+       ldr     r3, [r7, #12]
+       add     r3, r3, r2
+       str     r3, [r7, #48]
+       ldr     r3, [r7, #44]
+       add     r3, r3, #512
+       str     r3, [r7, #44]
+       ldr     r3, [r7, #40]
+       adds    r3, r3, #1
+       str     r3, [r7, #40]
+.L13:
+       ldr     r2, [r7, #40]
+       ldr     r3, [r7, #4]
+       cmp     r2, r3
+       bcc     .L16
+       b       .L17
+.L10:
+       ldr     r3, .L19+4
+       ldr     r4, [r3]
+       movs    r3, #48
+       str     r3, [sp, #12]
+       mov     r3, #768
+       str     r3, [sp, #8]
+       movs    r3, #80
+       str     r3, [sp, #4]
+       movs    r3, #40
+       str     r3, [sp]
+       movs    r3, #16
+       ldr     r2, [r7, #20]
+       ldr     r1, [r7, #52]
+       ldr     r0, [r7, #32]
+       blx     r4
+.L17:
+       ldr     r3, [r7, #36]
+       movs    r2, #0
+       str     r2, [r3, #20]
+.L3:
+       .syntax unified
+@ 148 "../src/write.c" 1
+           BKPT      #0
+@ 0 "" 2
+       .thumb
+       .syntax unified
+       movs    r3, #0
+       mov     r0, r3
+       adds    r7, r7, #60
+       mov     sp, r7
+       @ sp needed
+       pop     {r4, r7, pc}
+.L20:
+       .align  2
+.L19:
+       .word   268443648
+       .word   BootROM_flash_program
+       .size   main, .-main
+       .ident  "GCC: (15:5.4.1+svn241155-1) 5.4.1 20160919"
diff --git a/doc/openocd.texi b/doc/openocd.texi
index ebd03c4..f463982 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -5318,6 +5318,37 @@ Note that in order for this command to take effect, the 
target needs to be reset
 supported.}
 @end deffn
 
+@deffn {Flash Driver} etacorem3
+Eta Compute's ECM35xx series SOC's include ARM's Cortex-M3 and a Dual MAC DSP.
+Both cores are implemented using Eta Compute's proprietary
+DIAL Technology
+supporting deep subthreshold and self-timed operation (140Khz - 100Mhz)
+for ultra-low power IOT applications including:
+@itemize @bullet
+@item IOT Sensor Nodes
+@item BLE Beacon
+@item Wearable Computation.
+@end itemize
+ECM35XX SOC's include an ADC to reduce the need for external sensors, and
+several PMIC / Buck Converters that reduce power requirements.
+
+The driver automatically recognizes flash size, and autoconfigures itself.
+In some cases the optional BOARDTYPE parameter is used by the driver.
+Separate board config files are available defining this parameter.
+@example
+# Optional parameter for Board/FPGA type.
+flash bank $_FLASHNAME etacorem3 0 0 0 0 $_TARGETNAME $_BOARDTYPE
+@end example
+
+There is one additional command defined in the @var{etacorem3} driver:
+
+@deffn Command {etacorem3 mass_erase} num
+Mass erases the entire etacorem3 device.
+The @var{num} parameter is a value shown by @command{flash banks}.
+@end deffn
+
+@end deffn
+
 @deffn {Flash Driver} fm3
 All members of the FM3 microcontroller family from Fujitsu
 include internal flash and use ARM Cortex-M3 cores.
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index ebf4775..7f5e9bd 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -22,6 +22,7 @@ NOR_DRIVERS = \
        %D%/dsp5680xx_flash.c \
        %D%/efm32.c \
        %D%/em357.c \
+       %D%/etacorem3.c \
        %D%/faux.c \
        %D%/fm3.c \
        %D%/fm4.c \
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index eacca03..9a0e287 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -35,6 +35,7 @@ extern struct flash_driver cfi_flash;
 extern struct flash_driver dsp5680xx_flash;
 extern struct flash_driver efm32_flash;
 extern struct flash_driver em357_flash;
+extern struct flash_driver etacorem3_flash;
 extern struct flash_driver faux_flash;
 extern struct flash_driver fm3_flash;
 extern struct flash_driver fm4_flash;
@@ -90,6 +91,7 @@ static struct flash_driver *flash_drivers[] = {
        &dsp5680xx_flash,
        &efm32_flash,
        &em357_flash,
+       &etacorem3_flash,
        &faux_flash,
        &fm3_flash,
        &fm4_flash,
diff --git a/src/flash/nor/etacorem3.c b/src/flash/nor/etacorem3.c
new file mode 100644
index 0000000..ab50523
--- /dev/null
+++ b/src/flash/nor/etacorem3.c
@@ -0,0 +1,1093 @@
+/*
+ * Copyright (C) 2017-2018 by Rick Foos
+ * [email protected]
+ *
+ * Copyright (C) 2017-2018 by Eta Compute, Inc.
+ * www.etacompute.com
+ *
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "imp.h"
+#include "helper/binarybuffer.h"
+#include "target/algorithm.h"
+#include "target/armv7m.h"
+#include "target/cortex_m.h"
+#include "target/arm_opcodes.h"
+
+/**
+ * @file
+ * Flash programming support for ETA ECM3xx devices.
+ */
+
+/* SRAM Address for magic numbers. */
+
+#define MAGIC_ADDR_M3ETA    (0x0001FFF0)
+#define MAGIC_ADDR_SUBZ     (0x1001FFF0)
+
+/* Max flash/sram size all supported parts. */
+
+#define ETA_COMMON_SRAM_SIZE_MAX        (0x00020000)
+#define ETA_COMMON_FLASH_SIZE_MAX       (0x00080000)
+
+/* Supported parts, M3ETA, SUBZ */
+
+#define ETA_COMMON_SRAM_MAX_M3ETA  (0x00020000)
+#define ETA_COMMON_SRAM_BASE_M3ETA (0x00000000)
+#define ETA_COMMON_SRAM_SIZE_M3ETA \
+       (ETA_COMMON_SRAM_MAX_M3ETA - ETA_COMMON_SRAM_BASE_M3ETA)
+#define ETA_COMMON_FLASH_PAGE_SIZE_M3ETA (0)
+
+#define ETA_COMMON_SRAM_MAX_SUBZ  (0x10020000)
+#define ETA_COMMON_SRAM_BASE_SUBZ (0x10000000)
+#define ETA_COMMON_SRAM_SIZE_SUBZ \
+       (ETA_COMMON_SRAM_MAX_SUBZ - ETA_COMMON_SRAM_BASE_SUBZ)
+
+#define ETA_COMMON_FLASH_MAX_SUBZ  0x01080000
+#define ETA_COMMON_FLASH_BASE_SUBZ 0x01000000
+#define ETA_COMMON_FLASH_SIZE_SUBZ \
+       (ETA_COMMON_FLASH_MAX_SUBZ - ETA_COMMON_FLASH_BASE_SUBZ)
+#define ETA_COMMON_FLASH_PAGE_SIZE_SUBZ (4096)
+#define ETA_COMMON_FLASH_NUM_PAGES_SUBZ \
+       (ETA_COMMON_FLASH_SIZE_SUBZ / ETA_COMMON_FLASH_PAGE_SIZE_SUBZ)
+#define ETA_COMMON_FLASH_PAGE_ADDR_BITS (12)
+#define ETA_COMMON_FLASH_PAGE_ADDR_MASK (0xFFFFF000)
+
+/* Fixed parameters in bootrom calls. */
+
+#define BOOTROM_FLASH_TNVS_COUNT   (0x10)
+#define BOOTROM_FLASH_TRE_COUNT    (0x28)
+#define BOOTROM_FLASH_TNVH_COUNT   (0x300)
+#define BOOTROM_FLASH_TRCV_COUNT   (0x30)
+#define BOOTROM_FLASH_TERASE_COUNT (0x30)
+#define BOOTROM_FLASH_TPGS_COUNT   (0x28)
+#define BOOTROM_FLASH_TPROG_COUNT  (0x50)
+
+/**
+@verbatim
+ ARM Debug Interface Architecture Specification ADIv5.0 to ADIv5.2
+
+ SCS Coresite Identification
+ 0xE000EFE0    Peripheral ID0  0x0000000C
+ 0xE000EFE4    Peripheral ID1  0x000000B0
+ 0xE000EFE8    Peripheral ID2  0x0000000B
+ 0xE000EFEC    Peripheral ID3  0x00000000
+ 0xE000EFF0    Component ID0   0x0000000D
+ 0xE000EFF4    Component ID1   0x000000E0
+ 0xE000EFF8    Component ID2   0x00000005
+ 0xE000EFFC    Component ID3   0x000000B1
+
+ ROM Table
+ 0xE00FFFD0    Peripheral ID4  0x00000000
+ 0xE00FFFE0    Peripheral ID0  0x00000000
+ 0xE00FFFE4    Peripheral ID1  0x00000000
+ 0xE00FFFE8    Peripheral ID2  0x00000000
+ 0xE00FFFEC    Peripheral ID3  0x00000000
+ 0xE00FFFF0    Component ID0   0x0000000D
+ 0xE00FFFF4    Component ID1   0x00000010
+ 0xE00FFFF8    Component ID2   0x00000005
+ 0xE00FFFFC    Component ID3   0x000000B1
+@endverbatim
+*/
+
+/* Jedec ROM (Debug) Registers to ID chip/bootrom version. */
+
+/** ROM Peripheral ID 0 for Cortex M3. */
+#define REG_JEDEC_PID0             (0xE00FFFE0)
+#define REG_JEDEC_PID1             (0xE00FFFE4)
+#define REG_JEDEC_PID2             (0xE00FFFE8)
+#define REG_JEDEC_PID3             (0xE00FFFEC)
+
+typedef union {
+       uint8_t pids[4];
+       uint32_t jedec;
+} jedec_pid_container;
+
+#define PID_M3ETA       (0x11201691)
+#define PID_SUBZERO     (0x09201791)
+
+/**
+ * Chip versions supported by this driver.
+ * Based on Cortex M3 ROM PID 0-3.
+ */
+typedef enum {
+       etacore_m3eta = 0,      /* 0x11201691 */
+       etacore_subzero,        /* 0x09201791 */
+       etacore_unknown,
+} etacorem3_variant;
+
+/**
+ * ETA flash bank info from probe.
+ */
+struct etacorem3_flash_bank {
+       etacorem3_variant variant;
+
+       /* flash geometry */
+
+       uint32_t num_pages;     /**< Number of flash pages.  */
+       uint32_t pagesize;      /**< Flash Page Size  */
+
+       /* part specific info needed by driver. */
+
+       const char *target_name;
+       uint32_t magic_address;
+       uint32_t sram_base;     /**< SRAM Start Address. */
+       uint32_t sram_size;     /**< SRAM size calculated during probe. */
+       uint32_t sram_max;
+       uint32_t flash_base;    /**< Flash Start Address. */
+       uint32_t flash_size;    /**< Flash size calculated during probe. */
+       uint32_t flash_max;
+       uint32_t bootrom_erase_entry;
+       uint32_t bootrom_write_entry;   /**< BootROM_flash_program */
+
+       uint32_t jedec; /**< chip info from rom PID. */
+       bool fpga;      /**< board or fpga from cfg file. */
+       bool probed;    /**< Flash bank has been probed. */
+};
+
+/*
+ * Jump table for subzero bootroms.
+ */
+
+#define BootROM_flash_erase_board       (0x00000385)
+#define BootROM_flash_program_board     (0x000004C9)
+#define BootROM_flash_erase_fpga        (0x00000249)
+#define BootROM_flash_program_fpga      (0x000002CD)
+
+/**
+ * Load and entry points of wrapper function.
+ * @note Depends on -work-area-phys in target file.
+ */
+#define SRAM_ENTRY_POINT        (0x10000000)
+/** Location wrapper functions look for parameters, and top of stack. */
+#define SRAM_PARAM_START        (0x10001000)
+/** Target buffer start address for write operations. */
+#define SRAM_BUFFER_START       (0x10002000)
+/** Target buffer size. */
+#define SRAM_BUFFER_SIZE        (0x00004000)
+/** Target algorithm start, Set in target -work-area-size. */
+#define SRAM_ALGO_START         (0x10006000)
+/** Target algo code max size. Set in target file -work-area-phys. */
+#define SRAM_ALGO_SIZE          (0x00004000)
+
+/** Last element of one dimensional array */
+#define ARRAY_LAST(x) x[ARRAY_SIZE(x)-1]
+
+#define TARGET_HALTED(target) { \
+               if (target->state != TARGET_HALTED) { \
+                       LOG_ERROR("Target not halted"); \
+                       return ERROR_TARGET_NOT_HALTED; } }
+
+#define TARGET_PROBED(info) { \
+               if (!info->probed) { \
+                       LOG_ERROR("Target not probed"); \
+                       return ERROR_FLASH_BANK_NOT_PROBED; } }
+
+#define TARGET_HALTED_AND_PROBED(target, info) { \
+               if (target->state != TARGET_HALTED) { \
+                       LOG_ERROR("Target not halted"); \
+                       return ERROR_TARGET_NOT_HALTED; \
+               } \
+               if (!info->probed) { \
+                       LOG_ERROR("Target not probed"); \
+                       return ERROR_FLASH_BANK_NOT_PROBED; } }
+
+#define CHECK_STATUS(rc, msg) { \
+               if (rc != ERROR_OK) \
+                       LOG_ERROR("status(%" PRId32 "):%s\n", rc, msg); }
+
+#define CHECK_STATUS_RETURN(rc, msg) { \
+               if (rc != ERROR_OK) { \
+                       LOG_ERROR("status(%" PRId32 "):%s\n", rc, msg); \
+                       return rc; } }
+
+#define CHECK_STATUS_BREAK(rc, msg) { \
+               if (rc != ERROR_OK) { \
+                       LOG_ERROR("status(%" PRId32 "):%s\n", rc, msg); \
+                       break; } }
+
+/*
+ * Global storage for driver.
+ */
+
+/** Part names used by flash info command. */
+static const char const *etacorePartnames[] = {
+       "ETA M3",
+       "ETA M3/DSP (Subzero)",
+       "Unknown"
+};
+
+/** Magic numbers loaded into sram before bootrom call. */
+static const uint32_t magic_numbers[] = {
+       0xc001c0de,
+       0xc001c0de,
+       0xdeadbeef,
+       0xc369a517,
+};
+
+/*
+ * Utilities
+ */
+
+/**
+ * Set magic numbers in target sram.
+ * @param bank information.
+ * @returns status of write buffer.
+ */
+static int set_magic_numbers(struct flash_bank *bank)
+{
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+       int retval = target_write_buffer(bank->target, 
etacorem3_bank->magic_address,
+                       sizeof(magic_numbers), (uint8_t *)magic_numbers);
+       return retval;
+}
+
+/**
+ * Read Jedec PID 0-3.
+ * @param bank
+ * @returns success is 32 bit pids.
+ * @returns failure is 0
+ * @note If not Halted, reads to ROM PIDs return invalid values.
+ */
+static int get_jedec_pid03(struct flash_bank *bank)
+{
+       struct target *target = bank->target;
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+
+       /* If we have already read PID successfully, don't erase. */
+       if (etacorem3_bank->jedec != 0)
+               return etacorem3_bank->jedec;
+
+       /* special error return code 0 for this routine. */
+
+       /* If target is not halted, PID's don't read back a good value. */
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return 0;
+       }
+
+       jedec_pid_container pid03;
+       uint32_t i, addr;
+       for (i = 0, addr = REG_JEDEC_PID0; i < 4; i++, addr += 4) {
+               uint32_t buf;
+               int retval = target_read_u32(bank->target, addr, &buf);
+               pid03.pids[i] = (uint8_t) (buf & 0x000000FF);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("JEDEC PID%" PRId32 " not readable %" PRId32 
".", i, retval);
+                       return 0;
+               }
+       }
+
+       return pid03.jedec;
+}
+
+/**
+ * Set chip variant based on PID.
+ * Default to Subzero.
+ * @param bank
+ * @return success is ERROR_OK.
+ * @return failure if not probed.
+ */
+static int set_variant(struct flash_bank *bank)
+{
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+       int retval = ERROR_OK;
+
+       /* This may have failed previously if not halted. */
+       if (etacorem3_bank->jedec == 0) {
+               TARGET_HALTED(bank->target);
+               etacorem3_bank->jedec = get_jedec_pid03(bank);
+       }
+
+       /* Add parts here. We need to know the bootrom version. */
+       switch (etacorem3_bank->jedec) {
+               case 0x11201691:
+                       etacorem3_bank->variant = etacore_m3eta;
+                       break;
+               case 0x09201791:
+                       etacorem3_bank->variant = etacore_subzero;
+                       break;
+               default:
+                       etacorem3_bank->variant = etacore_subzero;
+                       break;
+       }
+       return retval;
+}
+
+/** write the caller's_is_erased flag to given sectors. */
+static int write_is_erased(struct flash_bank *bank, int first, int last, int 
flag)
+{
+       if ((first > bank->num_sectors) || (last > bank->num_sectors))
+               return ERROR_FAIL;
+
+       for (int i = first; i < last; i++)
+               bank->sectors[i].is_erased = flag;
+
+       LOG_DEBUG("%" PRId32 " pages erased!", 1+(last-first));
+
+       return ERROR_OK;
+}
+
+/**
+ * Find memory size.
+ * @param bank
+ * @param startaddress
+ * @param maxsize
+ * @param increment
+ * @returns on success size in bytes.
+ * @returns on failure 0.
+ *
+ */
+static uint32_t get_memory_size(struct flash_bank *bank,
+       uint32_t startaddress,
+       uint32_t maxsize,
+       uint32_t increment)
+{
+       int retval;
+       uint32_t i, data;
+
+       /* Chip has no Memory. */
+       retval = target_read_u32(bank->target, startaddress, &data);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Memory not found at 0x%08" PRIx32 ".", startaddress);
+               return 0;
+       }
+
+       /* The memory scan causes a bus fault. Ignore expected error messages. 
*/
+       int save_debug_level = debug_level;
+       debug_level = LOG_LVL_OUTPUT;
+       /* Read flash size we are testing. 0 - Max flash size, 16k increments. 
*/
+       for (i = 0; i < maxsize; i += increment) {
+               retval = target_read_u32(bank->target, startaddress+i, &data);
+               if (retval != ERROR_OK)
+                       break;
+       }
+       /* Restore output level. */
+       debug_level = save_debug_level;
+
+       LOG_DEBUG("Memory starting at 0x%08" PRIx32 " size: %" PRIu32 " KB.",
+               startaddress, i/1024);
+       return i;
+}
+
+/*
+ * OpenOCD exec commands.
+ */
+
+/** Breakpoint loaded to sram location of return codes. */
+#define BREAKPOINT                  (0xfffffffe)
+
+/** Target sram wrapper code for erase. */
+static const uint8_t erase_sector_code[] = {
+#include "../../../contrib/loaders/flash/etacorem3/erase.inc"
+};
+
+/** SRAM parameters for erase. */
+typedef struct {
+       uint32_t flashAddress;
+       uint32_t flashLength;
+       uint32_t options;
+       uint32_t BootROM_entry_point;
+       uint32_t retval;
+} eta_erase_interface;
+
+/** Target sram wrapper code for write. */
+static const uint8_t write_sector_code[] = {
+#include "../../../contrib/loaders/flash/etacorem3/write.inc"
+};
+
+/** SRAM parameters for write. */
+typedef struct {
+       uint32_t flashAddress;
+       uint32_t flashLength;
+       uint32_t sramBuffer;
+       uint32_t BootROM_entry_point;
+       uint32_t options;       /**< 1 - Write 512 bytes at a time. */
+       uint32_t retval;
+} eta_write_interface;
+
+static int common_erase_run(struct flash_bank *bank)
+{
+       int retval;
+
+       /*
+        * Load Magic numbers required for bootrom help function execution.
+        */
+       retval = set_magic_numbers(bank);
+       if (retval != ERROR_OK) {
+               CHECK_STATUS(retval, "error writing magic numbers to target.");
+               goto err_write_code;
+       }
+
+       struct working_area *workarea;
+       struct reg_param reg_params[1];
+       struct armv7m_algorithm armv7m_algo;
+
+       /*
+        * Load erase code.
+        */
+       retval = target_alloc_working_area(bank->target,
+                       sizeof(erase_sector_code), &workarea);
+       LOG_DEBUG("workarea address: 0x%08" PRIx64 ".", workarea->address);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("No working area available.");
+               retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               goto err_alloc_code;
+       }
+       retval = target_write_buffer(bank->target, workarea->address,
+                       sizeof(erase_sector_code), erase_sector_code);
+       if (retval != ERROR_OK)
+               goto err_write_code;
+
+       armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
+       armv7m_algo.core_mode = ARM_MODE_THREAD;
+
+       /* wrapper function needs stack */
+       init_reg_param(&reg_params[0], "sp", 32, PARAM_OUT);
+       /* Set the sram stack. */
+       buf_set_u32(reg_params[0].value, 0, 32, SRAM_PARAM_START);
+       /* Run the code. */
+       retval = target_run_algorithm(bank->target,
+                       0, NULL,
+                       ARRAY_SIZE(reg_params), reg_params,
+                       workarea->address, 0,
+                       5000, &armv7m_algo);
+       uint32_t retvalT;
+       int retval1 = target_read_u32(bank->target,
+                       SRAM_PARAM_START + 0x10,
+                       &retvalT);
+       if ((retval != ERROR_OK) || (retval1 != ERROR_OK) || (retvalT != 0)) {
+               LOG_ERROR(
+                       "Error executing flash erase %" PRId32 ", RC1 %" PRId32 
", TRC %" PRId32 ".",
+                       retval,
+                       retval1,
+                       retvalT);
+               target_read_u32(bank->target, SRAM_PARAM_START, &retvalT);
+               LOG_DEBUG("Address: 0x%08X", retvalT);
+               retval = ERROR_FLASH_OPERATION_FAILED;
+               goto err_run;
+       }
+
+err_run:
+       for (unsigned i = 0; i < ARRAY_SIZE(reg_params); i++)
+               destroy_reg_param(&reg_params[i]);
+
+err_write_code:
+       target_free_working_area(bank->target, workarea);
+
+err_alloc_code:
+
+       return retval;
+}
+
+/**
+ * Mass erase flash bank.
+ * @param bank Pointer to the flash bank descriptor.
+ * @return retval
+ *
+ */
+static int etacorem3_mass_erase(struct flash_bank *bank)
+{
+       struct target *target = bank->target;
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+       int retval = ERROR_OK;
+
+       TARGET_HALTED_AND_PROBED(target, etacorem3_bank);
+
+       /*
+        * Load SRAM Parameters.
+        */
+       eta_erase_interface sramargs = {
+               etacorem3_bank->flash_base,     /**< Start of flash. */
+               0x00000000,     /**< Length 0 for all. */
+               0x00000001,     /**< Option 1, mass erase. */
+               etacorem3_bank->bootrom_erase_entry,    /**< BootROM entry 
point. */
+               BREAKPOINT      /**< Return code from BootROM. */
+       };
+       retval = target_write_buffer(target, SRAM_PARAM_START,
+                       sizeof(eta_erase_interface), (uint8_t *)&sramargs);
+       if (retval != ERROR_OK) {
+               CHECK_STATUS(retval, "error writing target SRAM parameters.");
+               goto err_alloc_code;
+       }
+
+       /* Common erase execution code. */
+       retval = common_erase_run(bank);
+
+       /* if successful, mark sectors as erased */
+       if (retval == ERROR_OK)
+               write_is_erased(bank,
+                       etacorem3_bank->flash_base,
+                       etacorem3_bank->flash_base + etacorem3_bank->flash_size,
+                       1);
+
+       LOG_DEBUG("Mass erase on bank %" PRId32 ".", bank->bank_number);
+
+err_alloc_code:
+       return retval;
+}
+
+/**
+ * Erase pages in flash.
+ *
+ * @param bank Pointer to the flash bank descriptor.
+ * @param first
+ * @param last
+ * @return retval
+ *
+ */
+static int etacorem3_erase(struct flash_bank *bank, int first, int last)
+{
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+       struct target *target = bank->target;
+       int retval;
+
+       TARGET_HALTED_AND_PROBED(target, etacorem3_bank);
+
+       LOG_DEBUG("ETA ECM35xx erase sectors %" PRId32 " to %" PRId32 ".", 
first, last);
+
+       /*
+        * Check for valid page range.
+        */
+       if ((first < 0) || (last < first) || (last >= 
(int)etacorem3_bank->num_pages))
+               return ERROR_FLASH_SECTOR_INVALID;
+
+       /*
+        * Mass Erase if all pages are given.
+        */
+       if ((first == 0) && (last == ((int)etacorem3_bank->num_pages-1)))
+               return etacorem3_mass_erase(bank);
+
+       /*
+        * Load SRAM Parameters.
+        */
+       eta_erase_interface sramargs = {
+               etacorem3_bank->flash_base + (first * etacorem3_bank->pagesize),
+               (last - first + 1) * etacorem3_bank->pagesize,  /**< Length in 
bytes. */
+               0x00000000,     /**< Request page erase. */
+               etacorem3_bank->bootrom_erase_entry,    /**< BootROM entry 
point. */
+               BREAKPOINT      /**< Return code from BootROM. */
+       };
+       retval = target_write_buffer(bank->target, SRAM_PARAM_START,
+                       sizeof(eta_erase_interface), (uint8_t *)&sramargs);
+       if (retval != ERROR_OK) {
+               CHECK_STATUS(retval, "error writing target SRAM parameters.");
+               goto err_alloc_code;
+       }
+
+       /* Common erase execution code. */
+       retval = common_erase_run(bank);
+
+       /* if successful, mark sectors as erased */
+       if (retval == ERROR_OK)
+               write_is_erased(bank, first, last, 1);
+
+err_alloc_code:
+
+       return retval;
+}
+
+/**
+ * Write pages to flash from buffer.
+ * @param bank
+ * @param buffer
+ * @param offset
+ * @param count
+ * @returns success ERROR_OK
+ */
+static int etacorem3_write(struct flash_bank *bank,
+       const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+       struct target *target = bank->target;
+       uint32_t address = bank->base + offset;
+       uint32_t buffer_pointer = SRAM_BUFFER_START;
+       uint32_t maxbuffer;
+       uint32_t thisrun_count;
+       int retval = ERROR_OK;
+
+       /* Bootrom uses 64 bit count. */
+       if (((count%4) != 0) || ((offset%4) != 0)) {
+               LOG_ERROR("write block must be multiple of 4 bytes in offset & 
length");
+               return ERROR_FAIL;
+       }
+
+       /*
+        * Load Magic numbers required for bootrom help function execution.
+        */
+       retval = set_magic_numbers(bank);
+       if (retval != ERROR_OK) {
+               CHECK_STATUS(retval, "error writing magic numbers to target.");
+               goto err_write_code;
+       }
+
+       /*
+        * Max buffer size for this device...
+        * Bootrom can only write 512 bytes at a time.
+        * Target side code will block the write into 512 bytes.
+        */
+       maxbuffer = SRAM_BUFFER_SIZE;
+
+       struct working_area *workarea;
+       struct reg_param reg_params[1];
+
+       /*
+        * Allocate space on target for write code.
+        */
+       retval = target_alloc_working_area(bank->target,
+                       sizeof(write_sector_code),
+                       &workarea);
+       LOG_DEBUG("workarea address: 0x%08" PRIx64 ".", workarea->address);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("No working area available.");
+               retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               goto err_alloc_code;
+       }
+       /*
+        * Load code on target.
+        */
+       retval = target_write_buffer(bank->target, workarea->address,
+                       sizeof(write_sector_code), write_sector_code);
+       if (retval != ERROR_OK)
+               goto err_write_code;
+
+       while (count > 0) {
+               if (count > maxbuffer)
+                       thisrun_count = maxbuffer;
+               else
+                       thisrun_count = count;
+
+               /*
+                * Load target Write Buffer.
+                */
+               retval = target_write_buffer(target, buffer_pointer, 
thisrun_count, buffer);
+               CHECK_STATUS_BREAK(retval, "error writing buffer to target.");
+
+               LOG_DEBUG("address = 0x%08" PRIx32, address);
+
+               /*
+                * Load SRAM Parameters.
+                */
+               eta_write_interface sramargs = {
+                       address,        /**< Start address in flash. */
+                       thisrun_count,  /**< Length in bytes. */
+                       buffer_pointer,
+                       etacorem3_bank->bootrom_write_entry,    /**< BootROM 
entry point. */
+                       0x00000001,     /**< Option 1, write flash in 512 byte 
blocks. */
+                       BREAKPOINT      /**< Return code from BootROM. */
+               };
+               retval = target_write_buffer(bank->target, SRAM_PARAM_START,
+                               sizeof(eta_write_interface), (uint8_t 
*)&sramargs);
+               if (retval != ERROR_OK) {
+                       CHECK_STATUS(retval, "error writing target SRAM 
parameters.");
+                       goto err_alloc_code;
+               }
+
+               struct armv7m_algorithm armv7m_algo;
+
+               armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
+               armv7m_algo.core_mode = ARM_MODE_THREAD;
+
+               /* wrapper function stack */
+               init_reg_param(&reg_params[0], "sp", 32, PARAM_OUT);
+               /* Set the sram stack. */
+               buf_set_u32(reg_params[0].value, 0, 32, SRAM_PARAM_START);
+               /* Run the code. */
+               retval = target_run_algorithm(bank->target,
+                               0, NULL,
+                               ARRAY_SIZE(reg_params), reg_params,
+                               workarea->address, 0,
+                               4000, &armv7m_algo);
+               uint32_t retvalT;
+               int retval1 = target_read_u32(bank->target,
+                               SRAM_PARAM_START + 0x14,
+                               &retvalT);
+               if ((retval != ERROR_OK) || (retval1 != ERROR_OK) || (retvalT 
!= 0)) {
+                       LOG_ERROR(
+                               "Error executing flash erase %" PRId32 ", RC1 
%" PRId32 ", TRC %" PRId32 ".",
+                               retval,
+                               retval1,
+                               retvalT);
+                       LOG_DEBUG("address: 0x%08X, count: 0x%08X", address, 
thisrun_count);
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       goto err_run;
+               }
+               buffer += thisrun_count;
+               address += thisrun_count;
+               count -= thisrun_count;
+       }
+
+
+err_run:
+       for (unsigned i = 0; i < ARRAY_SIZE(reg_params); i++)
+               destroy_reg_param(&reg_params[i]);
+
+err_write_code:
+       target_free_working_area(bank->target, workarea);
+
+err_alloc_code:
+
+       return retval;
+}
+
+/**
+ * Can't protect/unprotect pages on etacorem3.
+ * @param bank
+ * @param set
+ * @param first
+ * @param last
+ * @returns
+ */
+static int etacorem3_protect(struct flash_bank *bank, int set, int first, int 
last)
+{
+       /*
+        * Can't protect/unprotect on the etacorem3.
+        * Initialized to unprotected.
+        */
+       LOG_WARNING("Cannot protect/unprotect.");
+       return ERROR_OK;
+}
+
+/**
+ * Sectors are always unprotected.
+ * @param bank
+ * @returns
+ *
+ */
+static int etacorem3_protect_check(struct flash_bank *bank)
+{
+       /*
+       * sectors are always unprotected.
+       * set at initialization.
+       */
+       return ERROR_OK;
+}
+/**
+ * Probe flash part, and build sector list.
+ * name: etacorem3_probe
+ * @param bank Pointer to the flash bank descriptor.
+ * @return on success: ERROR_OK
+ *
+ */
+static int etacorem3_probe(struct flash_bank *bank)
+{
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+
+       if (etacorem3_bank->probed)
+               return ERROR_OK;
+       else
+               LOG_DEBUG("Probing part.");
+
+       /* Load extra info. */
+       etacorem3_bank->jedec = get_jedec_pid03(bank);
+       if (etacorem3_bank->jedec == 0)
+               LOG_WARNING("Could not read PID");
+       LOG_DEBUG("ROM PID[0-3]: 0x%08" PRIx32, etacorem3_bank->jedec);
+
+       /* sets default value for case statement. */
+       set_variant(bank);
+       LOG_DEBUG("variant: %" PRId32 ".", (int)etacorem3_bank->variant);
+
+       switch (etacorem3_bank->variant) {
+               case etacore_m3eta:
+                       etacorem3_bank->target_name = etacorePartnames[0];
+                       etacorem3_bank->num_pages = 0;
+                       etacorem3_bank->pagesize = 0;
+                       etacorem3_bank->magic_address = MAGIC_ADDR_M3ETA;
+                       etacorem3_bank->sram_base = ETA_COMMON_SRAM_BASE_M3ETA;
+                       etacorem3_bank->sram_size = ETA_COMMON_SRAM_SIZE_M3ETA;
+                       etacorem3_bank->sram_max = ETA_COMMON_SRAM_SIZE_MAX;
+                       etacorem3_bank->flash_base = 0;
+                       etacorem3_bank->flash_size = 0;
+                       etacorem3_bank->flash_max = ETA_COMMON_FLASH_SIZE_MAX;
+                       etacorem3_bank->bootrom_erase_entry = 0;
+                       etacorem3_bank->bootrom_write_entry = 0;
+                       break;
+               case etacore_subzero:
+                       etacorem3_bank->target_name = etacorePartnames[1];
+                       etacorem3_bank->num_pages = 
ETA_COMMON_FLASH_NUM_PAGES_SUBZ;
+                       etacorem3_bank->pagesize = 
ETA_COMMON_FLASH_PAGE_SIZE_SUBZ;
+                       etacorem3_bank->magic_address = MAGIC_ADDR_SUBZ;
+                       etacorem3_bank->sram_base = ETA_COMMON_SRAM_BASE_SUBZ;
+                       etacorem3_bank->sram_size = ETA_COMMON_SRAM_SIZE_SUBZ;
+                       etacorem3_bank->sram_max = ETA_COMMON_SRAM_SIZE_MAX;
+                       etacorem3_bank->flash_base = ETA_COMMON_FLASH_BASE_SUBZ;
+                       etacorem3_bank->flash_size = ETA_COMMON_FLASH_SIZE_SUBZ;
+                       etacorem3_bank->flash_max = ETA_COMMON_FLASH_SIZE_MAX;
+                       if (etacorem3_bank->fpga) {
+                               etacorem3_bank->bootrom_erase_entry = 
BootROM_flash_erase_fpga;
+                               etacorem3_bank->bootrom_write_entry = 
BootROM_flash_program_fpga;
+                       } else {
+                               etacorem3_bank->bootrom_erase_entry = 
BootROM_flash_erase_board;
+                               etacorem3_bank->bootrom_write_entry = 
BootROM_flash_program_board;
+                       }
+                       break;
+               /* default: leave everything initialized to 0 (calloc). */
+               case etacore_unknown:
+               default:
+                       etacorem3_bank->target_name = 
ARRAY_LAST(etacorePartnames);
+                       LOG_ERROR("Unknown target %" PRId32 ".", 
etacorem3_bank->variant);
+                       break;
+       }
+
+       etacorem3_bank->sram_size  = get_memory_size(bank,
+                       etacorem3_bank->sram_base,
+                       etacorem3_bank->sram_max,
+                       (32*1024));
+       etacorem3_bank->flash_size = get_memory_size(bank,
+                       etacorem3_bank->flash_base,
+                       etacorem3_bank->flash_max,
+                       (32*1024));
+
+
+       /* provide this for the benefit of the NOR flash framework */
+       bank->base = (bank->bank_number * etacorem3_bank->flash_size) + \
+               etacorem3_bank->flash_base;
+       bank->size = etacorem3_bank->pagesize * etacorem3_bank->num_pages;
+       bank->num_sectors = etacorem3_bank->num_pages;
+
+       LOG_DEBUG("bank number: %" PRId32 ", base: 0x%08" PRIx32
+               ", size: %" PRId32 " KB, num sectors: %" PRId32 ".",
+               bank->bank_number,
+               bank->base,
+               bank->size/1024,
+               bank->num_sectors);
+
+       if (bank->sectors) {
+               free(bank->sectors);
+               bank->sectors = NULL;
+       }
+
+       bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
+       for (int i = 0; i < bank->num_sectors; i++) {
+               bank->sectors[i].offset = i * etacorem3_bank->pagesize;
+               bank->sectors[i].size = etacorem3_bank->pagesize;
+               bank->sectors[i].is_erased = -1;
+               /* No flash protect in this hardware. */
+               bank->sectors[i].is_protected = 0;
+       }
+
+       etacorem3_bank->probed = true;
+       return ERROR_OK;
+}
+
+static int emcorem3_auto_probe(struct flash_bank *bank)
+{
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+
+       if (etacorem3_bank->probed)
+               return ERROR_OK;
+
+       return etacorem3_probe(bank);
+}
+
+
+/**
+ * Display ETA chip info from probe.
+ * @param bank
+ * @param buf Buffer to be printed.
+ * @param buf_size Size of buffer.
+ * @returns success
+ */
+static int get_etacorem3_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+       struct etacorem3_flash_bank *etacorem3_bank = bank->driver_priv;
+
+       TARGET_PROBED(etacorem3_bank);
+
+       int printed = snprintf(buf,
+                       buf_size,
+                       "\nETA Compute %s Partnum %" PRIu32 ".%" PRIu32 ". %s"
+                       "\n\tTotal Flash: %" PRIu32 " KB, Sram: %" PRIu32 " KB."
+                       "\n\tStart Flash: 0x%08" PRIx32 ", Sram: 0x%08" PRIx32 
".",
+                       etacorem3_bank->target_name,
+                       (etacorem3_bank->jedec & 0x7FF),/* 11 bits. */
+                       ((etacorem3_bank->jedec & 0x00F00000)>>20),
+                       (etacorem3_bank->fpga ? "FPGA" : ""),
+                       (etacorem3_bank->flash_size/1024),
+                       (etacorem3_bank->sram_size/1024)
+                       ,
+                       etacorem3_bank->flash_base,
+                       etacorem3_bank->sram_base
+                       );
+
+       if (printed < 0)
+               return ERROR_BUF_TOO_SMALL;
+       return ERROR_OK;
+}
+
+/*
+ * openocd command interface
+ */
+
+/**
+ * Match group of case independant patterns starting with "s".
+ * @param s Prefix to match
+ * @param pattern Pattern to match.
+ * @returns true if match.
+ */
+static bool name_match(const char *s, const char *pattern)
+{
+       int i = 0;
+
+       /* Always returns true if null, as match string is shorter... */
+       if (s == NULL || s[0] == '\0') {
+               if (pattern == NULL || pattern[0] == '\0')
+                       return true;
+               else
+                       return false;
+       }
+
+       while (s[i]) {
+               /* If the match string is shorter, ignore excess */
+               if (!pattern[i])
+                       return true;
+               /* Use x as wildcard */
+               if (pattern[i] != 'x' && tolower(s[i]) != tolower(pattern[i]))
+                       return false;
+               i++;
+       }
+       LOG_DEBUG("Matched %s in %" PRId32 " characters.", pattern, i);
+       return true;
+}
+
+/**
+ * Initialize etacorem3 bank info.
+ * @returns success
+ *
+ * From target cfg file.
+ * @code
+ * flash_bank etacorem3 <base> <size> 0 0 <target#> [variant]
+ * @endcode
+ */
+FLASH_BANK_COMMAND_HANDLER(etacorem3_flash_bank_command)
+{
+       struct etacorem3_flash_bank *etacorem3_bank;
+       const char *variant = NULL;
+
+       if (CMD_ARGC < 6)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (CMD_ARGC == 7)
+               variant = CMD_ARGV[6];
+
+       etacorem3_bank = calloc(1, sizeof(*etacorem3_bank));
+       if (!etacorem3_bank)
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       etacorem3_bank->fpga = false;
+       if (name_match(variant, "FPGA"))
+               etacorem3_bank->fpga = true;
+
+       /* do this before get_jedec_pid03 */
+       bank->driver_priv = etacorem3_bank;
+
+       /* Try to read pid early. */
+       etacorem3_bank->jedec = get_jedec_pid03(bank);
+       /*
+        * ASSUMPTION: Change when there are more bootrom versions.
+        * workaround for times we cannot read PID.
+        */
+       if ((etacorem3_bank->jedec == 0) && (etacorem3_bank->fpga))
+               etacorem3_bank->jedec = PID_SUBZERO;
+
+       etacorem3_bank->probed = false;
+
+       return ERROR_OK;
+}
+
+/**
+ * Handle external mass erase command.
+ * @returns ERROR_COMMAND_SYNTAX_ERROR or ERROR_OK.
+ */
+COMMAND_HANDLER(etacorem3_handle_mass_erase_command)
+{
+
+       if (CMD_ARGC < 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       struct flash_bank *bank;
+       uint32_t retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, 
&bank);
+       if (ERROR_OK != retval)
+               return retval;
+
+       if (etacorem3_mass_erase(bank) == ERROR_OK) {
+               /* set all sectors as erased */
+               for (int i = 0; i < bank->num_sectors; i++)
+                       bank->sectors[i].is_erased = 1;
+
+               command_print(CMD_CTX, "etacorem3 mass erase complete");
+       } else
+               command_print(CMD_CTX, "etacorem3 mass erase failed");
+
+       return ERROR_OK;
+}
+
+
+/**
+ * Register exec commands, extensions to standard OCD commands.
+ * Use this for additional commands specific to this target.
+ * (i.e. Commands for automation, validation, or production)
+ */
+static const struct command_registration etacorem3_exec_command_handlers[] = {
+       {
+               .name = "mass_erase",
+               .usage = "<bank>",
+               .handler = etacorem3_handle_mass_erase_command,
+               .mode = COMMAND_EXEC,
+               .help = "Erase entire device",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+/**
+ * Register required commands and chain to optional exec commands.
+ */
+static const struct command_registration etacorem3_command_handlers[] = {
+       {
+               .name = "etacorem3",
+               .mode = COMMAND_EXEC,
+               .help = "etacorem3 flash command group",
+               .usage = "Support for ETA Compute ecm35xx parts.",
+               .chain = etacorem3_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+/**
+ * Required OpenOCD flash driver commands.
+ */
+struct flash_driver etacorem3_flash = {
+       .name = "etacorem3",
+       .commands = etacorem3_command_handlers,
+       .flash_bank_command = etacorem3_flash_bank_command,
+       .erase = etacorem3_erase,
+       .protect = etacorem3_protect,
+       .write = etacorem3_write,
+       .read = default_flash_read,
+       .probe = etacorem3_probe,
+       .auto_probe = emcorem3_auto_probe,
+       .erase_check = default_flash_blank_check,
+       .protect_check = etacorem3_protect_check,
+       .info = get_etacorem3_info,
+};

-- 

------------------------------------------------------------------------------
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