This is an automated email from Gerrit. Ivan Buliev ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/2787
-- gerrit commit 9832b64f1d30447eb369f43020a7336a988f89cd Author: Ivan Buliev <[email protected]> Date: Sat May 30 15:26:28 2015 +0300 ADuCM360 support A target config and a simple flash driver for the ADuCM360 microcontroller. The EEPROM of the chip may be erased and programmed. The patch of Paul Fertser, related to @raggedright (http://openocd.zylin.com/#/c/2781/) has been also applied. Change-Id: Ic2bc2f91ec5b6f72e3976dbe18071f461fe503b8 Signed-off-by: Ivan Buliev <[email protected]> diff --git a/doc/openocd.texi b/doc/openocd.texi index 511bc6c..0208fcf 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8460,11 +8460,17 @@ Cyg_Thread::thread_list, Cyg_Scheduler_Base::current_thread. @item ThreadX symbols _tx_thread_current_ptr, _tx_thread_created_ptr, _tx_thread_created_count. @item FreeRTOS symbols -@raggedright +@c The following is taken from recent texinfo to provide compatibility +@c with ancient versions that do not support @raggedright +@tex +\begingroup +\rightskip0pt plus2em \spaceskip.3333em \xspaceskip.5em\relax pxCurrentTCB, pxReadyTasksLists, xDelayedTaskList1, xDelayedTaskList2, pxDelayedTaskList, pxOverflowDelayedTaskList, xPendingReadyList, uxCurrentNumberOfTasks, uxTopUsedPriority. -@end raggedright +\par +\endgroup +@end tex @item linux symbols init_task. @item ChibiOS symbols diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 878fc26..4872b28 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -9,6 +9,7 @@ libocdflashnor_la_SOURCES = \ NOR_DRIVERS = \ aduc702x.c \ + aducm360.c \ at91sam4.c \ at91sam4l.c \ at91samd.c \ diff --git a/src/flash/nor/aducm360.c b/src/flash/nor/aducm360.c new file mode 100755 index 0000000..8ce1989 --- /dev/null +++ b/src/flash/nor/aducm360.c @@ -0,0 +1,639 @@ +/*************************************************************************** + * Copyright (C) 2015 by Ivan Buliev * + * [email protected] * + * * + * 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. * + * * + ***************************************************************************/ + +/*************************************************************************** + * This version for ADuCM360 is largely based on the following flash * + * drivers: * + * - aduc702x.c * + * Copyright (C) 2008 by Kevin McGuire * + * Copyright (C) 2008 by Marcel Wijlaars * + * Copyright (C) 2009 by Michael Ashton * + * and * + * - stm32f1x.c * + * Copyright (C) 2005 by Dominic Rath * + * [email protected] * + * * + * Copyright (C) 2008 by Spencer Oliver * + * [email protected] * + * * + * Copyright (C) 2011 by Andreas Fritiofson * + * [email protected] * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include <helper/binarybuffer.h> +#include <helper/time_support.h> +#include <target/algorithm.h> +#include <target/armv7m.h> + +static int aducm360_build_sector_list(struct flash_bank *bank); +static int aducm360_check_flash_completion(struct target *target, unsigned int timeout_ms); +static int aducm360_set_write_enable(struct target *target, int enable); + +#define ADUCM360_FLASH_BASE 0x40002800 +#define ADUCM360_FLASH_FEESTA 0x0000 +#define ADUCM360_FLASH_FEECON0 0x0004 +#define ADUCM360_FLASH_FEECMD 0x0008 +#define ADUCM360_FLASH_FEEADR0L 0x0010 +#define ADUCM360_FLASH_FEEADR0H 0x0014 +#define ADUCM360_FLASH_FEEADR1L 0x0018 +#define ADUCM360_FLASH_FEEADR1H 0x001C +#define ADUCM360_FLASH_FEEKEY 0x0020 +#define ADUCM360_FLASH_FEEPROL 0x0028 +#define ADUCM360_FLASH_FEEPROH 0x002C +#define ADUCM360_FLASH_FEESIGL 0x0030 +#define ADUCM360_FLASH_FEESIGH 0x0034 +#define ADUCM360_FLASH_FEECON1 0x0038 +#define ADUCM360_FLASH_FEEADRAL 0x0048 +#define ADUCM360_FLASH_FEEADRAH 0x004C +#define ADUCM360_FLASH_FEEAEN0 0x0078 +#define ADUCM360_FLASH_FEEAEN1 0x007C +#define ADUCM360_FLASH_FEEAEN2 0x0080 + +/* flash bank aducm360 0 0 0 0 <target#> + * The ADC7019-28 devices all have the same flash layout */ +FLASH_BANK_COMMAND_HANDLER(aducm360_flash_bank_command) +{ + printf("aducm360_flash_bank_command executed.\n"); + + bank->base = 0x00000000; + bank->size = 0x00020000; + + aducm360_build_sector_list(bank); + + return ERROR_OK; +} + +#define FLASH_SECTOR_SIZE 512 + +/* ----------------------------------------------------------------------- */ +static int aducm360_build_sector_list(struct flash_bank *bank) +{ + /* aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; */ + + int i = 0; + uint32_t offset = 0; + + /* sector size is 512 */ + bank->num_sectors = bank->size / FLASH_SECTOR_SIZE; + bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); + for (i = 0; i < bank->num_sectors; ++i) { + bank->sectors[i].offset = offset; + bank->sectors[i].size = FLASH_SECTOR_SIZE; + offset += bank->sectors[i].size; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 0; + } + + return ERROR_OK; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_protect_check(struct flash_bank *bank) +{ + printf("aducm360_protect_check not implemented yet.\n"); + return ERROR_OK; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_mass_erase(struct target *target) +{ + uint32_t value; + int res = ERROR_OK; + + printf("performing mass erase..."); + + /* Clear any old status */ + target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA,&value); + + /* Enable the writing to the flash*/ + aducm360_set_write_enable(target, 1); + + /* Unlock for writing */ + target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F456); + target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY, 0x0000F123); + /* Issue the 'MASSERASE' command */ + target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEECMD, 0x00000003); + + /* Check the result */ + res = aducm360_check_flash_completion(target, 3500); + if (res != ERROR_OK) { + printf("mass erase failed.\n"); + aducm360_set_write_enable(target, 0); + res = ERROR_FLASH_OPERATION_FAILED; + } else { + printf("mass erase successful.\n"); + } + return res; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_page_erase(struct target *target, uint32_t padd) +{ + uint32_t value; + int res = ERROR_OK; + + printf("performing sector erase (at 0x%08lX)... ", (unsigned long)padd); + + /* Clear any old status */ + target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA,&value); + + /* Enable the writing to the flash*/ + aducm360_set_write_enable(target, 1); + + /* Unlock for writing */ + target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY,0x0000F456); + target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEKEY,0x0000F123); + /* Write the sector address */ + target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEADR0L,padd & 0xFFFF); + target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEEADR0H,(padd>>16) & 0xFFFF); + /* Issue the 'ERASEPAGE' command */ + target_write_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEECMD,0x00000001); + + /* Check the result */ + res = aducm360_check_flash_completion(target, 50); + if (res != ERROR_OK) { + printf("failed.\n"); + aducm360_set_write_enable(target, 0); + res = ERROR_FLASH_OPERATION_FAILED; + } else { + printf("successful.\n"); + } + + return res; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_erase(struct flash_bank *bank, int first, int last) +{ + int res=ERROR_OK; + int i; + int count; + struct target *target = bank->target; + uint32_t padd; + + printf("performing aducm360_erase(%d,%d)...\n",first,last); + + if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) { + res = aducm360_mass_erase(target); + } else { + count = last - first + 1; + for (i=0; i<count; ++i) { + padd = bank->base + ((first+i)*FLASH_SECTOR_SIZE); + res = aducm360_page_erase(target, padd); + if (res != ERROR_OK) break; + } + } + + return res; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_protect(struct flash_bank *bank, int set, int first, int last) +{ + printf("aducm360_protect not implemented yet.\n"); + return ERROR_FLASH_OPERATION_FAILED; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_write_block_sync( + struct flash_bank *bank, + const uint8_t *buffer, + uint32_t offset, + uint32_t count) +{ + struct target *target = bank->target; + uint32_t target_buffer_size = 8192; + struct working_area *helper; + struct working_area *target_buffer; + uint32_t address = bank->base + offset; + struct reg_param reg_params[8]; + int ix; + int retval = ERROR_OK; + uint32_t entry_point=0, exit_point=0; + uint32_t res; + struct armv7m_algorithm armv7m_algo; +#if 0 + static const uint32_t aducm360_flash_write_code[] = { + /* Single blink pulse */ + 0xEA4F2240, 0x22002302, 0x0302EA43, 0x2303EA4F, 0xEA432260, + 0xEA4F0302, 0x22302303, 0x0402EA43, 0xF8842208, 0x22012020, + 0x4282EA4F, 0x33012300, 0xD1FC4293, 0xF8842208, 0x2201201C, + 0x4282EA4F, 0x33012300, 0xD1FC4293, 0xF04FBF00, 0xBE000301 + }; +#else + static const uint32_t aducm360_flash_write_code[] = { + /* helper.code */ + 0x88AF4D10,0x0704F047,0x682F80AF,0x600E6806, + 0xF017882F,0xF43F0F08,0xF851AFFB,0x42B77B04, + 0x800DF040,0x0004F100,0xF47F3A04,0x686FAFEF, + 0x0704F027,0xF04F80AF,0xF0000400,0xF04FB802, + 0xBE000480,0x40002800,0x00015000,0x20000000, + 0x00013000 + }; +#endif + printf("'aducm360_write_block_sync' requested, dst:0x%08lX, count:0x%08lX(%d) bytes.\n", + (unsigned long)address, (unsigned long)count, count); + + /* ----- Check the destination area for a Long Word alignment ----- */ + if (((count%4) != 0) || ((offset%4) != 0)) { + LOG_ERROR("write block must be multiple of four bytes in offset & length"); + return ERROR_FAIL; + } + + /* ----- Allocate space in the target's RAM for the helper code ----- */ + printf("allocating space for the aducm360_helper_sync code...\n"); + if (target_alloc_working_area(target, sizeof(aducm360_flash_write_code), + &helper) != ERROR_OK) { + LOG_WARNING("no working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + printf("allocated at 0x%08lX .. 0x%08lX ...\n", + (unsigned long)helper->address, + (unsigned long)(helper->address + helper->size - 1) ); + + /* ----- Upload the helper code to the space in the target's RAM ----- */ + printf("sending the aducm360_write_block code to the target...\n"); + uint8_t code[sizeof(aducm360_flash_write_code)]; + target_buffer_set_u32_array(target, code, ARRAY_SIZE(aducm360_flash_write_code), + aducm360_flash_write_code); + retval = target_write_buffer(target, helper->address, sizeof(code), code); + if (retval != ERROR_OK) return retval; + entry_point = helper->address; + printf("Helper's RAM start address:0x%08lX, exit point address:0x%08lX\n", + (unsigned long)entry_point, (unsigned long)exit_point); + + /* ----- Allocate space in the target's RAM for the user application's object code ----- */ + while (target_alloc_working_area_try(target, target_buffer_size, &target_buffer) != ERROR_OK) { + printf("couldn't allocate a buffer space of 0x%08lX bytes in the target's SRAM.\n", (unsigned long)target_buffer_size); + target_buffer_size /= 2; + if (target_buffer_size <= 256) { // No room available + LOG_WARNING("no large enough working area available, can't do block memory writes"); + target_free_working_area(target, helper); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + } + printf("buffer space of 0x%08lX bytes was successfully allocated.\n", (unsigned long)target_buffer_size); + + // ----- Prepare the target for the helper ----- + armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC; + armv7m_algo.core_mode = ARM_MODE_THREAD; + + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); //SRC + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); //DST + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); //COUNT + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); //not used + init_reg_param(®_params[4], "r4", 32, PARAM_IN); //RESULT + + /* ===== Execute the Main Programming Loop! ===== */ + ix = 0; + while (count > 0) { + uint32_t thisrun_count = (count > target_buffer_size) ? target_buffer_size : count; + + printf("Copying chunk %02d: ROM:0x%08lX-0x%08lX, bytes:%d(0x%08lX)\n", ++ix, + (unsigned long)address, (unsigned long)address+(unsigned long)thisrun_count-1, + thisrun_count, (unsigned long)thisrun_count); + + /* ----- Upload the chunk ----- */ + retval = target_write_buffer(target, target_buffer->address, thisrun_count, buffer); if (retval != ERROR_OK) break; + // Set the arguments for the helper + buf_set_u32(reg_params[0].value, 0, 32, target_buffer->address); //SRC + buf_set_u32(reg_params[1].value, 0, 32, address); //DST + buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); //COUNT + buf_set_u32(reg_params[3].value, 0, 32, 0); //NOT USED + + printf("Programming chunk %02d...\n",ix); + retval = target_run_algorithm(target, 0, NULL, 5, + reg_params, entry_point, exit_point, 10000, &armv7m_algo); + + printf("retval = 0x%08X...\n",(unsigned)retval); + if (retval != ERROR_OK) { + LOG_ERROR("error executing aducm360 flash write algorithm"); + break; + } + + res = buf_get_u32(reg_params[4].value, 0, 32); + if (res) { + LOG_ERROR("aducm360 fast sync algorithm reports an error (%02X)", res); + retval = ERROR_FAIL; + break; + } + + buffer += thisrun_count; + address += thisrun_count; + count -= thisrun_count; + } + + target_free_working_area(target, target_buffer); + target_free_working_area(target, helper); + + 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; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_write_block_async( + struct flash_bank *bank, + const uint8_t *buffer, + uint32_t offset, + uint32_t count) +{ + struct target *target = bank->target; + uint32_t target_buffer_size = 1024; + struct working_area *helper; + struct working_area *target_buffer; + uint32_t address = bank->base + offset; + struct reg_param reg_params[9]; + int retval = ERROR_OK; + uint32_t entry_point=0, exit_point=0; + uint32_t res; + uint32_t wcount; + struct armv7m_algorithm armv7m_algo; + + static const uint32_t aducm360_flash_write_code[] = { + /* helper.code */ + /* + 0x404CF8DF, 0xF04588A5, 0x80A50504, 0x8000F8D0, + 0x0F00F1B8, 0x8016F000, 0x45476847, 0xAFF6F43F, + 0x6B04F857, 0x6B04F842, 0xF0158825, 0xF43F0F08, + 0x428FAFFB, 0xF100BF28, 0x60470708, 0xB10B3B01, + 0xBFE4F7FF, 0xF02588A5, 0x80A50504, 0xBE00BF00, + 0x40002800, 0x20000000, 0x20000100, 0x00013000 + */ + 0x4050F8DF, 0xF04588A5, 0x80A50504, 0x8000F8D0, + 0x0F00F1B8, 0x8016F000, 0x45476847, 0xAFF6F43F, + 0x6B04F857, 0x6B04F842, 0xF0158825, 0xF43F0F08, + 0x428FAFFB, 0xF100BF28, 0x60470708, 0xB10B3B01, + 0xBFE4F7FF, 0xF02588A5, 0x80A50504, 0x0900F04F, + 0xBE00BF00, 0x40002800, 0x20000000, 0x20000100, + 0x00013000 + }; + + printf("'aducm360_write_block_async' requested, dst:0x%08lX, count:0x%08lX(%d) bytes.\n", + (unsigned long)address, (unsigned long)count, count); + + /* ----- Check the destination area for a Long Word alignment ----- */ + if (((count%4) != 0) || ((offset%4) != 0)) { + LOG_ERROR("write block must be multiple of four bytes in offset & length"); + return ERROR_FAIL; + } + wcount = count/4; + + /* ----- Allocate space in the target's RAM for the helper code ----- */ + printf("allocating space for the aducm360_helper_sync code...\n"); + if (target_alloc_working_area(target, sizeof(aducm360_flash_write_code), + &helper) != ERROR_OK) { + LOG_WARNING("no working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + printf("allocated at 0x%08lX .. 0x%08lX ...\n", + (unsigned long)helper->address, + (unsigned long)(helper->address + helper->size - 1) ); + + /* ----- Upload the helper code to the space in the target's RAM ----- */ + printf("sending the aducm360_write_block code to the target...\n"); + uint8_t code[sizeof(aducm360_flash_write_code)]; + target_buffer_set_u32_array(target, code, ARRAY_SIZE(aducm360_flash_write_code), + aducm360_flash_write_code); + retval = target_write_buffer(target, helper->address, sizeof(code), code); + if (retval != ERROR_OK) return retval; + entry_point = helper->address; + printf("Helper's RAM start address:0x%08lX, exit point address:0x%08lX\n", + (unsigned long)entry_point, (unsigned long)exit_point); + + /* ----- Allocate space in the target's RAM for the user application's object code ----- */ + while (target_alloc_working_area_try(target, target_buffer_size, &target_buffer) != ERROR_OK) { + printf("couldn't allocate a buffer space of 0x%08lX bytes in the target's SRAM.\n", (unsigned long)target_buffer_size); + target_buffer_size /= 2; + if (target_buffer_size <= 256) { // No room available + LOG_WARNING("no large enough working area available, can't do block memory writes"); + target_free_working_area(target, helper); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + } + printf("buffer space of 0x%08lX bytes was successfully allocated.\n", (unsigned long)target_buffer_size); + + /* ----- Prepare the target for the helper ----- */ + armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC; + armv7m_algo.core_mode = ARM_MODE_THREAD; + + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /*SRCBEG */ + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /*SRCEND */ + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /*DST */ + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /*COUNT (LWs)*/ + init_reg_param(®_params[4], "r9", 32, PARAM_IN); /*RESULT */ + + buf_set_u32(reg_params[0].value, 0, 32, target_buffer->address); + buf_set_u32(reg_params[1].value, 0, 32, target_buffer->address + target_buffer->size); + buf_set_u32(reg_params[2].value, 0, 32, address); + buf_set_u32(reg_params[3].value, 0, 32, wcount); + + printf("Programming ...\n"); + retval = target_run_flash_async_algorithm(target, buffer, wcount, 4, + 0, NULL, + 5, reg_params, + target_buffer->address, target_buffer->size, + entry_point, exit_point, + &armv7m_algo); + + /* + if (retval == ERROR_FLASH_OPERATION_FAILED) + LOG_ERROR("error %d executing stellaris flash write algorithm", retval); + */ + + printf("retval = 0x%08X...\n",(unsigned)retval); + if (retval != ERROR_OK) { + LOG_ERROR("error executing aducm360 flash write algorithm"); + } else { + res = buf_get_u32(reg_params[4].value, 0, 32); /*RESULT*/ + if (res) { + LOG_ERROR("aducm360 fast async algorithm reports an error (%02X)", res); + retval = ERROR_FAIL; + } + } + + target_free_working_area(target, target_buffer); + target_free_working_area(target, helper); + + 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; +} + +/* ----------------------------------------------------------------------- */ +/* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall + * back to another mechanism that does not require onboard RAM + * + * Caller should not check for other return values specifically + */ +static int aducm360_write_block(struct flash_bank *bank, + const uint8_t *buffer, + uint32_t offset, + uint32_t count) +{ + int choice = 0; + + switch (choice) { + case 0: + return aducm360_write_block_sync(bank,buffer,offset,count); + break; + case 1: + return aducm360_write_block_async(bank,buffer,offset,count); + break; + default: + printf("Info! The aducm360_write_block is cancelled on purpose!\n"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } +} + +/* ----------------------------------------------------------------------- */ +#define FEESTA_WRDONE 0x00000008 + +static int aducm360_write_modified(struct flash_bank *bank, + const uint8_t *buffer, + uint32_t offset, + uint32_t count) +{ + uint32_t value; + int res = ERROR_OK; + uint32_t i, a, d; + struct target *target = bank->target; + + printf("performing slow write (offset=0x%08lX, count=0x%08lX)... \n", + (unsigned long)offset, (unsigned long)count); + + /* Enable the writing to the flash */ + aducm360_set_write_enable(target, 1); + + /* Clear any old status */ + target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA,&value); + + printf("writing flash ..."); + for (i=0; i<count; i+=4) { + a = offset+i; + d = *((uint32_t*)(&buffer[i])); + if (i%256==0)printf("\n"); printf("."); + target_write_u32(target, a, d); + do { + target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value); + } while(!(value & FEESTA_WRDONE)); + } + printf("\n"); + aducm360_set_write_enable(target, 0); + + return res; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) +{ + int retval; + + /* try using a block write */ + retval = aducm360_write_block(bank, buffer, offset, count); + if (retval != ERROR_OK) { + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { + /* if block write failed (no sufficient working area), + * use normal (slow) JTAG method */ + LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); + + /*retval = aducm360_write_single(bank, buffer, offset, count);*/ + retval = aducm360_write_modified(bank, buffer, offset, count); + if (retval != ERROR_OK) { + LOG_ERROR("slow write failed"); + return ERROR_FLASH_OPERATION_FAILED; + } + } + } + return retval; +} + +/* ----------------------------------------------------------------------- */ +static int aducm360_probe(struct flash_bank *bank) +{ + return ERROR_OK; +} + +/* ----------------------------------------------------------------------- */ +/* sets FEECON0 bit 2 + * enable = 1 enables writes & erases, 0 disables them */ +static int aducm360_set_write_enable(struct target *target, int enable) +{ + /* don't bother to preserve int enable bit here */ + uint32_t value; + + target_read_u32(target,ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEECON0, &value); + if (enable) + value |= 0x00000004; + else + value &= ~0x00000004; + target_write_u32(target,ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEECON0, value); + + return ERROR_OK; +} + +/* ----------------------------------------------------------------------- */ +/* wait up to timeout_ms for controller to not be busy, + * then check whether the command passed or failed. + * + * this function sleeps 1ms between checks (after the first one), + * so in some cases may slow things down without a usleep after the first read */ +static int aducm360_check_flash_completion(struct target *target, unsigned int timeout_ms) +{ + uint32_t v=1; + + long long endtime = timeval_ms() + timeout_ms; + while (1) { + target_read_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEESTA, &v); + if ((v & 0x00000001) == 0) break; + alive_sleep(1); + if (timeval_ms() >= endtime) break; + } + + /*printf("aducm360_FEESTA=%08lX\n", (unsigned long)v & 0xFFFF);*/ + + if (!(v & 0x00000004)) /* b2 */ + return ERROR_FAIL; + + return ERROR_OK; +} + +/* ----------------------------------------------------------------------- */ +struct flash_driver aducm360_flash = { + .name = "aducm360", + .flash_bank_command = aducm360_flash_bank_command, + .erase = aducm360_erase, + .protect = aducm360_protect, + .write = aducm360_write, + .read = default_flash_read, + .probe = aducm360_probe, + .auto_probe = aducm360_probe, + .erase_check = default_flash_blank_check, + .protect_check = aducm360_protect_check, +}; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index fead797..2800277 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -35,6 +35,7 @@ extern struct flash_driver at91sam7_flash; extern struct flash_driver str7x_flash; extern struct flash_driver str9x_flash; extern struct flash_driver aduc702x_flash; +extern struct flash_driver aducm360_flash; extern struct flash_driver stellaris_flash; extern struct flash_driver str9xpec_flash; extern struct flash_driver stm32f1x_flash; @@ -78,6 +79,7 @@ static struct flash_driver *flash_drivers[] = { &str7x_flash, &str9x_flash, &aduc702x_flash, + &aducm360_flash, &stellaris_flash, &str9xpec_flash, &stm32f1x_flash, diff --git a/tcl/target/aducm360.cfg b/tcl/target/aducm360.cfg new file mode 100755 index 0000000..a5fd56f --- /dev/null +++ b/tcl/target/aducm360.cfg @@ -0,0 +1,71 @@ +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME aducm360 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + # This config file was defaulting to big endian.. + set _ENDIAN little +} + +# Work-area is a space in RAM used for flash programming +# By default use 4kB (as found on some STM32F100s) +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x1000 +} + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x2ba01477 +} + + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + + +# JTAG speed +adapter_khz 1000 + +#foreach t [jtag names] { +# puts [format "TAP: %s\n" $t] +# } + +#scan_chain + +## JTAG scan chain +#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) +#jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +#jtag newtap $_CHIPNAME cpu -expected-id $_CPUTAPID + +## +## Target configuration +## +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME + +# allocate the entire SRAM as working area +#$_TARGETNAME configure -work-area-phys 0x10000 -work-area-size 0x2000 +#$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# flash size will be probed +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME aducm360 0x00 0 0 0 $_TARGETNAME + +adapter_nsrst_delay 100 +#if {$using_jtag} { +# jtag_ntrst_delay 100 +#} + +# if srst is not fitted use SYSRESETREQ to +# perform a soft reset +cortex_m reset_config sysresetreq \ No newline at end of file -- ------------------------------------------------------------------------------ _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
