flash: add stellaris async flash loader
authorSpencer Oliver <spen@spen-soft.co.uk>
Fri, 10 Feb 2012 15:27:27 +0000 (15:27 +0000)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sun, 26 Feb 2012 00:46:48 +0000 (00:46 +0000)
This enable the Stellaris flash driver to use the asynchronous
algorithm support.

Speed increase is as follows:
before - wrote 65536 bytes from file test.bin in 5.486040s (11.666 KiB/s)
after - wrote 65536 bytes from file test.bin in 2.274001s (28.144 KiB/s)

Change-Id: I9004c9aadffa1ae3b0cbf908e6549b5b1f794508
Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk>
Reviewed-on: http://openocd.zylin.com/403
Tested-by: jenkins
Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
contrib/loaders/flash/stellaris.s
src/flash/nor/stellaris.c

index 166dd52ac8eab8bb71fc31bac2ac62f28780e0b5..42494938893d41bffbbe4bcba10349a5a8563f41 100644 (file)
        .cpu cortex-m3
        .thumb
        .thumb_func
-       .align  2
 
 /*
-       Call with :     
-       r0 = buffer address
-       r1 = destination address
-       r2 = bytecount (in) - endaddr (work) 
-       
-       Used registers: 
-       r3 = pFLASH_CTRL_BASE
-       r4 = FLASHWRITECMD
-       r5 = #1
-       r6 = bytes written
-       r7 = temp reg
-*/
+ * Params :
+ * r0 = workarea start
+ * r1 = workarea end
+ * r2 = target address
+ * r3 = count (32bit words)
+ *
+ * Clobbered:
+ * r4 = pFLASH_CTRL_BASE
+ * r5 = FLASHWRITECMD
+ * r7 - rp
+ * r8 - wp, tmp
+ */
 
 write:
-       ldr     r3,pFLASH_CTRL_BASE
-       ldr     r4,FLASHWRITECMD
-       movs    r5, 1
-       movs    r6, #0
+       ldr     r4, pFLASH_CTRL_BASE
+       ldr     r5, FLASHWRITECMD
+
+wait_fifo:
+       ldr     r8, [r0, #0]    /* read wp */
+       cmp     r8, #0                  /* abort if wp == 0 */
+       beq     exit
+       ldr     r7, [r0, #4]    /* read rp */
+       cmp     r7, r8                  /* wait until rp != wp */
+       beq     wait_fifo
+
 mainloop:
-       str             r1, [r3, #0]
-       ldr             r7, [r0, r6]
-       str             r7, [r3, #4]
-       str             r4, [r3, #8]
-waitloop:
-       ldr             r7, [r3, #8]
-       tst             r7, r5
-       bne             waitloop
-       adds    r1, r1, #4
-       adds    r6, r6, #4
-       cmp             r6, r2
-       bne             mainloop
-       bkpt    #0
+       str             r2, [r4, #0]    /* FMA - write address */
+       add             r2, r2, #4              /* increment target address */
+       ldr             r8, [r7], #4
+       str             r8, [r4, #4]    /* FMD - write data */
+       str             r5, [r4, #8]    /* FMC - enable write */
+busy:
+       ldr             r8, [r4, #8]
+       tst             r8, #1
+       bne             busy
+
+       cmp     r7, r1                  /* wrap rp at end of buffer */
+       it      cs
+       addcs   r7, r0, #8              /* skip loader args */
+       str     r7, [r0, #4]    /* store rp */
+       subs    r3, r3, #1              /* decrement word count */
+       cbz     r3, exit                /* loop if not done */
+       b               wait_fifo
+exit:
+       bkpt    #0
 
 pFLASH_CTRL_BASE: .word 0x400FD000
 FLASHWRITECMD: .word 0xA4420001
index 712077da233d35c9f20818b35961c3688d3e7d93..0c4169c7f9f5f9860a5742b2cc9bfc722ffdc98b 100644 (file)
@@ -958,43 +958,41 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
 /* see contib/loaders/flash/stellaris.s for src */
 
 static const uint8_t stellaris_write_code[] = {
-/*
-       Call with :
-       r0 = buffer address
-       r1 = destination address
-       r2 = bytecount (in) - endaddr (work)
-
-       Used registers:
-       r3 = pFLASH_CTRL_BASE
-       r4 = FLASHWRITECMD
-       r5 = #1
-       r6 = bytes written
-       r7 = temp reg
-*/
-       0x07, 0x4B,                     /* ldr r3,pFLASH_CTRL_BASE */
-       0x08, 0x4C,                     /* ldr r4,FLASHWRITECMD */
-       0x01, 0x25,                     /* movs r5, 1 */
-       0x00, 0x26,                     /* movs r6, #0 */
-/* mainloop: */
-       0x19, 0x60,                     /* str  r1, [r3, #0] */
-       0x87, 0x59,                     /* ldr  r7, [r0, r6] */
-       0x5F, 0x60,                     /* str  r7, [r3, #4] */
-       0x9C, 0x60,                     /* str  r4, [r3, #8] */
-/* waitloop: */
-       0x9F, 0x68,                     /* ldr  r7, [r3, #8] */
-       0x2F, 0x42,                     /* tst  r7, r5 */
-       0xFC, 0xD1,                     /* bne  waitloop */
-       0x04, 0x31,                     /* adds r1, r1, #4 */
-       0x04, 0x36,                     /* adds r6, r6, #4 */
-       0x96, 0x42,                     /* cmp  r6, r2 */
-       0xF4, 0xD1,                     /* bne  mainloop */
-       0x00, 0xBE,                     /* bkpt #0 */
-/* pFLASH_CTRL_BASE: */
+                                                               /* write: */
+       0xDF, 0xF8, 0x40, 0x40,         /* ldr          r4, pFLASH_CTRL_BASE */
+       0xDF, 0xF8, 0x40, 0x50,         /* ldr          r5, FLASHWRITECMD */
+                                                               /* wait_fifo: */
+       0xD0, 0xF8, 0x00, 0x80,         /* ldr          r8, [r0, #0] */
+       0xB8, 0xF1, 0x00, 0x0F,         /* cmp          r8, #0 */
+       0x17, 0xD0,                                     /* beq          exit */
+       0x47, 0x68,                                     /* ldr          r7, [r0, #4] */
+       0x47, 0x45,                                     /* cmp          r7, r8 */
+       0xF7, 0xD0,                                     /* beq          wait_fifo */
+                                                               /* mainloop: */
+       0x22, 0x60,                                     /* str          r2, [r4, #0] */
+       0x02, 0xF1, 0x04, 0x02,         /* add          r2, r2, #4 */
+       0x57, 0xF8, 0x04, 0x8B,         /* ldr          r8, [r7], #4 */
+       0xC4, 0xF8, 0x04, 0x80,         /* str          r8, [r4, #4] */
+       0xA5, 0x60,                                     /* str          r5, [r4, #8] */
+                                                               /* busy: */
+       0xD4, 0xF8, 0x08, 0x80,         /* ldr          r8, [r4, #8] */
+       0x18, 0xF0, 0x01, 0x0F,         /* tst          r8, #1 */
+       0xFA, 0xD1,                                     /* bne          busy */
+       0x8F, 0x42,                                     /* cmp          r7, r1 */
+       0x28, 0xBF,                                     /* it           cs */
+       0x00, 0xF1, 0x08, 0x07,         /* addcs        r7, r0, #8 */
+       0x47, 0x60,                                     /* str          r7, [r0, #4] */
+       0x01, 0x3B,                                     /* subs         r3, r3, #1 */
+       0x03, 0xB1,                                     /* cbz          r3, exit */
+       0xE2, 0xE7,                                     /* b            wait_fifo */
+                                                               /* exit: */
+       0x00, 0xBE,                                     /* bkpt         #0 */
+
+       /* pFLASH_CTRL_BASE: */
        0x00, 0xD0, 0x0F, 0x40, /* .word        0x400FD000 */
-/* FLASHWRITECMD: */
+       /* FLASHWRITECMD: */
        0x01, 0x00, 0x42, 0xA4  /* .word        0xA4420001 */
 };
-
 static int stellaris_write_block(struct flash_bank *bank,
                uint8_t *buffer, uint32_t offset, uint32_t wcount)
 {
@@ -1003,7 +1001,7 @@ static int stellaris_write_block(struct flash_bank *bank,
        struct working_area *source;
        struct working_area *write_algorithm;
        uint32_t address = bank->base + offset;
-       struct reg_param reg_params[3];
+       struct reg_param reg_params[4];
        struct armv7m_algorithm armv7m_info;
        int retval = ERROR_OK;
 
@@ -1032,7 +1030,8 @@ static int stellaris_write_block(struct flash_bank *bank,
        while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
                buffer_size /= 2;
                if (buffer_size <= buf_min) {
-                       target_free_working_area(target, write_algorithm);
+                       if (write_algorithm)
+                               target_free_working_area(target, write_algorithm);
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
                LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
@@ -1049,39 +1048,22 @@ static int stellaris_write_block(struct flash_bank *bank,
        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);
 
-       while (wcount > 0) {
-               uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
-
-               target_write_buffer(target, source->address, thisrun_count * 4, buffer);
-
-               buf_set_u32(reg_params[0].value, 0, 32, source->address);
-               buf_set_u32(reg_params[1].value, 0, 32, address);
-               buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
-               LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32
-                               ", %u remaining",
-                               (unsigned) thisrun_count, address,
-                               (unsigned) (wcount - thisrun_count));
-               retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
-                               write_algorithm->address,
-                               0,
-                               10000, &armv7m_info);
-               if (retval != ERROR_OK) {
-                       LOG_ERROR("error %d executing stellaris "
-                                       "flash write algorithm",
-                                       retval);
-                       retval = ERROR_FLASH_OPERATION_FAILED;
-                       break;
-               }
+       buf_set_u32(reg_params[0].value, 0, 32, source->address);
+       buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
+       buf_set_u32(reg_params[2].value, 0, 32, address);
+       buf_set_u32(reg_params[3].value, 0, 32, wcount);
 
-               buffer += thisrun_count * 4;
-               address += thisrun_count * 4;
-               wcount -= thisrun_count;
-       }
+       retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
+                       0, NULL,
+                       4, reg_params,
+                       source->address, source->size,
+                       write_algorithm->address, 0,
+                       &armv7m_info);
 
-       /* REVISIT we could speed up writing multi-section images by
-        * not freeing the initialized write_algorithm this way.
-        */
+       if (retval == ERROR_FLASH_OPERATION_FAILED)
+               LOG_ERROR("error %d executing stellaris flash write algorithm", retval);
 
        target_free_working_area(target, write_algorithm);
        target_free_working_area(target, source);
@@ -1089,6 +1071,7 @@ static int stellaris_write_block(struct flash_bank *bank,
        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;
 }

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)