summaryrefslogtreecommitdiff
path: root/ecos/packages/devs/flash/arm/lpc2xxx/current/src/flash_arm_lpc2xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'ecos/packages/devs/flash/arm/lpc2xxx/current/src/flash_arm_lpc2xxx.c')
-rw-r--r--ecos/packages/devs/flash/arm/lpc2xxx/current/src/flash_arm_lpc2xxx.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/ecos/packages/devs/flash/arm/lpc2xxx/current/src/flash_arm_lpc2xxx.c b/ecos/packages/devs/flash/arm/lpc2xxx/current/src/flash_arm_lpc2xxx.c
new file mode 100644
index 0000000..85b6dcc
--- /dev/null
+++ b/ecos/packages/devs/flash/arm/lpc2xxx/current/src/flash_arm_lpc2xxx.c
@@ -0,0 +1,218 @@
+//==========================================================================
+//
+// flash_arm_lpc2xxx.c
+//
+// Flash programming for LPC2xxx
+//
+//==========================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+//
+// eCos 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 or (at your option) any later
+// version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+// Contributors:
+// Date: 2007-07-12
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/system.h>
+#include <pkgconf/devs_flash_arm_lpc2xxx.h>
+#include <pkgconf/hal.h>
+#include <pkgconf/hal_arm.h>
+#include <cyg/hal/hal_intr.h>
+
+#include <cyg/io/flash.h>
+#include <cyg/io/flash_dev.h>
+
+#include "flash_arm_lpc2xxx.h"
+
+/* gcc builtins */
+extern void* memcpy(void *, const void *, size_t);
+extern void* memset(void *, int, size_t);
+
+/* wrapper for simpler IAP access */
+static void
+iap(struct iap_param *param, struct iap_param *result)
+{
+ static void (* const iap)(struct iap_param *, struct iap_param *)
+ = (void (*)(struct iap_param *, struct iap_param *)) IAP_LOCATION;
+ cyg_uint32 cpsr;
+
+ HAL_DISABLE_INTERRUPTS(cpsr);
+ iap(param, result);
+ HAL_RESTORE_INTERRUPTS(cpsr);
+}
+
+void
+flash_query(void *data)
+{
+ /* nothing to do here */
+}
+
+/*
+ * 248k in 31 blocks by 8k there actually less blocks since two of
+ * them are 64k, but accessing anything but the last few 8k blocks is
+ * not supported anyway
+ */
+int
+flash_hwr_init(void)
+{
+ flash_info.block_size = 8 * 1024;
+ flash_info.blocks = 31;
+ flash_info.start = (void *) 0;
+ flash_info.end = (void *) (248 * 1024);
+
+ return FLASH_ERR_OK;
+}
+
+
+static const cyg_uint8 flash_errors[12] = {
+ FLASH_ERR_OK, /* IAP_CMD_SUCCESS */
+ FLASH_ERR_PROTOCOL, /* IAP_INV_COMMAND */
+ FLASH_ERR_INVALID, /* IAP_SRC_ADDRERR */
+ FLASH_ERR_INVALID, /* IAP_DST_ADDRERR */
+ FLASH_ERR_INVALID, /* IAP_SRC_ADDRMAP */
+ FLASH_ERR_INVALID, /* IAP_DST_ADDRMAP */
+ FLASH_ERR_INVALID, /* IAP_CNT_INVALID */
+ FLASH_ERR_INVALID, /* IAP_SEC_INVALID */
+ FLASH_ERR_PROTOCOL, /* IAP_SEC_NOTBLNK */
+ FLASH_ERR_PROTOCOL, /* IAP_SEC_NOTPREP */
+ FLASH_ERR_DRV_VERIFY, /* IAP_CMP_INEQUAL */
+ FLASH_ERR_DRV_TIMEOUT, /* IAP_BSY */
+};
+
+int
+flash_hwr_map_error(e)
+{
+ if(e > 11)
+ return FLASH_ERR_PROTOCOL;
+ return flash_errors[e];
+}
+
+/* this will not work for flash addresses < 0x30000 */
+static int
+block_by_addr(cyg_uint32 addr)
+{
+ int block;
+
+ block = (addr >> 13) & 0x1f;
+ block -= 14;
+
+ return block;
+}
+
+int
+flash_erase_block(void *block, unsigned int size)
+{
+ struct iap_param param, result;
+
+ param.code = IAP_PREPARE;
+
+ param.p[0] = param.p[1] = block_by_addr((cyg_uint32) block);
+ if(param.p[0] < 10)
+ return FLASH_ERR_INVALID;
+
+ /* prepare sector(s) */
+ iap(&param, &result);
+ if(result.code != IAP_CMD_SUCCESS)
+ return result.code;
+
+ param.code = IAP_ERASE;
+ param.p[2] = CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED / 1000;
+
+ /* erase sector(s) */
+ iap(&param, &result);
+ return result.code;
+}
+
+int
+flash_program_buf(void *addr, void *data, int len)
+{
+ static const int size = CYGPKG_DEVS_FLASH_ARM_LPC2XXX_BUFSIZE;
+ static const cyg_uint32 b = (0x40004000 - 32 -
+ CYGPKG_DEVS_FLASH_ARM_LPC2XXX_BUFSIZE);
+ static void * const buf = (void *) (0x40004000 - 32 -
+ CYGPKG_DEVS_FLASH_ARM_LPC2XXX_BUFSIZE);
+ cyg_uint32 a = (cyg_uint32) addr;
+ char *d = (char *) data;
+ struct iap_param param, result;
+
+ param.code = IAP_PREPARE;
+ param.p[0] = block_by_addr(a);
+ param.p[1] = block_by_addr(a + len - 1);
+ if(param.p[0] < 10 || param.p[1] > 16)
+ return FLASH_ERR_INVALID;
+
+ do {
+ /* prepare sector(s) */
+ iap(&param, &result);
+ if(result.code != IAP_CMD_SUCCESS)
+ return result.code;
+
+ if(len < size)
+ memset(buf, 0xff, size);
+ memcpy(buf, d, size);
+
+ param.code = IAP_COPY;
+ param.p[0] = a;
+ param.p[1] = b;
+ param.p[2] = size;
+ param.p[3] = CYGNUM_HAL_ARM_LPC2XXX_CLOCK_SPEED / 1000;
+
+ /* copy ram to flash */
+ iap(&param, &result);
+ if(result.code != IAP_CMD_SUCCESS)
+ return result.code;
+
+ len -= size;
+ a += size;
+ d += size;
+ } while(len > 0);
+
+ return(result.code);
+}
+
+bool
+flash_code_overlaps(void *start, void *end)
+{
+ extern unsigned char _stext[], _etext[];
+
+ return ((((unsigned long)&_stext >= (unsigned long)start) &&
+ ((unsigned long)&_stext < (unsigned long)end)) ||
+ (((unsigned long)&_etext >= (unsigned long)start) &&
+ ((unsigned long)&_etext < (unsigned long)end)));
+}