You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2016/06/15 22:04:19 UTC
[36/51] [partial] incubator-mynewt-site git commit: Fixed broken
Quick Start link and added OpenOCD option for Arduino Primo debugging
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/s3c24xx_regs.h
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/s3c24xx_regs.h b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/s3c24xx_regs.h
new file mode 100755
index 0000000..fc0f96f
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/s3c24xx_regs.h
@@ -0,0 +1,132 @@
+/***************************************************************************
+ * Copyright (C) 2004, 2005 by Simtec Electronics *
+ * linux@simtec.co.uk *
+ * http://www.simtec.co.uk/products/SWLINUX/ *
+ * *
+ * 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; version 2 of the License. *
+ * *
+ * 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. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ ***************************************************************************/
+
+/*
+ * S3C2410 NAND register definitions
+ */
+
+#ifndef __ASM_ARM_REGS_NAND
+#define __ASM_ARM_REGS_NAND
+
+#define S3C2410_NFREG(x) (x)
+
+#define S3C2410_NFCONF S3C2410_NFREG(0x00)
+#define S3C2410_NFCMD S3C2410_NFREG(0x04)
+#define S3C2410_NFADDR S3C2410_NFREG(0x08)
+#define S3C2410_NFDATA S3C2410_NFREG(0x0C)
+#define S3C2410_NFSTAT S3C2410_NFREG(0x10)
+#define S3C2410_NFECC S3C2410_NFREG(0x14)
+
+#define S3C2440_NFCONT S3C2410_NFREG(0x04)
+#define S3C2440_NFCMD S3C2410_NFREG(0x08)
+#define S3C2440_NFADDR S3C2410_NFREG(0x0C)
+#define S3C2440_NFDATA S3C2410_NFREG(0x10)
+#define S3C2440_NFECCD0 S3C2410_NFREG(0x14)
+#define S3C2440_NFECCD1 S3C2410_NFREG(0x18)
+#define S3C2440_NFECCD S3C2410_NFREG(0x1C)
+#define S3C2440_NFSTAT S3C2410_NFREG(0x20)
+#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24)
+#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
+#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
+#define S3C2440_NFMECC1 S3C2410_NFREG(0x30)
+#define S3C2440_NFSECC S3C2410_NFREG(0x34)
+#define S3C2440_NFSBLK S3C2410_NFREG(0x38)
+#define S3C2440_NFEBLK S3C2410_NFREG(0x3C)
+
+#define S3C2412_NFSBLK S3C2410_NFREG(0x20)
+#define S3C2412_NFEBLK S3C2410_NFREG(0x24)
+#define S3C2412_NFSTAT S3C2410_NFREG(0x28)
+#define S3C2412_NFMECC_ERR0 S3C2410_NFREG(0x2C)
+#define S3C2412_NFMECC_ERR1 S3C2410_NFREG(0x30)
+#define S3C2412_NFMECC0 S3C2410_NFREG(0x34)
+#define S3C2412_NFMECC1 S3C2410_NFREG(0x38)
+#define S3C2412_NFSECC S3C2410_NFREG(0x3C)
+
+#define S3C2410_NFCONF_EN (1 << 15)
+#define S3C2410_NFCONF_512BYTE (1 << 14)
+#define S3C2410_NFCONF_4STEP (1 << 13)
+#define S3C2410_NFCONF_INITECC (1 << 12)
+#define S3C2410_NFCONF_nFCE (1 << 11)
+#define S3C2410_NFCONF_TACLS(x) ((x) << 8)
+#define S3C2410_NFCONF_TWRPH0(x) ((x) << 4)
+#define S3C2410_NFCONF_TWRPH1(x) ((x) << 0)
+
+#define S3C2410_NFSTAT_BUSY (1 << 0)
+
+#define S3C2440_NFCONF_BUSWIDTH_8 (0 << 0)
+#define S3C2440_NFCONF_BUSWIDTH_16 (1 << 0)
+#define S3C2440_NFCONF_ADVFLASH (1 << 3)
+#define S3C2440_NFCONF_TACLS(x) ((x) << 12)
+#define S3C2440_NFCONF_TWRPH0(x) ((x) << 8)
+#define S3C2440_NFCONF_TWRPH1(x) ((x) << 4)
+
+#define S3C2440_NFCONT_LOCKTIGHT (1 << 13)
+#define S3C2440_NFCONT_SOFTLOCK (1 << 12)
+#define S3C2440_NFCONT_ILLEGALACC_EN (1 << 10)
+#define S3C2440_NFCONT_RNBINT_EN (1 << 9)
+#define S3C2440_NFCONT_RN_FALLING (1 << 8)
+#define S3C2440_NFCONT_SPARE_ECCLOCK (1 << 6)
+#define S3C2440_NFCONT_MAIN_ECCLOCK (1 << 5)
+#define S3C2440_NFCONT_INITECC (1 << 4)
+#define S3C2440_NFCONT_nFCE (1 << 1)
+#define S3C2440_NFCONT_ENABLE (1 << 0)
+
+#define S3C2440_NFSTAT_READY (1 << 0)
+#define S3C2440_NFSTAT_nCE (1 << 1)
+#define S3C2440_NFSTAT_RnB_CHANGE (1 << 2)
+#define S3C2440_NFSTAT_ILLEGAL_ACCESS (1 << 3)
+
+#define S3C2412_NFCONF_NANDBOOT (1 << 31)
+#define S3C2412_NFCONF_ECCCLKCON (1 << 30)
+#define S3C2412_NFCONF_ECC_MLC (1 << 24)
+#define S3C2412_NFCONF_TACLS_MASK (7 << 12) /* 1 extra bit of Tacls */
+
+#define S3C2412_NFCONT_ECC4_DIRWR (1 << 18)
+#define S3C2412_NFCONT_LOCKTIGHT (1 << 17)
+#define S3C2412_NFCONT_SOFTLOCK (1 << 16)
+#define S3C2412_NFCONT_ECC4_ENCINT (1 << 13)
+#define S3C2412_NFCONT_ECC4_DECINT (1 << 12)
+#define S3C2412_NFCONT_MAIN_ECC_LOCK (1 << 7)
+#define S3C2412_NFCONT_INIT_MAIN_ECC (1 << 5)
+#define S3C2412_NFCONT_nFCE1 (1 << 2)
+#define S3C2412_NFCONT_nFCE0 (1 << 1)
+
+#define S3C2412_NFSTAT_ECC_ENCDONE (1 << 7)
+#define S3C2412_NFSTAT_ECC_DECDONE (1 << 6)
+#define S3C2412_NFSTAT_ILLEGAL_ACCESS (1 << 5)
+#define S3C2412_NFSTAT_RnB_CHANGE (1 << 4)
+#define S3C2412_NFSTAT_nFCE1 (1 << 3)
+#define S3C2412_NFSTAT_nFCE0 (1 << 2)
+#define S3C2412_NFSTAT_Res1 (1 << 1)
+#define S3C2412_NFSTAT_READY (1 << 0)
+
+#define S3C2412_NFECCERR_SERRDATA(x) (((x) >> 21) & 0xf)
+#define S3C2412_NFECCERR_SERRBIT(x) (((x) >> 18) & 0x7)
+#define S3C2412_NFECCERR_MERRDATA(x) (((x) >> 7) & 0x3ff)
+#define S3C2412_NFECCERR_MERRBIT(x) (((x) >> 4) & 0x7)
+#define S3C2412_NFECCERR_SPARE_ERR(x) (((x) >> 2) & 0x3)
+#define S3C2412_NFECCERR_MAIN_ERR(x) (((x) >> 2) & 0x3)
+#define S3C2412_NFECCERR_NONE (0)
+#define S3C2412_NFECCERR_1BIT (1)
+#define S3C2412_NFECCERR_MULTIBIT (2)
+#define S3C2412_NFECCERR_ECCAREA (3)
+
+#endif /* __ASM_ARM_REGS_NAND */
+
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/s3c6400.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/s3c6400.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/s3c6400.c
new file mode 100755
index 0000000..abbfb25
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/s3c6400.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Peter Korsgaard <ja...@sunsite.dk> *
+ * Heavily based on s3c2412.c by Ben Dooks <be...@fluff.org> *
+ * *
+ * 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. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "s3c24xx.h"
+/* s3c64xx uses another base address for the nand controller than 24xx */
+#undef S3C2410_NFREG
+#define S3C2410_NFREG(x) ((x) + 0x70200000)
+
+NAND_DEVICE_COMMAND_HANDLER(s3c6400_nand_device_command)
+{
+ struct s3c24xx_nand_controller *info;
+ CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
+
+ /* fill in the address fields for the core device */
+ info->cmd = S3C2440_NFCMD;
+ info->addr = S3C2440_NFADDR;
+ info->data = S3C2440_NFDATA;
+ info->nfstat = S3C2412_NFSTAT;
+
+ return ERROR_OK;
+}
+
+static int s3c6400_init(struct nand_device *nand)
+{
+ struct target *target = nand->target;
+
+ target_write_u32(target, S3C2410_NFCONF,
+ S3C2440_NFCONF_TACLS(3) |
+ S3C2440_NFCONF_TWRPH0(7) |
+ S3C2440_NFCONF_TWRPH1(7) | 4);
+
+ target_write_u32(target, S3C2440_NFCONT,
+ S3C2412_NFCONT_INIT_MAIN_ECC |
+ S3C2440_NFCONT_ENABLE);
+
+ return ERROR_OK;
+}
+
+struct nand_flash_controller s3c6400_nand_controller = {
+ .name = "s3c6400",
+ .nand_device_command = &s3c6400_nand_device_command,
+ .init = &s3c6400_init,
+ .reset = &s3c24xx_reset,
+ .command = &s3c24xx_command,
+ .address = &s3c24xx_address,
+ .write_data = &s3c24xx_write_data,
+ .read_data = &s3c24xx_read_data,
+ .write_page = s3c24xx_write_page,
+ .read_page = s3c24xx_read_page,
+ .write_block_data = &s3c2440_write_block_data,
+ .read_block_data = &s3c2440_read_block_data,
+ .nand_ready = &s3c2440_nand_ready,
+};
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/tcl.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/tcl.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/tcl.c
new file mode 100755
index 0000000..d238e7a
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nand/tcl.c
@@ -0,0 +1,628 @@
+/***************************************************************************
+ * Copyright (C) 2007 by Dominic Rath <Do...@gmx.de> *
+ * Copyright (C) 2002 Thomas Gleixner <tg...@linutronix.de> *
+ * Copyright (C) 2009 Zachary T Welch <zw...@superlucidity.net> *
+ * *
+ * Partially based on drivers/mtd/nand_ids.c from Linux. *
+ * *
+ * 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. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "core.h"
+#include "imp.h"
+#include "fileio.h"
+#include <target/target.h>
+
+/* to be removed */
+extern struct nand_device *nand_devices;
+
+COMMAND_HANDLER(handle_nand_list_command)
+{
+ struct nand_device *p;
+ int i;
+
+ if (!nand_devices) {
+ command_print(CMD_CTX, "no NAND flash devices configured");
+ return ERROR_OK;
+ }
+
+ for (p = nand_devices, i = 0; p; p = p->next, i++) {
+ if (p->device)
+ command_print(CMD_CTX, "#%i: %s (%s) "
+ "pagesize: %i, buswidth: %i,\n\t"
+ "blocksize: %i, blocks: %i",
+ i, p->device->name, p->manufacturer->name,
+ p->page_size, p->bus_width,
+ p->erase_size, p->num_blocks);
+ else
+ command_print(CMD_CTX, "#%i: not probed", i);
+ }
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nand_info_command)
+{
+ int i = 0;
+ int j = 0;
+ int first = -1;
+ int last = -1;
+
+ switch (CMD_ARGC) {
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ case 1:
+ first = 0;
+ last = INT32_MAX;
+ break;
+ case 2:
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
+ first = last = i;
+ i = 0;
+ break;
+ case 3:
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
+ break;
+ }
+
+ struct nand_device *p;
+ int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
+ if (ERROR_OK != retval)
+ return retval;
+
+ if (NULL == p->device) {
+ command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
+ return ERROR_OK;
+ }
+
+ if (first >= p->num_blocks)
+ first = p->num_blocks - 1;
+
+ if (last >= p->num_blocks)
+ last = p->num_blocks - 1;
+
+ command_print(CMD_CTX,
+ "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
+ i++,
+ p->device->name,
+ p->manufacturer->name,
+ p->page_size,
+ p->bus_width,
+ p->erase_size);
+
+ for (j = first; j <= last; j++) {
+ char *erase_state, *bad_state;
+
+ if (p->blocks[j].is_erased == 0)
+ erase_state = "not erased";
+ else if (p->blocks[j].is_erased == 1)
+ erase_state = "erased";
+ else
+ erase_state = "erase state unknown";
+
+ if (p->blocks[j].is_bad == 0)
+ bad_state = "";
+ else if (p->blocks[j].is_bad == 1)
+ bad_state = " (marked bad)";
+ else
+ bad_state = " (block condition unknown)";
+
+ command_print(CMD_CTX,
+ "\t#%i: 0x%8.8" PRIx32 " (%" PRId32 "kB) %s%s",
+ j,
+ p->blocks[j].offset,
+ p->blocks[j].size / 1024,
+ erase_state,
+ bad_state);
+ }
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nand_probe_command)
+{
+ if (CMD_ARGC != 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct nand_device *p;
+ int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
+ if (ERROR_OK != retval)
+ return retval;
+
+ retval = nand_probe(p);
+ if (retval == ERROR_OK) {
+ command_print(CMD_CTX, "NAND flash device '%s (%s)' found",
+ p->device->name, p->manufacturer->name);
+ }
+
+ return retval;
+}
+
+COMMAND_HANDLER(handle_nand_erase_command)
+{
+ if (CMD_ARGC != 1 && CMD_ARGC != 3)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct nand_device *p;
+ int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
+ if (ERROR_OK != retval)
+ return retval;
+
+ unsigned long offset;
+ unsigned long length;
+
+ /* erase specified part of the chip; or else everything */
+ if (CMD_ARGC == 3) {
+ unsigned long size = p->erase_size * p->num_blocks;
+
+ COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
+ if ((offset % p->erase_size) != 0 || offset >= size)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
+ if ((length == 0) || (length % p->erase_size) != 0
+ || (length + offset) > size)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ offset /= p->erase_size;
+ length /= p->erase_size;
+ } else {
+ offset = 0;
+ length = p->num_blocks;
+ }
+
+ retval = nand_erase(p, offset, offset + length - 1);
+ if (retval == ERROR_OK) {
+ command_print(CMD_CTX, "erased blocks %lu to %lu "
+ "on NAND flash device #%s '%s'",
+ offset, offset + length - 1,
+ CMD_ARGV[0], p->device->name);
+ }
+
+ return retval;
+}
+
+COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
+{
+ int first = -1;
+ int last = -1;
+
+ if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2))
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct nand_device *p;
+ int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
+ if (ERROR_OK != retval)
+ return retval;
+
+ if (CMD_ARGC == 3) {
+ unsigned long offset;
+ unsigned long length;
+
+ COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
+ if (offset % p->erase_size)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ offset /= p->erase_size;
+
+ COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
+ if (length % p->erase_size)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ length -= 1;
+ length /= p->erase_size;
+
+ first = offset;
+ last = offset + length;
+ }
+
+ retval = nand_build_bbt(p, first, last);
+ if (retval == ERROR_OK) {
+ command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
+ "use \"nand info\" command to list blocks");
+ }
+
+ return retval;
+}
+
+COMMAND_HANDLER(handle_nand_write_command)
+{
+ struct nand_device *nand = NULL;
+ struct nand_fileio_state s;
+ int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
+ &s, &nand, FILEIO_READ, false, true);
+ if (ERROR_OK != retval)
+ return retval;
+
+ uint32_t total_bytes = s.size;
+ while (s.size > 0) {
+ int bytes_read = nand_fileio_read(nand, &s);
+ if (bytes_read <= 0) {
+ command_print(CMD_CTX, "error while reading file");
+ return nand_fileio_cleanup(&s);
+ }
+ s.size -= bytes_read;
+
+ retval = nand_write_page(nand, s.address / nand->page_size,
+ s.page, s.page_size, s.oob, s.oob_size);
+ if (ERROR_OK != retval) {
+ command_print(CMD_CTX, "failed writing file %s "
+ "to NAND flash %s at offset 0x%8.8" PRIx32,
+ CMD_ARGV[1], CMD_ARGV[0], s.address);
+ return nand_fileio_cleanup(&s);
+ }
+ s.address += s.page_size;
+ }
+
+ if (nand_fileio_finish(&s) == ERROR_OK) {
+ command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
+ "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
+ CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
+ duration_kbps(&s.bench, total_bytes));
+ }
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nand_verify_command)
+{
+ struct nand_device *nand = NULL;
+ struct nand_fileio_state file;
+ int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
+ &file, &nand, FILEIO_READ, false, true);
+ if (ERROR_OK != retval)
+ return retval;
+
+ struct nand_fileio_state dev;
+ nand_fileio_init(&dev);
+ dev.address = file.address;
+ dev.size = file.size;
+ dev.oob_format = file.oob_format;
+ retval = nand_fileio_start(CMD_CTX, nand, NULL, FILEIO_NONE, &dev);
+ if (ERROR_OK != retval)
+ return retval;
+
+ while (file.size > 0) {
+ retval = nand_read_page(nand, dev.address / dev.page_size,
+ dev.page, dev.page_size, dev.oob, dev.oob_size);
+ if (ERROR_OK != retval) {
+ command_print(CMD_CTX, "reading NAND flash page failed");
+ nand_fileio_cleanup(&dev);
+ nand_fileio_cleanup(&file);
+ return retval;
+ }
+
+ int bytes_read = nand_fileio_read(nand, &file);
+ if (bytes_read <= 0) {
+ command_print(CMD_CTX, "error while reading file");
+ nand_fileio_cleanup(&dev);
+ nand_fileio_cleanup(&file);
+ return ERROR_FAIL;
+ }
+
+ if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
+ (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size))) {
+ command_print(CMD_CTX, "NAND flash contents differ "
+ "at 0x%8.8" PRIx32, dev.address);
+ nand_fileio_cleanup(&dev);
+ nand_fileio_cleanup(&file);
+ return ERROR_FAIL;
+ }
+
+ file.size -= bytes_read;
+ dev.address += nand->page_size;
+ }
+
+ if (nand_fileio_finish(&file) == ERROR_OK) {
+ command_print(CMD_CTX, "verified file %s in NAND flash %s "
+ "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
+ CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
+ duration_kbps(&file.bench, dev.size));
+ }
+
+ return nand_fileio_cleanup(&dev);
+}
+
+COMMAND_HANDLER(handle_nand_dump_command)
+{
+ size_t filesize;
+ struct nand_device *nand = NULL;
+ struct nand_fileio_state s;
+ int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
+ &s, &nand, FILEIO_WRITE, true, false);
+ if (ERROR_OK != retval)
+ return retval;
+
+ while (s.size > 0) {
+ size_t size_written;
+ retval = nand_read_page(nand, s.address / nand->page_size,
+ s.page, s.page_size, s.oob, s.oob_size);
+ if (ERROR_OK != retval) {
+ command_print(CMD_CTX, "reading NAND flash page failed");
+ nand_fileio_cleanup(&s);
+ return retval;
+ }
+
+ if (NULL != s.page)
+ fileio_write(s.fileio, s.page_size, s.page, &size_written);
+
+ if (NULL != s.oob)
+ fileio_write(s.fileio, s.oob_size, s.oob, &size_written);
+
+ s.size -= nand->page_size;
+ s.address += nand->page_size;
+ }
+
+ retval = fileio_size(s.fileio, &filesize);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (nand_fileio_finish(&s) == ERROR_OK) {
+ command_print(CMD_CTX, "dumped %zu bytes in %fs (%0.3f KiB/s)",
+ filesize, duration_elapsed(&s.bench),
+ duration_kbps(&s.bench, filesize));
+ }
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nand_raw_access_command)
+{
+ if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct nand_device *p;
+ int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
+ if (ERROR_OK != retval)
+ return retval;
+
+ if (NULL == p->device) {
+ command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]);
+ return ERROR_OK;
+ }
+
+ if (CMD_ARGC == 2)
+ COMMAND_PARSE_ENABLE(CMD_ARGV[1], p->use_raw);
+
+ const char *msg = p->use_raw ? "enabled" : "disabled";
+ command_print(CMD_CTX, "raw access is %s", msg);
+
+ return ERROR_OK;
+}
+
+static const struct command_registration nand_exec_command_handlers[] = {
+ {
+ .name = "list",
+ .handler = handle_nand_list_command,
+ .mode = COMMAND_EXEC,
+ .help = "list configured NAND flash devices",
+ },
+ {
+ .name = "info",
+ .handler = handle_nand_info_command,
+ .mode = COMMAND_EXEC,
+ .usage = "[banknum | first_bank_num last_bank_num]",
+ .help = "print info about one or more NAND flash devices",
+ },
+ {
+ .name = "probe",
+ .handler = handle_nand_probe_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id",
+ .help = "identify NAND flash device",
+ },
+ {
+ .name = "check_bad_blocks",
+ .handler = handle_nand_check_bad_blocks_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id [offset length]",
+ .help = "check all or part of NAND flash device for bad blocks",
+ },
+ {
+ .name = "erase",
+ .handler = handle_nand_erase_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id [offset length]",
+ .help = "erase all or subset of blocks on NAND flash device",
+ },
+ {
+ .name = "dump",
+ .handler = handle_nand_dump_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id filename offset length "
+ "['oob_raw'|'oob_only']",
+ .help = "dump from NAND flash device",
+ },
+ {
+ .name = "verify",
+ .handler = handle_nand_verify_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id filename offset "
+ "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
+ .help = "verify NAND flash device",
+ },
+ {
+ .name = "write",
+ .handler = handle_nand_write_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id filename offset "
+ "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
+ .help = "write to NAND flash device",
+ },
+ {
+ .name = "raw_access",
+ .handler = handle_nand_raw_access_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id ['enable'|'disable']",
+ .help = "raw access to NAND flash device",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static int nand_init(struct command_context *cmd_ctx)
+{
+ if (!nand_devices)
+ return ERROR_OK;
+ struct command *parent = command_find_in_context(cmd_ctx, "nand");
+ return register_commands(cmd_ctx, parent, nand_exec_command_handlers);
+}
+
+COMMAND_HANDLER(handle_nand_init_command)
+{
+ if (CMD_ARGC != 0)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ static bool nand_initialized;
+ if (nand_initialized) {
+ LOG_INFO("'nand init' has already been called");
+ return ERROR_OK;
+ }
+ nand_initialized = true;
+
+ LOG_DEBUG("Initializing NAND devices...");
+ return nand_init(CMD_CTX);
+}
+
+static int nand_list_walker(struct nand_flash_controller *c, void *x)
+{
+ struct command_context *cmd_ctx = x;
+ command_print(cmd_ctx, " %s", c->name);
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nand_list_drivers)
+{
+ command_print(CMD_CTX, "Available NAND flash controller drivers:");
+ return nand_driver_walk(&nand_list_walker, CMD_CTX);
+}
+
+static COMMAND_HELPER(create_nand_device, const char *bank_name,
+ struct nand_flash_controller *controller)
+{
+ struct nand_device *c;
+ struct target *target;
+ int retval;
+
+ if (CMD_ARGC < 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ target = get_target(CMD_ARGV[1]);
+ if (!target) {
+ LOG_ERROR("invalid target %s", CMD_ARGV[1]);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ if (NULL != controller->commands) {
+ retval = register_commands(CMD_CTX, NULL,
+ controller->commands);
+ if (ERROR_OK != retval)
+ return retval;
+ }
+ c = malloc(sizeof(struct nand_device));
+ if (c == NULL) {
+ LOG_ERROR("End of memory");
+ return ERROR_FAIL;
+ }
+
+ c->name = strdup(bank_name);
+ c->target = target;
+ c->controller = controller;
+ c->controller_priv = NULL;
+ c->manufacturer = NULL;
+ c->device = NULL;
+ c->bus_width = 0;
+ c->address_cycles = 0;
+ c->page_size = 0;
+ c->use_raw = 0;
+ c->next = NULL;
+
+ retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
+ if (ERROR_OK != retval) {
+ LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
+ controller->name,
+ controller->usage);
+ free(c);
+ return retval;
+ }
+
+ if (controller->usage == NULL)
+ LOG_DEBUG("'%s' driver usage field missing", controller->name);
+
+ nand_device_add(c);
+
+ return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nand_device_command)
+{
+ if (CMD_ARGC < 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ /* save name and increment (for compatibility) with drivers */
+ const char *bank_name = *CMD_ARGV++;
+ CMD_ARGC--;
+
+ const char *driver_name = CMD_ARGV[0];
+ struct nand_flash_controller *controller;
+ controller = nand_driver_find_by_name(CMD_ARGV[0]);
+ if (NULL == controller) {
+ LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
+ return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
+ }
+ return CALL_COMMAND_HANDLER(create_nand_device, bank_name, controller);
+}
+
+static const struct command_registration nand_config_command_handlers[] = {
+ {
+ .name = "device",
+ .handler = &handle_nand_device_command,
+ .mode = COMMAND_CONFIG,
+ .help = "defines a new NAND bank",
+ .usage = "bank_id driver target [driver_options ...]",
+ },
+ {
+ .name = "drivers",
+ .handler = &handle_nand_list_drivers,
+ .mode = COMMAND_ANY,
+ .help = "lists available NAND drivers",
+ .usage = ""
+ },
+ {
+ .name = "init",
+ .mode = COMMAND_CONFIG,
+ .handler = &handle_nand_init_command,
+ .help = "initialize NAND devices",
+ .usage = ""
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration nand_command_handlers[] = {
+ {
+ .name = "nand",
+ .mode = COMMAND_ANY,
+ .help = "NAND flash command group",
+ .usage = "",
+ .chain = nand_config_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+int nand_register_commands(struct command_context *cmd_ctx)
+{
+ return register_commands(cmd_ctx, NULL, nand_command_handlers);
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/Makefile.am
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/Makefile.am b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/Makefile.am
new file mode 100755
index 0000000..b6a2be3
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/Makefile.am
@@ -0,0 +1,70 @@
+include $(top_srcdir)/common.mk
+
+noinst_LTLIBRARIES = libocdflashnor.la
+libocdflashnor_la_SOURCES = \
+ core.c \
+ tcl.c \
+ $(NOR_DRIVERS) \
+ drivers.c
+
+NOR_DRIVERS = \
+ aduc702x.c \
+ aducm360.c \
+ ambiqmicro.c \
+ at91sam4.c \
+ at91sam4l.c \
+ at91samd.c \
+ at91sam3.c \
+ at91sam7.c \
+ atsamv.c \
+ avrf.c \
+ cfi.c \
+ dsp5680xx_flash.c \
+ efm32.c \
+ em357.c \
+ faux.c \
+ fm3.c \
+ fm4.c \
+ jtagspi.c \
+ kinetis.c \
+ kinetis_ke.c \
+ lpc2000.c \
+ lpc288x.c \
+ lpc2900.c \
+ lpcspifi.c \
+ mdr.c \
+ mrvlqspi.c \
+ niietcm4.c \
+ non_cfi.c \
+ nrf51.c \
+ nrf52.c \
+ numicro.c \
+ ocl.c \
+ pic32mx.c \
+ psoc4.c \
+ sim3x.c \
+ spi.c \
+ stmsmi.c \
+ stellaris.c \
+ stm32f1x.c \
+ stm32f2x.c \
+ stm32lx.c \
+ stm32l4x.c \
+ str7x.c \
+ str9x.c \
+ str9xpec.c \
+ tms470.c \
+ virtual.c \
+ xmc1xxx.c \
+ xmc4xxx.c
+
+noinst_HEADERS = \
+ core.h \
+ cfi.h \
+ driver.h \
+ imp.h \
+ non_cfi.h \
+ ocl.h \
+ spi.h
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/Makefile.am.orig
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/Makefile.am.orig b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/Makefile.am.orig
new file mode 100755
index 0000000..b6a2be3
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/Makefile.am.orig
@@ -0,0 +1,70 @@
+include $(top_srcdir)/common.mk
+
+noinst_LTLIBRARIES = libocdflashnor.la
+libocdflashnor_la_SOURCES = \
+ core.c \
+ tcl.c \
+ $(NOR_DRIVERS) \
+ drivers.c
+
+NOR_DRIVERS = \
+ aduc702x.c \
+ aducm360.c \
+ ambiqmicro.c \
+ at91sam4.c \
+ at91sam4l.c \
+ at91samd.c \
+ at91sam3.c \
+ at91sam7.c \
+ atsamv.c \
+ avrf.c \
+ cfi.c \
+ dsp5680xx_flash.c \
+ efm32.c \
+ em357.c \
+ faux.c \
+ fm3.c \
+ fm4.c \
+ jtagspi.c \
+ kinetis.c \
+ kinetis_ke.c \
+ lpc2000.c \
+ lpc288x.c \
+ lpc2900.c \
+ lpcspifi.c \
+ mdr.c \
+ mrvlqspi.c \
+ niietcm4.c \
+ non_cfi.c \
+ nrf51.c \
+ nrf52.c \
+ numicro.c \
+ ocl.c \
+ pic32mx.c \
+ psoc4.c \
+ sim3x.c \
+ spi.c \
+ stmsmi.c \
+ stellaris.c \
+ stm32f1x.c \
+ stm32f2x.c \
+ stm32lx.c \
+ stm32l4x.c \
+ str7x.c \
+ str9x.c \
+ str9xpec.c \
+ tms470.c \
+ virtual.c \
+ xmc1xxx.c \
+ xmc4xxx.c
+
+noinst_HEADERS = \
+ core.h \
+ cfi.h \
+ driver.h \
+ imp.h \
+ non_cfi.h \
+ ocl.h \
+ spi.h
+
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/aduc702x.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/aduc702x.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/aduc702x.c
new file mode 100755
index 0000000..8852245
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/aduc702x.c
@@ -0,0 +1,406 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Kevin McGuire *
+ * Copyright (C) 2008 by Marcel Wijlaars *
+ * Copyright (C) 2009 by Michael Ashton *
+ * *
+ * 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. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ ***************************************************************************/
+
+#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/arm.h>
+
+static int aduc702x_build_sector_list(struct flash_bank *bank);
+static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms);
+static int aduc702x_set_write_enable(struct target *target, int enable);
+
+#define ADUC702x_FLASH 0xfffff800
+#define ADUC702x_FLASH_FEESTA (0*4)
+#define ADUC702x_FLASH_FEEMOD (1*4)
+#define ADUC702x_FLASH_FEECON (2*4)
+#define ADUC702x_FLASH_FEEDAT (3*4)
+#define ADUC702x_FLASH_FEEADR (4*4)
+#define ADUC702x_FLASH_FEESIGN (5*4)
+#define ADUC702x_FLASH_FEEPRO (6*4)
+#define ADUC702x_FLASH_FEEHIDE (7*4)
+
+/* flash bank aduc702x 0 0 0 0 <target#>
+ * The ADC7019-28 devices all have the same flash layout */
+FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
+{
+ bank->base = 0x80000;
+ bank->size = 0xF800; /* top 4k not accessible */
+
+ aduc702x_build_sector_list(bank);
+
+ return ERROR_OK;
+}
+
+static int aduc702x_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 / 512;
+ 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 = 512;
+ offset += bank->sectors[i].size;
+ bank->sectors[i].is_erased = -1;
+ bank->sectors[i].is_protected = 0;
+ }
+
+ return ERROR_OK;
+}
+
+static int aduc702x_protect_check(struct flash_bank *bank)
+{
+ printf("aduc702x_protect_check not implemented yet.\n");
+ return ERROR_OK;
+}
+
+static int aduc702x_erase(struct flash_bank *bank, int first, int last)
+{
+ /* int res; */
+ int x;
+ int count;
+ /* uint32_t v; */
+ struct target *target = bank->target;
+
+ aduc702x_set_write_enable(target, 1);
+
+ /* mass erase */
+ if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
+ LOG_DEBUG("performing mass erase.");
+ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, 0x3cff);
+ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, 0xffc3);
+ target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x06);
+
+ if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) {
+ LOG_ERROR("mass erase failed");
+ aduc702x_set_write_enable(target, 0);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ LOG_DEBUG("mass erase successful.");
+ return ERROR_OK;
+ } else {
+ unsigned long adr;
+
+ count = last - first + 1;
+ for (x = 0; x < count; ++x) {
+ adr = bank->base + ((first + x) * 512);
+
+ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, adr);
+ target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x05);
+
+ if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) {
+ LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
+ aduc702x_set_write_enable(target, 0);
+ return ERROR_FLASH_SECTOR_NOT_ERASED;
+ }
+
+ LOG_DEBUG("erased sector at address 0x%08lX", adr);
+ }
+ }
+
+ aduc702x_set_write_enable(target, 0);
+
+ return ERROR_OK;
+}
+
+static int aduc702x_protect(struct flash_bank *bank, int set, int first, int last)
+{
+ printf("aduc702x_protect not implemented yet.\n");
+ return ERROR_FLASH_OPERATION_FAILED;
+}
+
+/* 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 aduc702x_write_block(struct flash_bank *bank,
+ const uint8_t *buffer,
+ uint32_t offset,
+ uint32_t count)
+{
+ struct target *target = bank->target;
+ uint32_t buffer_size = 7000;
+ struct working_area *write_algorithm;
+ struct working_area *source;
+ uint32_t address = bank->base + offset;
+ struct reg_param reg_params[6];
+ struct arm_algorithm arm_algo;
+ int retval = ERROR_OK;
+
+ if (((count%2) != 0) || ((offset%2) != 0)) {
+ LOG_ERROR("write block must be multiple of two bytes in offset & length");
+ return ERROR_FAIL;
+ }
+
+ /* parameters:
+
+ r0 - address of source data (absolute)
+ r1 - number of halfwords to be copied
+ r2 - start address in flash (offset from beginning of flash memory)
+ r3 - exit code
+ r4 - base address of flash controller (0xFFFFF800)
+
+ registers:
+
+ r5 - scratch
+ r6 - set to 2, used to write flash command
+
+ */
+ static const uint32_t aduc702x_flash_write_code[] = {
+ /* <_start>: */
+ 0xe3a05008, /* mov r5, #8 ; 0x8 */
+ 0xe5845004, /* str r5, [r4, #4] */
+ 0xe3a06002, /* mov r6, #2 ; 0x2 */
+ /* <next>: */
+ 0xe1c421b0, /* strh r2, [r4, #16] */
+ 0xe0d050b2, /* ldrh r5, [r0], #2 */
+ 0xe1c450bc, /* strh r5, [r4, #12] */
+ 0xe5c46008, /* strb r6, [r4, #8] */
+ /* <wait_complete>: */
+ 0xe1d430b0, /* ldrh r3, [r4] */
+ 0xe3130004, /* tst r3, #4 ; 0x4 */
+ 0x1afffffc, /* bne 1001c <wait_complete> */
+ 0xe2822002, /* add r2, r2, #2 ; 0x2 */
+ 0xe2511001, /* subs r1, r1, #1 ; 0x1 */
+ 0x0a000001, /* beq 1003c <done> */
+ 0xe3130001, /* tst r3, #1 ; 0x1 */
+ 0x1afffff3, /* bne 1000c <next> */
+ /* <done>: */
+ 0xeafffffe /* b 1003c <done> */
+ };
+
+ /* flash write code */
+ if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code),
+ &write_algorithm) != ERROR_OK) {
+ LOG_WARNING("no working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ uint8_t code[sizeof(aduc702x_flash_write_code)];
+ target_buffer_set_u32_array(target, code, ARRAY_SIZE(aduc702x_flash_write_code),
+ aduc702x_flash_write_code);
+ retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* memory buffer */
+ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
+ buffer_size /= 2;
+ if (buffer_size <= 256) {
+ /* we already allocated the writing code, but failed to get a buffer,
+ *free the algorithm */
+ target_free_working_area(target, write_algorithm);
+
+ LOG_WARNING("no large enough working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ }
+
+ arm_algo.common_magic = ARM_COMMON_MAGIC;
+ arm_algo.core_mode = ARM_MODE_SVC;
+ arm_algo.core_state = ARM_STATE_ARM;
+
+ 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_IN);
+ init_reg_param(®_params[4], "r4", 32, PARAM_OUT);
+
+ while (count > 0) {
+ uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
+
+ retval = target_write_buffer(target, source->address, thisrun_count, buffer);
+ if (retval != ERROR_OK)
+ break;
+
+ buf_set_u32(reg_params[0].value, 0, 32, source->address);
+ buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
+ buf_set_u32(reg_params[2].value, 0, 32, address);
+ buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);
+
+ retval = target_run_algorithm(target, 0, NULL, 5,
+ reg_params, write_algorithm->address,
+ write_algorithm->address +
+ sizeof(aduc702x_flash_write_code) - 4,
+ 10000, &arm_algo);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("error executing aduc702x flash write algorithm");
+ break;
+ }
+
+ if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) {
+ /* FIX!!!! what does this mean??? replace w/sensible error message */
+ LOG_ERROR("aduc702x detected error writing flash");
+ retval = ERROR_FAIL;
+ break;
+ }
+
+ buffer += thisrun_count;
+ address += thisrun_count;
+ count -= thisrun_count;
+ }
+
+ target_free_working_area(target, source);
+ target_free_working_area(target, write_algorithm);
+
+ 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;
+}
+
+/* All-JTAG, single-access method. Very slow. Used only if there is no
+ * working area available. */
+static int aduc702x_write_single(struct flash_bank *bank,
+ const uint8_t *buffer,
+ uint32_t offset,
+ uint32_t count)
+{
+ uint32_t x;
+ uint8_t b;
+ struct target *target = bank->target;
+
+ aduc702x_set_write_enable(target, 1);
+
+ for (x = 0; x < count; x += 2) {
+ /* FEEADR = address */
+ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEADR, offset + x);
+
+ /* set up data */
+ if ((x + 1) == count) {
+ /* last byte */
+ target_read_u8(target, offset + x + 1, &b);
+ } else
+ b = buffer[x + 1];
+
+ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEDAT, buffer[x] | (b << 8));
+
+ /* do single-write command */
+ target_write_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEECON, 0x02);
+
+ if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) {
+ LOG_ERROR("single write failed for address 0x%08lX",
+ (unsigned long)(offset + x));
+ aduc702x_set_write_enable(target, 0);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ }
+ LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x));
+
+ aduc702x_set_write_enable(target, 0);
+
+ return ERROR_OK;
+}
+
+static int aduc702x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ int retval;
+
+ /* try using a block write */
+ retval = aduc702x_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 = aduc702x_write_single(bank, buffer, offset, count);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("slow write failed");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ }
+ }
+
+ return retval;
+}
+
+static int aduc702x_probe(struct flash_bank *bank)
+{
+ return ERROR_OK;
+}
+
+/* sets FEEMOD bit 3
+ * enable = 1 enables writes & erases, 0 disables them */
+static int aduc702x_set_write_enable(struct target *target, int enable)
+{
+ /* don't bother to preserve int enable bit here */
+ target_write_u16(target, ADUC702x_FLASH + ADUC702x_FLASH_FEEMOD, enable ? 8 : 0);
+
+ 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 aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms)
+{
+ uint8_t v = 4;
+
+ long long endtime = timeval_ms() + timeout_ms;
+ while (1) {
+ target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v);
+ if ((v & 4) == 0)
+ break;
+ alive_sleep(1);
+ if (timeval_ms() >= endtime)
+ break;
+ }
+
+ if (v & 2)
+ return ERROR_FAIL;
+ /* if a command is ignored, both the success and fail bits may be 0 */
+ else if ((v & 3) == 0)
+ return ERROR_FAIL;
+ else
+ return ERROR_OK;
+}
+
+struct flash_driver aduc702x_flash = {
+ .name = "aduc702x",
+ .flash_bank_command = aduc702x_flash_bank_command,
+ .erase = aduc702x_erase,
+ .protect = aduc702x_protect,
+ .write = aduc702x_write,
+ .read = default_flash_read,
+ .probe = aduc702x_probe,
+ .auto_probe = aduc702x_probe,
+ .erase_check = default_flash_blank_check,
+ .protect_check = aduc702x_protect_check,
+};
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/aducm360.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/aducm360.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/aducm360.c
new file mode 100755
index 0000000..3e446f5
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/aducm360.c
@@ -0,0 +1,580 @@
+/***************************************************************************
+ * Copyright (C) 2015 by Ivan Buliev *
+ * i.buliev@mikrosistemi.com *
+ * *
+ * 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 *
+ * Dominic.Rath@gmx.de *
+ * *
+ * Copyright (C) 2008 by Spencer Oliver *
+ * spen@spen-soft.co.uk *
+ * *
+ * Copyright (C) 2011 by Andreas Fritiofson *
+ * andreas.fritiofson@gmail.com *
+ ***************************************************************************/
+
+#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#> */
+FLASH_BANK_COMMAND_HANDLER(aducm360_flash_bank_command)
+{
+ 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)
+{
+ 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)
+{
+ LOG_WARNING("aducm360_protect_check not implemented.");
+ return ERROR_OK;
+}
+
+/* ----------------------------------------------------------------------- */
+static int aducm360_mass_erase(struct target *target)
+{
+ uint32_t value;
+ int res = ERROR_OK;
+
+ /* 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) {
+ LOG_ERROR("mass erase failed.");
+ aducm360_set_write_enable(target, 0);
+ res = ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ return res;
+}
+
+/* ----------------------------------------------------------------------- */
+static int aducm360_page_erase(struct target *target, uint32_t padd)
+{
+ uint32_t value;
+ int res = ERROR_OK;
+
+ /* 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) {
+ LOG_ERROR("page erase failed at 0x%08" PRIx32, padd);
+ aducm360_set_write_enable(target, 0);
+ res = ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ 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;
+
+ 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)
+{
+ LOG_ERROR("aducm360_protect not implemented.");
+ 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 retval = ERROR_OK;
+ uint32_t entry_point = 0, exit_point = 0;
+ uint32_t res;
+ struct armv7m_algorithm armv7m_algo;
+
+ 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
+ };
+
+ LOG_DEBUG("'aducm360_write_block_sync' requested, dst:0x%08" PRIx32 ", count:0x%08" PRIx32 "bytes.",
+ address, 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 ----- */
+ 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;
+ }
+
+ /* ----- Upload the helper code to the space in the target's RAM ----- */
+ 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;
+
+ /* ----- 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) {
+ LOG_WARNING("couldn't allocate a buffer space of 0x%08" PRIx32 "bytes in the target's SRAM.",
+ 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;
+ }
+ }
+
+ /* ----- 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! ===== */
+ while (count > 0) {
+ uint32_t thisrun_count = (count > target_buffer_size) ? target_buffer_size : 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*/
+
+ retval = target_run_algorithm(target, 0, NULL, 5,
+ reg_params, entry_point, exit_point, 10000, &armv7m_algo);
+ 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 */
+ 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
+ };
+
+ LOG_DEBUG("'aducm360_write_block_async' requested, dst:0x%08" PRIx32 ", count:0x%08" PRIx32 "bytes.",
+ address, 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 ----- */
+ 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;
+ }
+
+ /* ----- Upload the helper code to the space in the target's RAM ----- */
+ 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;
+
+ /* ----- 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) {
+ LOG_WARNING("couldn't allocate a buffer space of 0x%08" PRIx32 "bytes in the target's SRAM.",
+ 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;
+ }
+ }
+
+ /* ----- 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);
+
+ 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_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:
+ LOG_ERROR("aducm360_write_block was cancelled (no writing method was chosen)!");
+ 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, j, a, d;
+ struct target *target = bank->target;
+
+ LOG_DEBUG("performing slow write (offset=0x%08" PRIx32 ", count=0x%08" PRIx32 ")...",
+ offset, 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);
+
+ for (i = 0; i < count; i += 4) {
+ a = offset+i;
+ for (j = 0; i < 4; i += 1)
+ *((uint8_t *)(&d) + j) = buffer[i+j];
+ target_write_u32(target, a, d);
+ do {
+ target_read_u32(target, ADUCM360_FLASH_BASE + ADUCM360_FLASH_FEESTA, &value);
+ } while (!(value & FEESTA_WRDONE));
+ }
+ 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_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;
+ }
+
+ 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,
+};