Added SPIFI flash driver, algorithms, and docs
[openocd.git] / contrib / loaders / flash / lpcspifi_erase.S
diff --git a/contrib/loaders/flash/lpcspifi_erase.S b/contrib/loaders/flash/lpcspifi_erase.S
new file mode 100644 (file)
index 0000000..219f645
--- /dev/null
@@ -0,0 +1,176 @@
+/***************************************************************************
+ *   Copyright (C) 2012 by George Harris                                   *
+ *   george@luminairecoffee.com                                            *
+ *                                                                         *
+ *   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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+       .text
+       .syntax unified
+       .cpu cortex-m3
+       .thumb
+       .thumb_func
+
+/*
+ * Params :
+ * r0 = start address, status (out)
+ * r1 = count
+ * r2 = erase command
+ * r3 = block size
+ */
+
+#define SSP_BASE_HIGH                          0x4008
+#define SSP_BASE_LOW                           0x3000
+#define SSP_CR0_OFFSET                         0x00
+#define SSP_CR1_OFFSET                         0x04
+#define SSP_DATA_OFFSET                        0x08
+#define SSP_CPSR_OFFSET                        0x10
+#define SSP_SR_OFFSET                          0x0c
+
+#define SSP_CLOCK_BASE_HIGH            0x4005
+#define SSP_CLOCK_BASE_LOW                     0x0000
+#define SSP_BRANCH_CLOCK_BASE_HIGH     0x4005
+#define SSP_BRANCH_CLOCK_BASE_LOW      0x2000
+#define SSP_BASE_CLOCK_OFFSET          0x94
+#define SSP_BRANCH_CLOCK_OFFSET                0x700
+
+#define IOCONFIG_BASE_HIGH                     0x4008
+#define IOCONFIG_BASE_LOW                      0x6000
+#define IOCONFIG_SCK_OFFSET                    0x18c
+#define IOCONFIG_HOLD_OFFSET           0x190
+#define IOCONFIG_WP_OFFSET                     0x194
+#define IOCONFIG_MISO_OFFSET           0x198
+#define IOCONFIG_MOSI_OFFSET           0x19c
+#define IOCONFIG_CS_OFFSET                     0x1a0
+
+#define IO_BASE_HIGH                           0x400f
+#define IO_BASE_LOW                            0x4000
+#define IO_CS_OFFSET                           0xab
+#define IODIR_BASE_HIGH                        0x400f
+#define IODIR_BASE_LOW                         0x6000
+#define IO_CS_DIR_OFFSET                       0x14
+
+
+setup: /* Initialize SSP pins and module */
+       mov.w   r10, #IOCONFIG_BASE_LOW
+       movt    r10, #IOCONFIG_BASE_HIGH
+       mov.w   r8, #0xea
+       str.w   r8, [r10, #IOCONFIG_SCK_OFFSET]         /* Configure SCK pin function */
+       mov.w   r8, #0x40
+       str.w   r8, [r10, #IOCONFIG_HOLD_OFFSET]        /* Configure /HOLD pin function */
+       mov.w   r8, #0x40
+       str.w   r8, [r10, #IOCONFIG_WP_OFFSET]          /* Configure /WP pin function */
+       mov.w   r8, #0xed
+       str.w   r8, [r10, #IOCONFIG_MISO_OFFSET]        /* Configure MISO pin function */
+       mov.w   r8, #0xed
+       str.w   r8, [r10, #IOCONFIG_MOSI_OFFSET]        /* Configure MOSI pin function */
+       mov.w   r8, #0x44
+       str.w   r8, [r10, #IOCONFIG_CS_OFFSET]          /* Configure CS pin function */
+
+       mov.w   r10, #IODIR_BASE_LOW
+       movt    r10, #IODIR_BASE_HIGH
+       mov.w   r8, #0x800
+       str     r8, [r10, #IO_CS_DIR_OFFSET]            /* Set CS as output */
+       mov.w   r10, #IO_BASE_LOW
+       movt    r10, #IO_BASE_HIGH
+       mov.w   r8, #0xff
+       str.w   r8, [r10, #IO_CS_OFFSET]                        /* Set CS high */
+
+       mov.w   r10, #SSP_CLOCK_BASE_LOW
+       movt    r10, #SSP_CLOCK_BASE_HIGH
+       mov.w   r8, #0x0000
+       movt    r8, #0x0100
+       str.w   r8, [r10, #SSP_BASE_CLOCK_OFFSET]       /* Configure SSP0 base clock (use 12 MHz IRC) */
+
+       mov.w   r10, #SSP_BRANCH_CLOCK_BASE_LOW
+       movt    r10, #SSP_BRANCH_CLOCK_BASE_HIGH
+       mov.w   r8, #0x01
+       str.w   r8, [r10, #SSP_BRANCH_CLOCK_OFFSET] /* Configure (enable) SSP0 branch clock */
+
+       mov.w   r10, #SSP_BASE_LOW
+       movt    r10, #SSP_BASE_HIGH
+       mov.w   r8, #0x07
+       str.w   r8, [r10, #SSP_CR0_OFFSET]                      /* Set clock postscale */
+       mov.w   r8, #0x02
+       str.w   r8, [r10, #SSP_CPSR_OFFSET]             /* Set clock prescale */
+       str.w   r8, [r10, #SSP_CR1_OFFSET]                      /* Enable SSP in SPI mode */
+write_enable:
+       bl              cs_down
+       mov.w   r9, #0x06               /* Send the write enable command */
+       bl              write_data
+       bl              cs_up
+
+       bl              cs_down
+       mov.w   r9, #0x05               /* Get status register */
+       bl              write_data
+       mov.w   r9, #0x00               /* Dummy data to clock in status */
+       bl              write_data
+       bl              cs_up
+
+       tst     r9, #0x02               /* If the WE bit isn't set, we have a problem. */
+       beq     error
+erase:
+       bl              cs_down
+       mov.w   r9, r2                  /* Send the erase command */
+       bl              write_data
+write_address:
+       lsr     r9, r0, #16     /* Send the current 24-bit write address, MSB first */
+       bl              write_data
+       lsr     r9, r0, #8
+       bl              write_data
+       mov.w   r9, r0
+       bl              write_data
+       bl              cs_up
+wait_flash_busy:                       /* Wait for the flash to finish the previous erase */
+       bl              cs_down
+       mov.w   r9, #0x05               /* Get status register */
+       bl              write_data
+       mov.w   r9, #0x00               /* Dummy data to clock in status */
+       bl              write_data
+       bl              cs_up
+       tst     r9, #0x01               /* If it isn't done, keep waiting */
+       bne     wait_flash_busy
+
+       subs    r1, r1, #1                                      /* decrement count */
+       cbz             r1, exit                                        /* Exit if we have written everything */
+       add     r0, r3                                          /* Move the address up by the block size */
+       b               write_enable                            /* Start a new block erase */
+write_data:                                                    /* Send/receive 1 byte of data over SSP */
+       mov.w   r10, #SSP_BASE_LOW
+       movt    r10, #SSP_BASE_HIGH
+       str.w   r9, [r10, #SSP_DATA_OFFSET]     /* Write supplied data to the SSP data reg */
+wait_transmit:
+       ldr     r9, [r10, #SSP_SR_OFFSET]       /* Check SSP status */
+       tst     r9, #0x0010                                     /* Check if BSY bit is set */
+       bne     wait_transmit                           /* If still transmitting, keep waiting */
+       ldr     r9, [r10, #SSP_DATA_OFFSET]     /* Load received data */
+       bx              lr                                                      /* Exit subroutine */
+cs_up:
+       mov.w   r8, #0xff
+       b               cs_write
+cs_down:
+       mov.w   r8, #0x0000
+cs_write:
+       mov.w   r10, #IO_BASE_LOW
+       movt    r10, #IO_BASE_HIGH
+       str.w   r8, [r10, #IO_CS_OFFSET]
+       bx              lr
+error:
+       movs    r0, #0
+exit:
+       bkpt    #0x00
+
+       .end

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)