From 22b4a0f40da200563a32e5bab86aceecf486ddd3 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 22 Jul 2016 13:19:19 +0200 Subject: [PATCH] flash Kinetis: longword programming changed to flash_async_algorithm Change-Id: I9c40acfad37760c3dab454f2432817b2d420792d Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3563 Reviewed-by: Steven Stallion Tested-by: jenkins Reviewed-by: Freddie Chopin --- contrib/loaders/flash/kinetis/Makefile | 19 +++ .../loaders/flash/kinetis/kinetis_flash.inc | 6 + contrib/loaders/flash/kinetis/kinetis_flash.s | 101 ++++++++++++++ src/flash/nor/kinetis.c | 131 +++++------------- 4 files changed, 161 insertions(+), 96 deletions(-) create mode 100644 contrib/loaders/flash/kinetis/Makefile create mode 100644 contrib/loaders/flash/kinetis/kinetis_flash.inc create mode 100644 contrib/loaders/flash/kinetis/kinetis_flash.s diff --git a/contrib/loaders/flash/kinetis/Makefile b/contrib/loaders/flash/kinetis/Makefile new file mode 100644 index 0000000000..b240f53d44 --- /dev/null +++ b/contrib/loaders/flash/kinetis/Makefile @@ -0,0 +1,19 @@ +BIN2C = ../../../../src/helper/bin2char.sh + +CROSS_COMPILE ?= arm-none-eabi- +AS = $(CROSS_COMPILE)as +OBJCOPY = $(CROSS_COMPILE)objcopy + +all: kinetis_flash.inc + +%.elf: %.s + $(AS) $< -o $@ + +%.bin: %.elf + $(OBJCOPY) -Obinary $< $@ + +%.inc: %.bin + $(BIN2C) < $< > $@ + +clean: + -rm -f *.elf *.bin *.inc diff --git a/contrib/loaders/flash/kinetis/kinetis_flash.inc b/contrib/loaders/flash/kinetis/kinetis_flash.inc new file mode 100644 index 0000000000..c93797b7b9 --- /dev/null +++ b/contrib/loaders/flash/kinetis/kinetis_flash.inc @@ -0,0 +1,6 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x16,0x68,0x00,0x2e,0x1f,0xd0,0x55,0x68,0xb5,0x42,0xf9,0xd0,0x60,0x60,0x06,0x27, +0xe7,0x71,0x2f,0x68,0xa7,0x60,0x80,0x27,0x27,0x70,0x04,0x35,0x9d,0x42,0x01,0xd3, +0x15,0x1c,0x08,0x35,0x55,0x60,0x16,0x68,0x00,0x2e,0x0c,0xd0,0x26,0x78,0x3e,0x42, +0xf9,0xd0,0x70,0x27,0x3e,0x42,0x04,0xd1,0x04,0x30,0x01,0x39,0x00,0x29,0xdf,0xd1, +0x01,0xe0,0x00,0x25,0x55,0x60,0x00,0xbe, diff --git a/contrib/loaders/flash/kinetis/kinetis_flash.s b/contrib/loaders/flash/kinetis/kinetis_flash.s new file mode 100644 index 0000000000..c8e6e05a89 --- /dev/null +++ b/contrib/loaders/flash/kinetis/kinetis_flash.s @@ -0,0 +1,101 @@ +/*************************************************************************** + * Copyright (C) 2015 by Ivan Meleca * + * ivan@artekit.eu * + * * + * Copyright (C) 2016 by Tomas Vanek * + * vanekt@fbl.cz * + * * + * 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. * + ***************************************************************************/ + + /* Params: + * r0 = flash destination address in/out + * r1 = longword count + * r2 = workarea start address + * r3 = workarea end address + * r4 = FTFx base + */ + + .text + .cpu cortex-m0plus + .code 16 + .thumb_func + + .align 2 + + /* r5 = rp + * r6 = wp, tmp + * r7 = tmp + */ + + /* old longword algo: 6.680 KiB/s @ adapter_khz 2000 + * this async algo: 19.808 KiB/s @ adapter_khz 2000 + */ + +FTFx_FSTAT = 0 +FTFx_FCCOB3 = 4 +FTFx_FCCOB0 = 7 +FTFx_FCCOB7 = 8 + +wait_fifo: + ldr r6, [r2, #0] /* read wp */ + cmp r6, #0 /* abort if wp == 0 */ + beq exit + + ldr r5, [r2, #4] /* read rp */ + cmp r5, r6 /* wait until rp != wp */ + beq wait_fifo + + str r0, [r4, #FTFx_FCCOB3] /* set flash address */ + mov r7, #6 + strb r7, [r4, #FTFx_FCCOB0] /* flash command */ + + ldr r7, [r5] /* set longword data = *rp */ + str r7, [r4, #FTFx_FCCOB7] + + mov r7, #128 + strb r7, [r4, #FTFx_FSTAT] + + add r5, #4 /* rp += 4 */ + cmp r5, r3 /* Wrap? */ + bcc no_wrap + mov r5, r2 + add r5, #8 + +no_wrap: + str r5, [r2, #4] /* Store rp */ + +wait_ccif: + ldr r6, [r2, #0] /* read wp */ + cmp r6, #0 /* abort if wp == 0 */ + beq exit + + ldrb r6, [r4, #FTFx_FSTAT] + tst r6, r7 + beq wait_ccif + + mov r7, #0x70 + tst r6, r7 + bne error + + add r0, #4 /* flash address += 4, do not increment before err check */ + + sub r1, #1 /* word_count-- */ + cmp r1, #0 + bne wait_fifo + b exit + +error: + mov r5, #0 + str r5, [r2, #4] /* set rp = 0 on error */ + +exit: + bkpt #0 diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 2e34bcb71c..b640b3f637 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -865,65 +865,7 @@ static int kinetis_ftfx_prepare(struct target *target) /* Kinetis Program-LongWord Microcodes */ static const uint8_t kinetis_flash_write_code[] = { - /* Params: - * r0 - workarea buffer - * r1 - target address - * r2 - wordcount - * Clobbered: - * r4 - tmp - * r5 - tmp - * r6 - tmp - * r7 - tmp - */ - - /* .L1: */ - /* for(register uint32_t i=0;idriver_priv; uint32_t address = kinfo->prog_base + offset; - struct reg_param reg_params[3]; + uint32_t end_address; + struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; - int retval = ERROR_OK; - - /* Params: - * r0 - workarea buffer - * r1 - target address - * r2 - wordcount - * Clobbered: - * r4 - tmp - * r5 - tmp - * r6 - tmp - * r7 - tmp - */ + int retval; + uint8_t fstat; /* Increase buffer_size if needed */ if (buffer_size < (target->working_area_size/2)) @@ -982,35 +915,39 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; - init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */ - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* faddr */ - init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of words to program */ + init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* address */ + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* word count */ + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); + init_reg_param(®_params[4], "r4", 32, PARAM_OUT); - /* write code buffer and use Flash programming code within kinetis */ - /* Set breakpoint to 0 with time-out of 1000 ms */ - while (wcount > 0) { - uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount; + buf_set_u32(reg_params[0].value, 0, 32, address); + buf_set_u32(reg_params[1].value, 0, 32, wcount); + buf_set_u32(reg_params[2].value, 0, 32, source->address); + buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); + buf_set_u32(reg_params[4].value, 0, 32, FTFx_FSTAT); - retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer); - if (retval != ERROR_OK) - break; + retval = target_run_flash_async_algorithm(target, buffer, wcount, 4, + 0, NULL, + 5, 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, thisrun_count); + if (retval == ERROR_FLASH_OPERATION_FAILED) { + end_address = buf_get_u32(reg_params[0].value, 0, 32); - retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - write_algorithm->address, 0, 100000, &armv7m_info); - if (retval != ERROR_OK) { - LOG_ERROR("Error executing kinetis Flash programming algorithm"); - retval = ERROR_FLASH_OPERATION_FAILED; - break; - } + LOG_ERROR("Error writing flash at %08" PRIx32, end_address); - buffer += thisrun_count * 4; - address += thisrun_count * 4; - wcount -= thisrun_count; - } + retval = target_read_u8(target, FTFx_FSTAT, &fstat); + if (retval == ERROR_OK) { + retval = kinetis_ftfx_decode_error(fstat); + + /* reset error flags */ + target_write_u8(target, FTFx_FSTAT, 0x70); + } + } else if (retval != ERROR_OK) + LOG_ERROR("Error executing kinetis Flash programming algorithm"); target_free_working_area(target, source); target_free_working_area(target, write_algorithm); @@ -1018,6 +955,8 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + destroy_reg_param(®_params[4]); return retval; } -- 2.30.2