From 90cee3569611faabea6c9697836b4a75c7288832 Mon Sep 17 00:00:00 2001 From: Spencer Oliver Date: Fri, 10 Feb 2012 15:27:27 +0000 Subject: [PATCH] flash: add stellaris async flash loader 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 Reviewed-on: http://openocd.zylin.com/403 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- contrib/loaders/flash/stellaris.s | 72 +++++++++++-------- src/flash/nor/stellaris.c | 113 +++++++++++++----------------- 2 files changed, 90 insertions(+), 95 deletions(-) diff --git a/contrib/loaders/flash/stellaris.s b/contrib/loaders/flash/stellaris.s index 166dd52ac..424949388 100644 --- a/contrib/loaders/flash/stellaris.s +++ b/contrib/loaders/flash/stellaris.s @@ -26,41 +26,53 @@ .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 diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index 712077da2..0c4169c7f 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -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) + /* 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 */ - 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: */ + /* 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(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); - while (wcount > 0) { - uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount; + 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); - target_write_buffer(target, source->address, thisrun_count * 4, buffer); + 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); - 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; - } - - buffer += thisrun_count * 4; - address += thisrun_count * 4; - wcount -= thisrun_count; - } - - /* 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(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); return retval; }