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:10 UTC
[27/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/nor/fm3.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/fm3.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/fm3.c
new file mode 100755
index 0000000..d3d143f
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/fm3.c
@@ -0,0 +1,1002 @@
+/***************************************************************************
+ * Copyright (C) 2011 by Marc Willam, Holger Wech *
+ * openOCD.fseu(AT)de.fujitsu.com *
+ * Copyright (C) 2011 Ronny Strutz *
+ * *
+ * Copyright (C) 2013 Nemui Trinomius *
+ * nemuisan_kawausogasuki@live.jp *
+ * *
+ * 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 <target/algorithm.h>
+#include <target/armv7m.h>
+
+#define FLASH_DQ6 0x40 /* Data toggle flag bit (TOGG) position */
+#define FLASH_DQ5 0x20 /* Time limit exceeding flag bit (TLOV) position */
+
+enum fm3_variant {
+ mb9bfxx1, /* Flash Type '1' */
+ mb9bfxx2,
+ mb9bfxx3,
+ mb9bfxx4,
+ mb9bfxx5,
+ mb9bfxx6,
+ mb9bfxx7,
+ mb9bfxx8,
+
+ mb9afxx1, /* Flash Type '2' */
+ mb9afxx2,
+ mb9afxx3,
+ mb9afxx4,
+ mb9afxx5,
+ mb9afxx6,
+ mb9afxx7,
+ mb9afxx8,
+};
+
+enum fm3_flash_type {
+ fm3_no_flash_type = 0,
+ fm3_flash_type1 = 1,
+ fm3_flash_type2 = 2
+};
+
+struct fm3_flash_bank {
+ enum fm3_variant variant;
+ enum fm3_flash_type flashtype;
+ int probed;
+};
+
+FLASH_BANK_COMMAND_HANDLER(fm3_flash_bank_command)
+{
+ struct fm3_flash_bank *fm3_info;
+
+ if (CMD_ARGC < 6)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ fm3_info = malloc(sizeof(struct fm3_flash_bank));
+ bank->driver_priv = fm3_info;
+
+ /* Flash type '1' */
+ if (strcmp(CMD_ARGV[5], "mb9bfxx1.cpu") == 0) {
+ fm3_info->variant = mb9bfxx1;
+ fm3_info->flashtype = fm3_flash_type1;
+ } else if (strcmp(CMD_ARGV[5], "mb9bfxx2.cpu") == 0) {
+ fm3_info->variant = mb9bfxx2;
+ fm3_info->flashtype = fm3_flash_type1;
+ } else if (strcmp(CMD_ARGV[5], "mb9bfxx3.cpu") == 0) {
+ fm3_info->variant = mb9bfxx3;
+ fm3_info->flashtype = fm3_flash_type1;
+ } else if (strcmp(CMD_ARGV[5], "mb9bfxx4.cpu") == 0) {
+ fm3_info->variant = mb9bfxx4;
+ fm3_info->flashtype = fm3_flash_type1;
+ } else if (strcmp(CMD_ARGV[5], "mb9bfxx5.cpu") == 0) {
+ fm3_info->variant = mb9bfxx5;
+ fm3_info->flashtype = fm3_flash_type1;
+ } else if (strcmp(CMD_ARGV[5], "mb9bfxx6.cpu") == 0) {
+ fm3_info->variant = mb9bfxx6;
+ fm3_info->flashtype = fm3_flash_type1;
+ } else if (strcmp(CMD_ARGV[5], "mb9bfxx7.cpu") == 0) {
+ fm3_info->variant = mb9bfxx7;
+ fm3_info->flashtype = fm3_flash_type1;
+ } else if (strcmp(CMD_ARGV[5], "mb9bfxx8.cpu") == 0) {
+ fm3_info->variant = mb9bfxx8;
+ fm3_info->flashtype = fm3_flash_type1;
+ } else if (strcmp(CMD_ARGV[5], "mb9afxx1.cpu") == 0) { /* Flash type '2' */
+ fm3_info->variant = mb9afxx1;
+ fm3_info->flashtype = fm3_flash_type2;
+ } else if (strcmp(CMD_ARGV[5], "mb9afxx2.cpu") == 0) {
+ fm3_info->variant = mb9afxx2;
+ fm3_info->flashtype = fm3_flash_type2;
+ } else if (strcmp(CMD_ARGV[5], "mb9afxx3.cpu") == 0) {
+ fm3_info->variant = mb9afxx3;
+ fm3_info->flashtype = fm3_flash_type2;
+ } else if (strcmp(CMD_ARGV[5], "mb9afxx4.cpu") == 0) {
+ fm3_info->variant = mb9afxx4;
+ fm3_info->flashtype = fm3_flash_type2;
+ } else if (strcmp(CMD_ARGV[5], "mb9afxx5.cpu") == 0) {
+ fm3_info->variant = mb9afxx5;
+ fm3_info->flashtype = fm3_flash_type2;
+ } else if (strcmp(CMD_ARGV[5], "mb9afxx6.cpu") == 0) {
+ fm3_info->variant = mb9afxx6;
+ fm3_info->flashtype = fm3_flash_type2;
+ } else if (strcmp(CMD_ARGV[5], "mb9afxx7.cpu") == 0) {
+ fm3_info->variant = mb9afxx7;
+ fm3_info->flashtype = fm3_flash_type2;
+ } else if (strcmp(CMD_ARGV[5], "mb9afxx8.cpu") == 0) {
+ fm3_info->variant = mb9afxx8;
+ fm3_info->flashtype = fm3_flash_type2;
+ }
+
+ /* unknown Flash type */
+ else {
+ LOG_ERROR("unknown fm3 variant: %s", CMD_ARGV[5]);
+ free(fm3_info);
+ return ERROR_FLASH_BANK_INVALID;
+ }
+
+ fm3_info->probed = 0;
+
+ return ERROR_OK;
+}
+
+/* Data polling algorithm */
+static int fm3_busy_wait(struct target *target, uint32_t offset, int timeout_ms)
+{
+ int retval = ERROR_OK;
+ uint8_t state1, state2;
+ int ms = 0;
+
+ /* While(1) loop exit via "break" and "return" on error */
+ while (1) {
+ /* dummy-read - see flash manual */
+ retval = target_read_u8(target, offset, &state1);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Data polling 1 */
+ retval = target_read_u8(target, offset, &state1);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Data polling 2 */
+ retval = target_read_u8(target, offset, &state2);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Flash command finished via polled data equal? */
+ if ((state1 & FLASH_DQ6) == (state2 & FLASH_DQ6))
+ break;
+ /* Timeout Flag? */
+ else if (state1 & FLASH_DQ5) {
+ /* Retry data polling */
+
+ /* Data polling 1 */
+ retval = target_read_u8(target, offset, &state1);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Data polling 2 */
+ retval = target_read_u8(target, offset, &state2);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Flash command finished via polled data equal? */
+ if ((state1 & FLASH_DQ6) != (state2 & FLASH_DQ6))
+ return ERROR_FLASH_OPERATION_FAILED;
+
+ /* finish anyway */
+ break;
+ }
+ usleep(1000);
+ ++ms;
+
+ /* Polling time exceeded? */
+ if (ms > timeout_ms) {
+ LOG_ERROR("Polling data reading timed out!");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ }
+
+ if (retval == ERROR_OK)
+ LOG_DEBUG("fm3_busy_wait(%" PRIx32 ") needs about %d ms", offset, ms);
+
+ return retval;
+}
+
+static int fm3_erase(struct flash_bank *bank, int first, int last)
+{
+ struct fm3_flash_bank *fm3_info = bank->driver_priv;
+ struct target *target = bank->target;
+ int retval = ERROR_OK;
+ uint32_t u32DummyRead;
+ int sector, odd;
+ uint32_t u32FlashType;
+ uint32_t u32FlashSeqAddress1;
+ uint32_t u32FlashSeqAddress2;
+
+ struct working_area *write_algorithm;
+ struct reg_param reg_params[3];
+ struct armv7m_algorithm armv7m_info;
+
+ u32FlashType = (uint32_t) fm3_info->flashtype;
+
+ if (u32FlashType == fm3_flash_type1) {
+ u32FlashSeqAddress1 = 0x00001550;
+ u32FlashSeqAddress2 = 0x00000AA8;
+ } else if (u32FlashType == fm3_flash_type2) {
+ u32FlashSeqAddress1 = 0x00000AA8;
+ u32FlashSeqAddress2 = 0x00000554;
+ } else {
+ LOG_ERROR("Flash/Device type unknown!");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ /* RAMCODE used for fm3 Flash sector erase: */
+ /* R0 keeps Flash Sequence address 1 (u32FlashSeq1) */
+ /* R1 keeps Flash Sequence address 2 (u32FlashSeq2) */
+ /* R2 keeps Flash Offset address (ofs) */
+ static const uint8_t fm3_flash_erase_sector_code[] = {
+ /* *(uint16_t*)u32FlashSeq1 = 0xAA; */
+ 0xAA, 0x24, /* MOVS R4, #0xAA */
+ 0x04, 0x80, /* STRH R4, [R0, #0] */
+ /* *(uint16_t*)u32FlashSeq2 = 0x55; */
+ 0x55, 0x23, /* MOVS R3, #0x55 */
+ 0x0B, 0x80, /* STRH R3, [R1, #0] */
+ /* *(uint16_t*)u32FlashSeq1 = 0x80; */
+ 0x80, 0x25, /* MOVS R5, #0x80 */
+ 0x05, 0x80, /* STRH R5, [R0, #0] */
+ /* *(uint16_t*)u32FlashSeq1 = 0xAA; */
+ 0x04, 0x80, /* STRH R4, [R0, #0] */
+ /* *(uint16_t*)u32FlashSeq2 = 0x55; */
+ 0x0B, 0x80, /* STRH R3, [R1, #0] */
+ /* Sector_Erase Command (0x30) */
+ /* *(uint16_t*)ofs = 0x30; */
+ 0x30, 0x20, /* MOVS R0, #0x30 */
+ 0x10, 0x80, /* STRH R0, [R2, #0] */
+ /* End Code */
+ 0x00, 0xBE, /* BKPT #0 */
+ };
+
+ LOG_INFO("Fujitsu MB9[A/B]FXXX: Sector Erase ... (%d to %d)", first, last);
+
+ /* disable HW watchdog */
+ retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, 0x40011008, 0x00000000);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash acccess) */
+ retval = target_write_u32(target, 0x40000000, 0x0001);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* dummy read of FASZR */
+ retval = target_read_u32(target, 0x40000000, &u32DummyRead);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* allocate working area with flash sector erase code */
+ if (target_alloc_working_area(target, sizeof(fm3_flash_erase_sector_code),
+ &write_algorithm) != ERROR_OK) {
+ LOG_WARNING("no working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ retval = target_write_buffer(target, write_algorithm->address,
+ sizeof(fm3_flash_erase_sector_code), fm3_flash_erase_sector_code);
+ if (retval != ERROR_OK)
+ return retval;
+
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
+
+ init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* u32FlashSeqAddress1 */
+ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* u32FlashSeqAddress2 */
+ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* offset */
+
+ /* write code buffer and use Flash sector erase code within fm3 */
+ for (sector = first ; sector <= last ; sector++) {
+ uint32_t offset = bank->sectors[sector].offset;
+
+ for (odd = 0; odd < 2 ; odd++) {
+ if (odd)
+ offset += 4;
+
+ buf_set_u32(reg_params[0].value, 0, 32, u32FlashSeqAddress1);
+ buf_set_u32(reg_params[1].value, 0, 32, u32FlashSeqAddress2);
+ buf_set_u32(reg_params[2].value, 0, 32, offset);
+
+ retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
+ write_algorithm->address, 0, 100000, &armv7m_info);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error executing flash erase programming algorithm");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ return retval;
+ }
+
+ retval = fm3_busy_wait(target, offset, 500);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ bank->sectors[sector].is_erased = 1;
+ }
+
+ target_free_working_area(target, write_algorithm);
+ destroy_reg_param(®_params[0]);
+ destroy_reg_param(®_params[1]);
+ destroy_reg_param(®_params[2]);
+
+ /* FASZR = 0x02, Enables CPU Run Mode (32-bit Flash acccess) */
+ retval = target_write_u32(target, 0x40000000, 0x0002);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
+
+ return retval;
+}
+
+static int fm3_write_block(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ struct fm3_flash_bank *fm3_info = bank->driver_priv;
+ struct target *target = bank->target;
+ uint32_t buffer_size = 2048; /* Default minimum value */
+ struct working_area *write_algorithm;
+ struct working_area *source;
+ uint32_t address = bank->base + offset;
+ struct reg_param reg_params[6];
+ struct armv7m_algorithm armv7m_info;
+ int retval = ERROR_OK;
+ uint32_t u32FlashType;
+ uint32_t u32FlashSeqAddress1;
+ uint32_t u32FlashSeqAddress2;
+
+ /* Increase buffer_size if needed */
+ if (buffer_size < (target->working_area_size / 2))
+ buffer_size = (target->working_area_size / 2);
+
+ u32FlashType = (uint32_t) fm3_info->flashtype;
+
+ if (u32FlashType == fm3_flash_type1) {
+ u32FlashSeqAddress1 = 0x00001550;
+ u32FlashSeqAddress2 = 0x00000AA8;
+ } else if (u32FlashType == fm3_flash_type2) {
+ u32FlashSeqAddress1 = 0x00000AA8;
+ u32FlashSeqAddress2 = 0x00000554;
+ } else {
+ LOG_ERROR("Flash/Device type unknown!");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* RAMCODE used for fm3 Flash programming: */
+ /* R0 keeps source start address (u32Source) */
+ /* R1 keeps target start address (u32Target) */
+ /* R2 keeps number of halfwords to write (u32Count) */
+ /* R3 keeps Flash Sequence address 1 (u32FlashSeq1) */
+ /* R4 keeps Flash Sequence address 2 (u32FlashSeq2) */
+ /* R5 returns result value (u32FlashResult) */
+
+ static const uint8_t fm3_flash_write_code[] = {
+ /* fm3_FLASH_IF->FASZ &= 0xFFFD; */
+ 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
+ 0x2D, 0x68, /* LDR R5, [R5] */
+ 0x4F, 0xF6, 0xFD, 0x76, /* MOVW R6, #0xFFFD */
+ 0x35, 0x40, /* ANDS R5, R5, R6 */
+ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
+ 0x35, 0x60, /* STR R5, [R6] */
+ /* fm3_FLASH_IF->FASZ |= 1; */
+ 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
+ 0x2D, 0x68, /* LDR R5, [R3] */
+ 0x55, 0xF0, 0x01, 0x05, /* ORRS.W R5, R5, #1 */
+ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
+ 0x35, 0x60, /* STR R5, [R6] */
+ /* u32DummyRead = fm3_FLASH_IF->FASZ; */
+ 0x28, 0x4D, /* LDR.N R5, ??u32DummyRead */
+ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
+ 0x36, 0x68, /* LDR R6, [R6] */
+ 0x2E, 0x60, /* STR R6, [R5] */
+ /* u32FlashResult = FLASH_WRITE_NO_RESULT */
+ 0x26, 0x4D, /* LDR.N R5, ??u32FlashResult */
+ 0x00, 0x26, /* MOVS R6, #0 */
+ 0x2E, 0x60, /* STR R6, [R5] */
+ /* while ((u32Count > 0 ) */
+ /* && (u32FlashResult */
+ /* == FLASH_WRITE_NO_RESULT)) */
+ 0x01, 0x2A, /* L0: CMP R2, #1 */
+ 0x2C, 0xDB, /* BLT.N L1 */
+ 0x24, 0x4D, /* LDR.N R5, ??u32FlashResult */
+ 0x2D, 0x68, /* LDR R5, [R5] */
+ 0x00, 0x2D, /* CMP R5, #0 */
+ 0x28, 0xD1, /* BNE.N L1 */
+ /* *u32FlashSeq1 = FLASH_WRITE_1; */
+ 0xAA, 0x25, /* MOVS R5, #0xAA */
+ 0x1D, 0x60, /* STR R5, [R3] */
+ /* *u32FlashSeq2 = FLASH_WRITE_2; */
+ 0x55, 0x25, /* MOVS R5, #0x55 */
+ 0x25, 0x60, /* STR R5, [R4] */
+ /* *u32FlashSeq1 = FLASH_WRITE_3; */
+ 0xA0, 0x25, /* MOVS R5, #0xA0 */
+ 0x1D, 0x60, /* STRH R5, [R3] */
+ /* *(volatile uint16_t*)u32Target */
+ /* = *(volatile uint16_t*)u32Source; */
+ 0x05, 0x88, /* LDRH R5, [R0] */
+ 0x0D, 0x80, /* STRH R5, [R1] */
+ /* while (u32FlashResult */
+ /* == FLASH_WRITE_NO_RESTULT) */
+ 0x1E, 0x4D, /* L2: LDR.N R5, ??u32FlashResult */
+ 0x2D, 0x68, /* LDR R5, [R5] */
+ 0x00, 0x2D, /* CMP R5, #0 */
+ 0x11, 0xD1, /* BNE.N L3 */
+ /* if ((*(volatile uint16_t*)u32Target */
+ /* & FLASH_DQ5) == FLASH_DQ5) */
+ 0x0D, 0x88, /* LDRH R5, [R1] */
+ 0xAD, 0x06, /* LSLS R5, R5, #0x1A */
+ 0x02, 0xD5, /* BPL.N L4 */
+ /* u32FlashResult = FLASH_WRITE_TIMEOUT */
+ 0x1A, 0x4D, /* LDR.N R5, ??u32FlashResult */
+ 0x02, 0x26, /* MOVS R6, #2 */
+ 0x2E, 0x60, /* STR R6, [R5] */
+ /* if ((*(volatile uint16_t *)u32Target */
+ /* & FLASH_DQ7) */
+ /* == (*(volatile uint16_t*)u32Source */
+ /* & FLASH_DQ7)) */
+ 0x0D, 0x88, /* L4: LDRH R5, [R1] */
+ 0x15, 0xF0, 0x80, 0x05, /* ANDS.W R5, R5, #0x80 */
+ 0x06, 0x88, /* LDRH R6, [R0] */
+ 0x16, 0xF0, 0x80, 0x06, /* ANDS.W R6, R6, #0x80 */
+ 0xB5, 0x42, /* CMP R5, R6 */
+ 0xED, 0xD1, /* BNE.N L2 */
+ /* u32FlashResult = FLASH_WRITE_OKAY */
+ 0x15, 0x4D, /* LDR.N R5, ??u32FlashResult */
+ 0x01, 0x26, /* MOVS R6, #1 */
+ 0x2E, 0x60, /* STR R6, [R5] */
+ 0xE9, 0xE7, /* B.N L2 */
+ /* if (u32FlashResult */
+ /* != FLASH_WRITE_TIMEOUT) */
+ 0x13, 0x4D, /* LDR.N R5, ??u32FlashResult */
+ 0x2D, 0x68, /* LDR R5, [R5] */
+ 0x02, 0x2D, /* CMP R5, #2 */
+ 0x02, 0xD0, /* BEQ.N L5 */
+ /* u32FlashResult = FLASH_WRITE_NO_RESULT */
+ 0x11, 0x4D, /* LDR.N R5, ??u32FlashResult */
+ 0x00, 0x26, /* MOVS R6, #0 */
+ 0x2E, 0x60, /* STR R6, [R5] */
+ /* u32Count--; */
+ 0x52, 0x1E, /* L5: SUBS R2, R2, #1 */
+ /* u32Source += 2; */
+ 0x80, 0x1C, /* ADDS R0, R0, #2 */
+ /* u32Target += 2; */
+ 0x89, 0x1C, /* ADDS R1, R1, #2 */
+ 0xD0, 0xE7, /* B.N L0 */
+ /* fm3_FLASH_IF->FASZ &= 0xFFFE; */
+ 0x5F, 0xF0, 0x80, 0x45, /* L1: MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
+ 0x2D, 0x68, /* LDR R5, [R5] */
+ 0x4F, 0xF6, 0xFE, 0x76, /* MOVW R6, #0xFFFE */
+ 0x35, 0x40, /* ANDS R5, R5, R6 */
+ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
+ 0x35, 0x60, /* STR R5, [R6] */
+ /* fm3_FLASH_IF->FASZ |= 2; */
+ 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
+ 0x2D, 0x68, /* LDR R5, [R5] */
+ 0x55, 0xF0, 0x02, 0x05, /* ORRS.W R5, R5, #2 */
+ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
+ 0x35, 0x60, /* STR R5, [R6] */
+ /* u32DummyRead = fm3_FLASH_IF->FASZ; */
+ 0x04, 0x4D, /* LDR.N R5, ??u32DummyRead */
+ 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
+ 0x36, 0x68, /* LDR R6, [R6] */
+ 0x2E, 0x60, /* STR R6, [R5] */
+ /* copy u32FlashResult to R3 for return */
+ /* value */
+ 0xDF, 0xF8, 0x08, 0x50, /* LDR.W R5, ??u32FlashResult */
+ 0x2D, 0x68, /* LDR R5, [R5] */
+ /* Breakpoint here */
+ 0x00, 0xBE, /* BKPT #0 */
+
+ /* The following address pointers assume, that the code is running from */
+ /* SRAM basic-address + 8.These address pointers will be patched, if a */
+ /* different start address in RAM is used (e.g. for Flash type 2)! */
+ /* Default SRAM basic-address is 0x20000000. */
+ 0x00, 0x00, 0x00, 0x20, /* u32DummyRead address in RAM (0x20000000) */
+ 0x04, 0x00, 0x00, 0x20 /* u32FlashResult address in RAM (0x20000004) */
+ };
+
+ LOG_INFO("Fujitsu MB9[A/B]FXXX: FLASH Write ...");
+
+ /* disable HW watchdog */
+ retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, 0x40011008, 0x00000000);
+ if (retval != ERROR_OK)
+ return retval;
+
+ count = count / 2; /* number bytes -> number halfwords */
+
+ /* check code alignment */
+ if (offset & 0x1) {
+ LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
+ return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+ }
+
+ /* allocate working area and variables with flash programming code */
+ if (target_alloc_working_area(target, sizeof(fm3_flash_write_code) + 8,
+ &write_algorithm) != ERROR_OK) {
+ LOG_WARNING("no working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ retval = target_write_buffer(target, write_algorithm->address + 8,
+ sizeof(fm3_flash_write_code), fm3_flash_write_code);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Patching 'local variable address' */
+ /* Algorithm: u32DummyRead: */
+ retval = target_write_u32(target, (write_algorithm->address + 8)
+ + sizeof(fm3_flash_write_code) - 8, (write_algorithm->address));
+ if (retval != ERROR_OK)
+ return retval;
+ /* Algorithm: u32FlashResult: */
+ retval = target_write_u32(target, (write_algorithm->address + 8)
+ + sizeof(fm3_flash_write_code) - 4, (write_algorithm->address) + 4);
+ if (retval != ERROR_OK)
+ return retval;
+
+
+
+ /* memory buffer */
+ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
+ buffer_size /= 2;
+ if (buffer_size <= 256) {
+ /* free working area, write algorithm already allocated */
+ 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;
+ }
+ }
+
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
+
+ init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* source start address */
+ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* target start address */
+ init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of halfwords to program */
+ init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* Flash Sequence address 1 */
+ init_reg_param(®_params[4], "r4", 32, PARAM_OUT); /* Flash Sequence address 1 */
+ init_reg_param(®_params[5], "r5", 32, PARAM_IN); /* result */
+
+ /* write code buffer and use Flash programming code within fm3 */
+ /* Set breakpoint to 0 with time-out of 1000 ms */
+ while (count > 0) {
+ uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
+
+ retval = target_write_buffer(target, source->address, thisrun_count * 2, 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, address);
+ buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
+ buf_set_u32(reg_params[3].value, 0, 32, u32FlashSeqAddress1);
+ buf_set_u32(reg_params[4].value, 0, 32, u32FlashSeqAddress2);
+
+ retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
+ (write_algorithm->address + 8), 0, 1000, &armv7m_info);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error executing fm3 Flash programming algorithm");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ }
+
+ if (buf_get_u32(reg_params[5].value, 0, 32) != ERROR_OK) {
+ LOG_ERROR("Fujitsu MB9[A/B]FXXX: Flash programming ERROR (Timeout) -> Reg R3: %" PRIx32,
+ buf_get_u32(reg_params[5].value, 0, 32));
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ break;
+ }
+
+ buffer += thisrun_count * 2;
+ address += thisrun_count * 2;
+ 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]);
+ destroy_reg_param(®_params[5]);
+
+ return retval;
+}
+
+static int fm3_probe(struct flash_bank *bank)
+{
+ struct fm3_flash_bank *fm3_info = bank->driver_priv;
+ uint16_t num_pages;
+
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+/*
+ -- page-- start -- blocksize - mpu - totalFlash --
+ page0 0x00000 16k
+ page1 0x04000 16k
+ page2 0x08000 96k ___ fxx3 128k Flash
+ page3 0x20000 128k ___ fxx4 256k Flash
+ page4 0x40000 128k ___ fxx5 384k Flash
+ page5 0x60000 128k ___ fxx6 512k Flash
+-----------------------
+ page6 0x80000 128k
+ page7 0xa0000 128k ___ fxx7 256k Flash
+ page8 0xc0000 128k
+ page9 0xe0000 128k ___ fxx8 256k Flash
+ */
+
+ num_pages = 10; /* max number of Flash pages for malloc */
+ fm3_info->probed = 0;
+
+ bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
+ bank->base = 0x00000000;
+ bank->size = 32 * 1024; /* bytes */
+
+ bank->sectors[0].offset = 0;
+ bank->sectors[0].size = 16 * 1024;
+ bank->sectors[0].is_erased = -1;
+ bank->sectors[0].is_protected = -1;
+
+ bank->sectors[1].offset = 0x4000;
+ bank->sectors[1].size = 16 * 1024;
+ bank->sectors[1].is_erased = -1;
+ bank->sectors[1].is_protected = -1;
+
+ if ((fm3_info->variant == mb9bfxx1)
+ || (fm3_info->variant == mb9afxx1)) {
+ num_pages = 3;
+ bank->size = 64 * 1024; /* bytes */
+ bank->num_sectors = num_pages;
+
+ bank->sectors[2].offset = 0x8000;
+ bank->sectors[2].size = 32 * 1024;
+ bank->sectors[2].is_erased = -1;
+ bank->sectors[2].is_protected = -1;
+ }
+
+ if ((fm3_info->variant == mb9bfxx2)
+ || (fm3_info->variant == mb9bfxx4)
+ || (fm3_info->variant == mb9bfxx5)
+ || (fm3_info->variant == mb9bfxx6)
+ || (fm3_info->variant == mb9bfxx7)
+ || (fm3_info->variant == mb9bfxx8)
+ || (fm3_info->variant == mb9afxx2)
+ || (fm3_info->variant == mb9afxx4)
+ || (fm3_info->variant == mb9afxx5)
+ || (fm3_info->variant == mb9afxx6)
+ || (fm3_info->variant == mb9afxx7)
+ || (fm3_info->variant == mb9afxx8)) {
+ num_pages = 3;
+ bank->size = 128 * 1024; /* bytes */
+ bank->num_sectors = num_pages;
+
+ bank->sectors[2].offset = 0x8000;
+ bank->sectors[2].size = 96 * 1024;
+ bank->sectors[2].is_erased = -1;
+ bank->sectors[2].is_protected = -1;
+ }
+
+ if ((fm3_info->variant == mb9bfxx4)
+ || (fm3_info->variant == mb9bfxx5)
+ || (fm3_info->variant == mb9bfxx6)
+ || (fm3_info->variant == mb9bfxx7)
+ || (fm3_info->variant == mb9bfxx8)
+ || (fm3_info->variant == mb9afxx4)
+ || (fm3_info->variant == mb9afxx5)
+ || (fm3_info->variant == mb9afxx6)
+ || (fm3_info->variant == mb9afxx7)
+ || (fm3_info->variant == mb9afxx8)) {
+ num_pages = 4;
+ bank->size = 256 * 1024; /* bytes */
+ bank->num_sectors = num_pages;
+
+ bank->sectors[3].offset = 0x20000;
+ bank->sectors[3].size = 128 * 1024;
+ bank->sectors[3].is_erased = -1;
+ bank->sectors[3].is_protected = -1;
+ }
+
+ if ((fm3_info->variant == mb9bfxx5)
+ || (fm3_info->variant == mb9bfxx6)
+ || (fm3_info->variant == mb9bfxx7)
+ || (fm3_info->variant == mb9bfxx8)
+ || (fm3_info->variant == mb9afxx5)
+ || (fm3_info->variant == mb9afxx6)
+ || (fm3_info->variant == mb9afxx7)
+ || (fm3_info->variant == mb9afxx8)) {
+ num_pages = 5;
+ bank->size = 384 * 1024; /* bytes */
+ bank->num_sectors = num_pages;
+
+ bank->sectors[4].offset = 0x40000;
+ bank->sectors[4].size = 128 * 1024;
+ bank->sectors[4].is_erased = -1;
+ bank->sectors[4].is_protected = -1;
+ }
+
+ if ((fm3_info->variant == mb9bfxx6)
+ || (fm3_info->variant == mb9bfxx7)
+ || (fm3_info->variant == mb9bfxx8)
+ || (fm3_info->variant == mb9afxx6)
+ || (fm3_info->variant == mb9afxx7)
+ || (fm3_info->variant == mb9afxx8)) {
+ num_pages = 6;
+ bank->size = 512 * 1024; /* bytes */
+ bank->num_sectors = num_pages;
+
+ bank->sectors[5].offset = 0x60000;
+ bank->sectors[5].size = 128 * 1024;
+ bank->sectors[5].is_erased = -1;
+ bank->sectors[5].is_protected = -1;
+ }
+
+ if ((fm3_info->variant == mb9bfxx7)
+ || (fm3_info->variant == mb9bfxx8)
+ || (fm3_info->variant == mb9afxx7)
+ || (fm3_info->variant == mb9afxx8)) {
+ num_pages = 8;
+ bank->size = 768 * 1024; /* bytes */
+ bank->num_sectors = num_pages;
+
+ bank->sectors[6].offset = 0x80000;
+ bank->sectors[6].size = 128 * 1024;
+ bank->sectors[6].is_erased = -1;
+ bank->sectors[6].is_protected = -1;
+
+ bank->sectors[7].offset = 0xa0000;
+ bank->sectors[7].size = 128 * 1024;
+ bank->sectors[7].is_erased = -1;
+ bank->sectors[7].is_protected = -1;
+ }
+
+ if ((fm3_info->variant == mb9bfxx8)
+ || (fm3_info->variant == mb9afxx8)) {
+ num_pages = 10;
+ bank->size = 1024 * 1024; /* bytes */
+ bank->num_sectors = num_pages;
+
+ bank->sectors[8].offset = 0xc0000;
+ bank->sectors[8].size = 128 * 1024;
+ bank->sectors[8].is_erased = -1;
+ bank->sectors[8].is_protected = -1;
+
+ bank->sectors[9].offset = 0xe0000;
+ bank->sectors[9].size = 128 * 1024;
+ bank->sectors[9].is_erased = -1;
+ bank->sectors[9].is_protected = -1;
+ }
+
+ fm3_info->probed = 1;
+
+ return ERROR_OK;
+}
+
+static int fm3_auto_probe(struct flash_bank *bank)
+{
+ struct fm3_flash_bank *fm3_info = bank->driver_priv;
+ if (fm3_info->probed)
+ return ERROR_OK;
+ return fm3_probe(bank);
+}
+
+/* Chip erase */
+static int fm3_chip_erase(struct flash_bank *bank)
+{
+ struct target *target = bank->target;
+ struct fm3_flash_bank *fm3_info2 = bank->driver_priv;
+ int retval = ERROR_OK;
+ uint32_t u32DummyRead;
+ uint32_t u32FlashType;
+ uint32_t u32FlashSeqAddress1;
+ uint32_t u32FlashSeqAddress2;
+
+ struct working_area *write_algorithm;
+ struct reg_param reg_params[3];
+ struct armv7m_algorithm armv7m_info;
+
+ u32FlashType = (uint32_t) fm3_info2->flashtype;
+
+ if (u32FlashType == fm3_flash_type1) {
+ LOG_INFO("*** Erasing mb9bfxxx type");
+ u32FlashSeqAddress1 = 0x00001550;
+ u32FlashSeqAddress2 = 0x00000AA8;
+ } else if (u32FlashType == fm3_flash_type2) {
+ LOG_INFO("*** Erasing mb9afxxx type");
+ u32FlashSeqAddress1 = 0x00000AA8;
+ u32FlashSeqAddress2 = 0x00000554;
+ } else {
+ LOG_ERROR("Flash/Device type unknown!");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ /* RAMCODE used for fm3 Flash chip erase: */
+ /* R0 keeps Flash Sequence address 1 (u32FlashSeq1) */
+ /* R1 keeps Flash Sequence address 2 (u32FlashSeq2) */
+ static const uint8_t fm3_flash_erase_chip_code[] = {
+ /* *(uint16_t*)u32FlashSeq1 = 0xAA; */
+ 0xAA, 0x22, /* MOVS R2, #0xAA */
+ 0x02, 0x80, /* STRH R2, [R0, #0] */
+ /* *(uint16_t*)u32FlashSeq2 = 0x55; */
+ 0x55, 0x23, /* MOVS R3, #0x55 */
+ 0x0B, 0x80, /* STRH R3, [R1, #0] */
+ /* *(uint16_t*)u32FlashSeq1 = 0x80; */
+ 0x80, 0x24, /* MOVS R4, #0x80 */
+ 0x04, 0x80, /* STRH R4, [R0, #0] */
+ /* *(uint16_t*)u32FlashSeq1 = 0xAA; */
+ 0x02, 0x80, /* STRH R2, [R0, #0] */
+ /* *(uint16_t*)u32FlashSeq2 = 0x55; */
+ 0x0B, 0x80, /* STRH R3, [R1, #0] */
+ /* Chip_Erase Command 0x10 */
+ /* *(uint16_t*)u32FlashSeq1 = 0x10; */
+ 0x10, 0x21, /* MOVS R1, #0x10 */
+ 0x01, 0x80, /* STRH R1, [R0, #0] */
+ /* End Code */
+ 0x00, 0xBE, /* BKPT #0 */
+ };
+
+ LOG_INFO("Fujitsu MB9[A/B]xxx: Chip Erase ... (may take several seconds)");
+
+ /* disable HW watchdog */
+ retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, 0x40011008, 0x00000000);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash access) */
+ retval = target_write_u32(target, 0x40000000, 0x0001);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* dummy read of FASZR */
+ retval = target_read_u32(target, 0x40000000, &u32DummyRead);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* allocate working area with flash chip erase code */
+ if (target_alloc_working_area(target, sizeof(fm3_flash_erase_chip_code),
+ &write_algorithm) != ERROR_OK) {
+ LOG_WARNING("no working area available, can't do block memory writes");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ retval = target_write_buffer(target, write_algorithm->address,
+ sizeof(fm3_flash_erase_chip_code), fm3_flash_erase_chip_code);
+ if (retval != ERROR_OK)
+ return retval;
+
+ armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_info.core_mode = ARM_MODE_THREAD;
+
+ init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* u32FlashSeqAddress1 */
+ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* u32FlashSeqAddress2 */
+
+ buf_set_u32(reg_params[0].value, 0, 32, u32FlashSeqAddress1);
+ buf_set_u32(reg_params[1].value, 0, 32, u32FlashSeqAddress2);
+
+ retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
+ write_algorithm->address, 0, 100000, &armv7m_info);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error executing flash erase programming algorithm");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ return retval;
+ }
+
+ target_free_working_area(target, write_algorithm);
+
+ destroy_reg_param(®_params[0]);
+ destroy_reg_param(®_params[1]);
+
+ retval = fm3_busy_wait(target, u32FlashSeqAddress2, 20000); /* 20s timeout */
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* FASZR = 0x02, Re-enables CPU Run Mode (32-bit Flash access) */
+ retval = target_write_u32(target, 0x40000000, 0x0002);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
+
+ return retval;
+}
+
+COMMAND_HANDLER(fm3_handle_chip_erase_command)
+{
+ int i;
+
+ if (CMD_ARGC < 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct flash_bank *bank;
+ int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+ if (ERROR_OK != retval)
+ return retval;
+
+ if (fm3_chip_erase(bank) == ERROR_OK) {
+ /* set all sectors as erased */
+ for (i = 0; i < bank->num_sectors; i++)
+ bank->sectors[i].is_erased = 1;
+
+ command_print(CMD_CTX, "fm3 chip erase complete");
+ } else {
+ command_print(CMD_CTX, "fm3 chip erase failed");
+ }
+
+ return ERROR_OK;
+}
+
+static const struct command_registration fm3_exec_command_handlers[] = {
+ {
+ .name = "chip_erase",
+ .usage = "<bank>",
+ .handler = fm3_handle_chip_erase_command,
+ .mode = COMMAND_EXEC,
+ .help = "Erase entire Flash device.",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration fm3_command_handlers[] = {
+ {
+ .name = "fm3",
+ .mode = COMMAND_ANY,
+ .help = "fm3 Flash command group",
+ .usage = "",
+ .chain = fm3_exec_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+struct flash_driver fm3_flash = {
+ .name = "fm3",
+ .commands = fm3_command_handlers,
+ .flash_bank_command = fm3_flash_bank_command,
+ .erase = fm3_erase,
+ .write = fm3_write_block,
+ .probe = fm3_probe,
+ .auto_probe = fm3_auto_probe,
+ .erase_check = default_flash_blank_check,
+};
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/fm4.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/fm4.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/fm4.c
new file mode 100755
index 0000000..c348c1d
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/fm4.c
@@ -0,0 +1,722 @@
+/*
+ * Spansion FM4 flash
+ *
+ * Copyright (c) 2015 Andreas F�rber
+ *
+ * Based on S6E2DH_MN709-00013 for S6E2DH/DF/D5/D3 series
+ * Based on S6E2CC_MN709-00007 for S6E2CC/C5/C4/C3/C2/C1 series
+ * Based on MB9B560R_MN709-00005 for MB9BFx66/x67/x68 series
+ * Based on MB9B560L_MN709-00006 for MB9BFx64/x65/x66 series
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imp.h"
+#include <helper/binarybuffer.h>
+#include <target/algorithm.h>
+#include <target/armv7m.h>
+
+#define FLASH_BASE 0x40000000
+#define FASZR (FLASH_BASE + 0x000)
+#define DFCTRLR (FLASH_BASE + 0x030)
+#define DFCTRLR_DFE (1UL << 0)
+
+#define WDG_BASE 0x40011000
+#define WDG_CTL (WDG_BASE + 0x008)
+#define WDG_LCK (WDG_BASE + 0xC00)
+
+enum fm4_variant {
+ mb9bfx64,
+ mb9bfx65,
+ mb9bfx66,
+ mb9bfx67,
+ mb9bfx68,
+
+ s6e2cx8,
+ s6e2cx9,
+ s6e2cxa,
+
+ s6e2dx,
+};
+
+struct fm4_flash_bank {
+ enum fm4_variant variant;
+ int macro_nr;
+ bool probed;
+};
+
+static int fm4_disable_hw_watchdog(struct target *target)
+{
+ int retval;
+
+ retval = target_write_u32(target, WDG_LCK, 0x1ACCE551);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, WDG_LCK, 0xE5331AAE);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, WDG_CTL, 0);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+static int fm4_enter_flash_cpu_programming_mode(struct target *target)
+{
+ uint32_t u32_value;
+ int retval;
+
+ /* FASZR ASZ = CPU programming mode */
+ retval = target_write_u32(target, FASZR, 0x00000001);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = target_read_u32(target, FASZR, &u32_value);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+static int fm4_enter_flash_cpu_rom_mode(struct target *target)
+{
+ uint32_t u32_value;
+ int retval;
+
+ /* FASZR ASZ = CPU ROM mode */
+ retval = target_write_u32(target, FASZR, 0x00000002);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = target_read_u32(target, FASZR, &u32_value);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+static int fm4_flash_erase(struct flash_bank *bank, int first, int last)
+{
+ struct target *target = bank->target;
+ struct working_area *workarea;
+ struct reg_param reg_params[4];
+ struct armv7m_algorithm armv7m_algo;
+ unsigned i;
+ int retval, sector;
+ const uint8_t erase_sector_code[] = {
+#include "../../../contrib/loaders/flash/fm4/erase.inc"
+ };
+
+ if (target->state != TARGET_HALTED) {
+ LOG_WARNING("Cannot communicate... target not halted.");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ LOG_DEBUG("Spansion FM4 erase sectors %d to %d", first, last);
+
+ retval = fm4_disable_hw_watchdog(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = fm4_enter_flash_cpu_programming_mode(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_alloc_working_area(target, sizeof(erase_sector_code),
+ &workarea);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("No working area available.");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto err_alloc_code;
+ }
+ retval = target_write_buffer(target, workarea->address,
+ sizeof(erase_sector_code), erase_sector_code);
+ if (retval != ERROR_OK)
+ goto err_write_code;
+
+ armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_algo.core_mode = ARM_MODE_THREAD;
+
+ 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);
+
+ for (sector = first; sector <= last; sector++) {
+ uint32_t addr = bank->base + bank->sectors[sector].offset;
+ uint32_t result;
+
+ buf_set_u32(reg_params[0].value, 0, 32, (addr & ~0xffff) | 0xAA8);
+ buf_set_u32(reg_params[1].value, 0, 32, (addr & ~0xffff) | 0x554);
+ buf_set_u32(reg_params[2].value, 0, 32, addr);
+
+ retval = target_run_algorithm(target,
+ 0, NULL,
+ ARRAY_SIZE(reg_params), reg_params,
+ workarea->address, 0,
+ 1000, &armv7m_algo);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error executing flash sector erase "
+ "programming algorithm");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ goto err_run;
+ }
+
+ result = buf_get_u32(reg_params[3].value, 0, 32);
+ if (result == 2) {
+ LOG_ERROR("Timeout error from flash sector erase programming algorithm");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ goto err_run_ret;
+ } else if (result != 0) {
+ LOG_ERROR("Unexpected error %d from flash sector erase programming algorithm", result);
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ goto err_run_ret;
+ } else
+ retval = ERROR_OK;
+
+ bank->sectors[sector].is_erased = 1;
+ }
+
+err_run_ret:
+err_run:
+ for (i = 0; i < ARRAY_SIZE(reg_params); i++)
+ destroy_reg_param(®_params[i]);
+
+err_write_code:
+ target_free_working_area(target, workarea);
+
+err_alloc_code:
+ if (retval != ERROR_OK)
+ fm4_enter_flash_cpu_rom_mode(target);
+ else
+ retval = fm4_enter_flash_cpu_rom_mode(target);
+
+ return retval;
+}
+
+static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t byte_count)
+{
+ struct target *target = bank->target;
+ struct working_area *code_workarea, *data_workarea;
+ struct reg_param reg_params[6];
+ struct armv7m_algorithm armv7m_algo;
+ uint32_t halfword_count = DIV_ROUND_UP(byte_count, 2);
+ uint32_t result;
+ unsigned i;
+ int retval;
+ const uint8_t write_block_code[] = {
+#include "../../../contrib/loaders/flash/fm4/write.inc"
+ };
+
+ LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32 " (%" PRId32 " bytes)",
+ offset, byte_count);
+
+ if (offset & 0x1) {
+ LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment",
+ offset);
+ return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+ }
+ if (byte_count & 0x1) {
+ LOG_WARNING("length %" PRId32 " is not 2-byte aligned, rounding up",
+ byte_count);
+ }
+
+ if (target->state != TARGET_HALTED) {
+ LOG_WARNING("Cannot communicate... target not halted.");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ retval = fm4_disable_hw_watchdog(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_alloc_working_area(target, sizeof(write_block_code),
+ &code_workarea);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("No working area available for write code.");
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ retval = target_write_buffer(target, code_workarea->address,
+ sizeof(write_block_code), write_block_code);
+ if (retval != ERROR_OK)
+ goto err_write_code;
+
+ retval = target_alloc_working_area(target,
+ MIN(halfword_count * 2, target_get_working_area_avail(target)),
+ &data_workarea);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("No working area available for write data.");
+ retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ goto err_alloc_data;
+ }
+
+ armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
+ armv7m_algo.core_mode = ARM_MODE_THREAD;
+
+ init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
+ init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
+ init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
+ init_reg_param(®_params[3], "r3", 32, PARAM_OUT);
+ init_reg_param(®_params[4], "r4", 32, PARAM_OUT);
+ init_reg_param(®_params[5], "r5", 32, PARAM_IN);
+
+ retval = fm4_enter_flash_cpu_programming_mode(target);
+ if (retval != ERROR_OK)
+ goto err_flash_mode;
+
+ while (byte_count > 0) {
+ uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2);
+ uint32_t addr = bank->base + offset;
+
+ LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32,
+ MIN(halfwords * 2, byte_count), data_workarea->address);
+
+ retval = target_write_buffer(target, data_workarea->address,
+ MIN(halfwords * 2, byte_count), buffer);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error writing data buffer");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ goto err_write_data;
+ }
+
+ LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRId32 "x)",
+ addr, addr + halfwords * 2 - 1, halfwords);
+
+ buf_set_u32(reg_params[0].value, 0, 32, (addr & ~0xffff) | 0xAA8);
+ buf_set_u32(reg_params[1].value, 0, 32, (addr & ~0xffff) | 0x554);
+ buf_set_u32(reg_params[2].value, 0, 32, addr);
+ buf_set_u32(reg_params[3].value, 0, 32, data_workarea->address);
+ buf_set_u32(reg_params[4].value, 0, 32, halfwords);
+
+ retval = target_run_algorithm(target,
+ 0, NULL,
+ ARRAY_SIZE(reg_params), reg_params,
+ code_workarea->address, 0,
+ 5 * 60 * 1000, &armv7m_algo);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error executing flash sector erase "
+ "programming algorithm");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ goto err_run;
+ }
+
+ result = buf_get_u32(reg_params[5].value, 0, 32);
+ if (result == 2) {
+ LOG_ERROR("Timeout error from flash write "
+ "programming algorithm");
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ goto err_run_ret;
+ } else if (result != 0) {
+ LOG_ERROR("Unexpected error %d from flash write "
+ "programming algorithm", result);
+ retval = ERROR_FLASH_OPERATION_FAILED;
+ goto err_run_ret;
+ } else
+ retval = ERROR_OK;
+
+ halfword_count -= halfwords;
+ offset += halfwords * 2;
+ buffer += halfwords * 2;
+ byte_count -= MIN(halfwords * 2, byte_count);
+ }
+
+err_run_ret:
+err_run:
+err_write_data:
+ retval = fm4_enter_flash_cpu_rom_mode(target);
+
+err_flash_mode:
+ for (i = 0; i < ARRAY_SIZE(reg_params); i++)
+ destroy_reg_param(®_params[i]);
+
+ target_free_working_area(target, data_workarea);
+err_alloc_data:
+err_write_code:
+ target_free_working_area(target, code_workarea);
+
+ return retval;
+}
+
+static int mb9bf_probe(struct flash_bank *bank)
+{
+ struct fm4_flash_bank *fm4_bank = bank->driver_priv;
+ uint32_t flash_addr = bank->base;
+ int i;
+
+ switch (fm4_bank->variant) {
+ case mb9bfx64:
+ bank->num_sectors = 8;
+ break;
+ case mb9bfx65:
+ bank->num_sectors = 10;
+ break;
+ case mb9bfx66:
+ bank->num_sectors = 12;
+ break;
+ case mb9bfx67:
+ bank->num_sectors = 16;
+ break;
+ case mb9bfx68:
+ bank->num_sectors = 20;
+ break;
+ default:
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+
+ LOG_DEBUG("%d sectors", bank->num_sectors);
+ bank->sectors = calloc(bank->num_sectors,
+ sizeof(struct flash_sector));
+ for (i = 0; i < bank->num_sectors; i++) {
+ if (i < 4)
+ bank->sectors[i].size = 8 * 1024;
+ else if (i == 4)
+ bank->sectors[i].size = 32 * 1024;
+ else
+ bank->sectors[i].size = 64 * 1024;
+ bank->sectors[i].offset = flash_addr - bank->base;
+ bank->sectors[i].is_erased = -1;
+ bank->sectors[i].is_protected = -1;
+
+ bank->size += bank->sectors[i].size;
+ flash_addr += bank->sectors[i].size;
+ }
+
+ return ERROR_OK;
+}
+
+static void s6e2cc_init_sector(struct flash_sector *sector, int sa)
+{
+ if (sa < 8)
+ sector->size = 8 * 1024;
+ else if (sa == 8)
+ sector->size = 32 * 1024;
+ else
+ sector->size = 64 * 1024;
+
+ sector->is_erased = -1;
+ sector->is_protected = -1;
+}
+
+static int s6e2cc_probe(struct flash_bank *bank)
+{
+ struct target *target = bank->target;
+ struct fm4_flash_bank *fm4_bank = bank->driver_priv;
+ uint32_t u32_value;
+ uint32_t flash_addr = bank->base;
+ int i, retval, num_sectors, num_extra_sectors;
+
+ retval = target_read_u32(target, DFCTRLR, &u32_value);
+ if (retval != ERROR_OK)
+ return retval;
+ if (u32_value & DFCTRLR_DFE) {
+ LOG_WARNING("Dual Flash mode is not implemented.");
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+
+ switch (fm4_bank->variant) {
+ case s6e2cx8:
+ num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 0;
+ break;
+ case s6e2cx9:
+ num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 12;
+ break;
+ case s6e2cxa:
+ num_sectors = 20;
+ break;
+ default:
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+ num_extra_sectors = (fm4_bank->macro_nr == 0) ? 1 : 4;
+ bank->num_sectors = num_sectors + num_extra_sectors;
+
+ LOG_DEBUG("%d sectors", bank->num_sectors);
+ bank->sectors = calloc(bank->num_sectors,
+ sizeof(struct flash_sector));
+ for (i = 0; i < num_sectors; i++) {
+ int sa = 4 + i;
+ bank->sectors[i].offset = flash_addr - bank->base;
+ s6e2cc_init_sector(&bank->sectors[i], sa);
+
+ bank->size += bank->sectors[i].size;
+ flash_addr += bank->sectors[i].size;
+ }
+
+ flash_addr = (fm4_bank->macro_nr == 0) ? 0x00406000 : 0x00408000;
+ for (; i < bank->num_sectors; i++) {
+ int sa = 4 - num_extra_sectors + (i - num_sectors);
+ bank->sectors[i].offset = flash_addr - bank->base;
+ s6e2cc_init_sector(&bank->sectors[i], sa);
+
+ /*
+ * Don't increase bank->size for these sectors
+ * to avoid an overlap between Flash Macros #0 and #1.
+ */
+ flash_addr += bank->sectors[i].size;
+ }
+
+ return ERROR_OK;
+}
+
+static int s6e2dh_probe(struct flash_bank *bank)
+{
+ uint32_t flash_addr = bank->base;
+ int i;
+
+ bank->num_sectors = 10;
+ bank->sectors = calloc(bank->num_sectors,
+ sizeof(struct flash_sector));
+ for (i = 0; i < bank->num_sectors; i++) {
+ if (i < 4)
+ bank->sectors[i].size = 8 * 1024;
+ else if (i == 4)
+ bank->sectors[i].size = 32 * 1024;
+ else
+ bank->sectors[i].size = 64 * 1024;
+ bank->sectors[i].offset = flash_addr - bank->base;
+ bank->sectors[i].is_erased = -1;
+ bank->sectors[i].is_protected = -1;
+
+ bank->size += bank->sectors[i].size;
+ flash_addr += bank->sectors[i].size;
+ }
+
+ return ERROR_OK;
+}
+
+static int fm4_probe(struct flash_bank *bank)
+{
+ struct fm4_flash_bank *fm4_bank = bank->driver_priv;
+ int retval;
+
+ if (fm4_bank->probed)
+ return ERROR_OK;
+
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_WARNING("Cannot communicate... target not halted.");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ switch (fm4_bank->variant) {
+ case mb9bfx64:
+ case mb9bfx65:
+ case mb9bfx66:
+ case mb9bfx67:
+ case mb9bfx68:
+ retval = mb9bf_probe(bank);
+ break;
+ case s6e2cx8:
+ case s6e2cx9:
+ case s6e2cxa:
+ retval = s6e2cc_probe(bank);
+ break;
+ case s6e2dx:
+ retval = s6e2dh_probe(bank);
+ break;
+ default:
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+ if (retval != ERROR_OK)
+ return retval;
+
+ fm4_bank->probed = true;
+
+ return ERROR_OK;
+}
+
+static int fm4_auto_probe(struct flash_bank *bank)
+{
+ struct fm4_flash_bank *fm4_bank = bank->driver_priv;
+
+ if (fm4_bank->probed)
+ return ERROR_OK;
+
+ return fm4_probe(bank);
+}
+
+static int fm4_protect_check(struct flash_bank *bank)
+{
+ return ERROR_OK;
+}
+
+static int fm4_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
+{
+ struct fm4_flash_bank *fm4_bank = bank->driver_priv;
+ const char *name;
+
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_WARNING("Cannot communicate... target not halted.");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ switch (fm4_bank->variant) {
+ case mb9bfx64:
+ name = "MB9BFx64";
+ break;
+ case mb9bfx65:
+ name = "MB9BFx65";
+ break;
+ case mb9bfx66:
+ name = "MB9BFx66";
+ break;
+ case mb9bfx67:
+ name = "MB9BFx67";
+ break;
+ case mb9bfx68:
+ name = "MB9BFx68";
+ break;
+ case s6e2cx8:
+ name = "S6E2Cx8";
+ break;
+ case s6e2cx9:
+ name = "S6E2Cx9";
+ break;
+ case s6e2cxa:
+ name = "S6E2CxA";
+ break;
+ case s6e2dx:
+ name = "S6E2Dx";
+ break;
+ default:
+ name = "unknown";
+ break;
+ }
+
+ switch (fm4_bank->variant) {
+ case s6e2cx8:
+ case s6e2cx9:
+ case s6e2cxa:
+ snprintf(buf, buf_size, "%s MainFlash Macro #%i",
+ name, fm4_bank->macro_nr);
+ break;
+ default:
+ snprintf(buf, buf_size, "%s MainFlash", name);
+ break;
+ }
+
+ return ERROR_OK;
+}
+
+static bool fm4_name_match(const char *s, const char *pattern)
+{
+ int i = 0;
+
+ while (s[i]) {
+ /* If the match string is shorter, ignore excess */
+ if (!pattern[i])
+ return true;
+ /* Use x as wildcard */
+ if (pattern[i] != 'x' && tolower(s[i]) != tolower(pattern[i]))
+ return false;
+ i++;
+ }
+ return true;
+}
+
+static int mb9bf_bank_setup(struct flash_bank *bank, const char *variant)
+{
+ struct fm4_flash_bank *fm4_bank = bank->driver_priv;
+
+ if (fm4_name_match(variant, "MB9BFx64")) {
+ fm4_bank->variant = mb9bfx64;
+ } else if (fm4_name_match(variant, "MB9BFx65")) {
+ fm4_bank->variant = mb9bfx65;
+ } else if (fm4_name_match(variant, "MB9BFx66")) {
+ fm4_bank->variant = mb9bfx66;
+ } else if (fm4_name_match(variant, "MB9BFx67")) {
+ fm4_bank->variant = mb9bfx67;
+ } else if (fm4_name_match(variant, "MB9BFx68")) {
+ fm4_bank->variant = mb9bfx68;
+ } else {
+ LOG_WARNING("MB9BF variant %s not recognized.", variant);
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+
+ return ERROR_OK;
+}
+
+static int s6e2cc_bank_setup(struct flash_bank *bank, const char *variant)
+{
+ struct fm4_flash_bank *fm4_bank = bank->driver_priv;
+
+ if (fm4_name_match(variant, "S6E2Cx8")) {
+ fm4_bank->variant = s6e2cx8;
+ } else if (fm4_name_match(variant, "S6E2Cx9")) {
+ fm4_bank->variant = s6e2cx9;
+ } else if (fm4_name_match(variant, "S6E2CxA")) {
+ fm4_bank->variant = s6e2cxa;
+ } else {
+ LOG_WARNING("S6E2CC variant %s not recognized.", variant);
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+
+ return ERROR_OK;
+}
+
+FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command)
+{
+ struct fm4_flash_bank *fm4_bank;
+ const char *variant;
+ int ret;
+
+ if (CMD_ARGC < 7)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ variant = CMD_ARGV[6];
+
+ fm4_bank = malloc(sizeof(struct fm4_flash_bank));
+ if (!fm4_bank)
+ return ERROR_FLASH_OPERATION_FAILED;
+
+ fm4_bank->probed = false;
+ fm4_bank->macro_nr = (bank->base == 0x00000000) ? 0 : 1;
+
+ bank->driver_priv = fm4_bank;
+
+ if (fm4_name_match(variant, "MB9BF"))
+ ret = mb9bf_bank_setup(bank, variant);
+ else if (fm4_name_match(variant, "S6E2Cx"))
+ ret = s6e2cc_bank_setup(bank, variant);
+ else if (fm4_name_match(variant, "S6E2Dx")) {
+ fm4_bank->variant = s6e2dx;
+ ret = ERROR_OK;
+ } else {
+ LOG_WARNING("Family %s not recognized.", variant);
+ ret = ERROR_FLASH_OPER_UNSUPPORTED;
+ }
+ if (ret != ERROR_OK)
+ free(fm4_bank);
+ return ret;
+}
+
+static const struct command_registration fm4_exec_command_handlers[] = {
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration fm4_command_handlers[] = {
+ {
+ .name = "fm4",
+ .mode = COMMAND_ANY,
+ .help = "fm4 flash command group",
+ .usage = "",
+ .chain = fm4_exec_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+struct flash_driver fm4_flash = {
+ .name = "fm4",
+ .commands = fm4_command_handlers,
+ .flash_bank_command = fm4_flash_bank_command,
+ .info = fm4_get_info_command,
+ .probe = fm4_probe,
+ .auto_probe = fm4_auto_probe,
+ .protect_check = fm4_protect_check,
+ .read = default_flash_read,
+ .erase = fm4_flash_erase,
+ .erase_check = default_flash_blank_check,
+ .write = fm4_flash_write,
+};
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/imp.h
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/imp.h b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/imp.h
new file mode 100755
index 0000000..31d0984
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/imp.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * Copyright (C) 2009 Zachary T Welch <zw...@superlucidity.net> *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+#ifndef FLASH_NOR_IMP_H
+#define FLASH_NOR_IMP_H
+
+/* this is an internal header */
+#include "core.h"
+#include "driver.h"
+/* almost all drivers will need this file */
+#include <target/target.h>
+
+/**
+ * Adds a new NOR bank to the global list of banks.
+ * @param bank The bank that should be added.
+ */
+void flash_bank_add(struct flash_bank *bank);
+
+/**
+ * @return The first bank in the global list.
+ */
+struct flash_bank *flash_bank_list(void);
+
+int flash_driver_erase(struct flash_bank *bank, int first, int last);
+int flash_driver_protect(struct flash_bank *bank, int set, int first, int last);
+int flash_driver_write(struct flash_bank *bank,
+ uint8_t *buffer, uint32_t offset, uint32_t count);
+int flash_driver_read(struct flash_bank *bank,
+ uint8_t *buffer, uint32_t offset, uint32_t count);
+
+/* write (optional verify) an image to flash memory of the given target */
+int flash_write_unlock(struct target *target, struct image *image,
+ uint32_t *written, int erase, bool unlock);
+
+#endif /* FLASH_NOR_IMP_H */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/jtagspi.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/jtagspi.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/jtagspi.c
new file mode 100755
index 0000000..1e623a7
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/flash/nor/jtagspi.c
@@ -0,0 +1,411 @@
+/***************************************************************************
+ * Copyright (C) 2015 Robert Jordens <jo...@gmail.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. *
+ * *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imp.h"
+#include <jtag/jtag.h>
+#include <flash/nor/spi.h>
+#include <helper/time_support.h>
+
+#define JTAGSPI_MAX_TIMEOUT 3000
+
+
+struct jtagspi_flash_bank {
+ struct jtag_tap *tap;
+ const struct flash_device *dev;
+ int probed;
+ uint32_t ir;
+ uint32_t dr_len;
+};
+
+FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
+{
+ struct jtagspi_flash_bank *info;
+
+ if (CMD_ARGC < 8)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ info = malloc(sizeof(struct jtagspi_flash_bank));
+ if (info == NULL) {
+ LOG_ERROR("no memory for flash bank info");
+ return ERROR_FAIL;
+ }
+ bank->driver_priv = info;
+
+ info->tap = NULL;
+ info->probed = 0;
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir);
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[7], info->dr_len);
+
+ return ERROR_OK;
+}
+
+static void jtagspi_set_ir(struct flash_bank *bank)
+{
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+ struct scan_field field;
+ uint8_t buf[4];
+
+ if (buf_get_u32(info->tap->cur_instr, 0, info->tap->ir_length) == info->ir)
+ return;
+
+ LOG_DEBUG("loading jtagspi ir");
+ buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
+ field.num_bits = info->tap->ir_length;
+ field.out_value = buf;
+ field.in_value = NULL;
+ jtag_add_ir_scan(info->tap, &field, TAP_IDLE);
+}
+
+static void flip_u8(uint8_t *in, uint8_t *out, int len)
+{
+ for (int i = 0; i < len; i++)
+ out[i] = flip_u32(in[i], 8);
+}
+
+static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
+ uint32_t *addr, uint8_t *data, int len)
+{
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+ struct scan_field fields[3];
+ uint8_t cmd_buf[4];
+ uint8_t *data_buf;
+ int is_read, lenb, n;
+
+ /* LOG_DEBUG("cmd=0x%02x len=%i", cmd, len); */
+
+ n = 0;
+ fields[n].num_bits = 8;
+ cmd_buf[0] = cmd;
+ if (addr) {
+ h_u24_to_be(cmd_buf + 1, *addr);
+ fields[n].num_bits += 24;
+ }
+ flip_u8(cmd_buf, cmd_buf, 4);
+ fields[n].out_value = cmd_buf;
+ fields[n].in_value = NULL;
+ n++;
+
+ is_read = (len < 0);
+ if (is_read)
+ len = -len;
+ lenb = DIV_ROUND_UP(len, 8);
+ data_buf = malloc(lenb);
+ if (lenb > 0) {
+ if (data_buf == NULL) {
+ LOG_ERROR("no memory for spi buffer");
+ return ERROR_FAIL;
+ }
+ if (is_read) {
+ fields[n].num_bits = info->dr_len;
+ fields[n].out_value = NULL;
+ fields[n].in_value = NULL;
+ n++;
+ fields[n].out_value = NULL;
+ fields[n].in_value = data_buf;
+ } else {
+ flip_u8(data, data_buf, lenb);
+ fields[n].out_value = data_buf;
+ fields[n].in_value = NULL;
+ }
+ fields[n].num_bits = len;
+ n++;
+ }
+
+ jtagspi_set_ir(bank);
+ jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
+ jtag_execute_queue();
+
+ if (is_read)
+ flip_u8(data_buf, data, lenb);
+ free(data_buf);
+ return ERROR_OK;
+}
+
+static int jtagspi_probe(struct flash_bank *bank)
+{
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+ struct flash_sector *sectors;
+ uint8_t in_buf[3];
+ uint32_t id;
+
+ if (info->probed)
+ free(bank->sectors);
+ info->probed = 0;
+
+ if (bank->target->tap == NULL) {
+ LOG_ERROR("Target has no JTAG tap");
+ return ERROR_FAIL;
+ }
+ info->tap = bank->target->tap;
+
+ jtagspi_cmd(bank, SPIFLASH_READ_ID, NULL, in_buf, -24);
+ /* the table in spi.c has the manufacturer byte (first) as the lsb */
+ id = le_to_h_u24(in_buf);
+
+ info->dev = NULL;
+ for (const struct flash_device *p = flash_devices; p->name ; p++)
+ if (p->device_id == id) {
+ info->dev = p;
+ break;
+ }
+
+ if (!(info->dev)) {
+ LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
+ return ERROR_FAIL;
+ }
+
+ LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
+ info->dev->name, info->dev->device_id);
+
+ /* Set correct size value */
+ bank->size = info->dev->size_in_bytes;
+
+ /* create and fill sectors array */
+ bank->num_sectors =
+ info->dev->size_in_bytes / info->dev->sectorsize;
+ sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
+ if (sectors == NULL) {
+ LOG_ERROR("not enough memory");
+ return ERROR_FAIL;
+ }
+
+ for (int sector = 0; sector < bank->num_sectors; sector++) {
+ sectors[sector].offset = sector * info->dev->sectorsize;
+ sectors[sector].size = info->dev->sectorsize;
+ sectors[sector].is_erased = -1;
+ sectors[sector].is_protected = 0;
+ }
+
+ bank->sectors = sectors;
+ info->probed = 1;
+ return ERROR_OK;
+}
+
+static void jtagspi_read_status(struct flash_bank *bank, uint32_t *status)
+{
+ uint8_t buf;
+ jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8);
+ *status = buf;
+ /* LOG_DEBUG("status=0x%08" PRIx32, *status); */
+}
+
+static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
+{
+ uint32_t status;
+ long long t0 = timeval_ms();
+ long long dt;
+
+ do {
+ dt = timeval_ms() - t0;
+ jtagspi_read_status(bank, &status);
+ if ((status & SPIFLASH_BSY_BIT) == 0) {
+ LOG_DEBUG("waited %lld ms", dt);
+ return ERROR_OK;
+ }
+ alive_sleep(1);
+ } while (dt <= timeout_ms);
+
+ LOG_ERROR("timeout, device still busy");
+ return ERROR_FAIL;
+}
+
+static int jtagspi_write_enable(struct flash_bank *bank)
+{
+ uint32_t status;
+
+ jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0);
+ jtagspi_read_status(bank, &status);
+ if ((status & SPIFLASH_WE_BIT) == 0) {
+ LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
+ return ERROR_FAIL;
+ }
+ return ERROR_OK;
+}
+
+static int jtagspi_bulk_erase(struct flash_bank *bank)
+{
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+ int retval;
+ long long t0 = timeval_ms();
+
+ retval = jtagspi_write_enable(bank);
+ if (retval != ERROR_OK)
+ return retval;
+ jtagspi_cmd(bank, info->dev->chip_erase_cmd, NULL, NULL, 0);
+ retval = jtagspi_wait(bank, bank->num_sectors*JTAGSPI_MAX_TIMEOUT);
+ LOG_INFO("took %lld ms", timeval_ms() - t0);
+ return retval;
+}
+
+static int jtagspi_sector_erase(struct flash_bank *bank, int sector)
+{
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+ int retval;
+ long long t0 = timeval_ms();
+
+ retval = jtagspi_write_enable(bank);
+ if (retval != ERROR_OK)
+ return retval;
+ jtagspi_cmd(bank, info->dev->erase_cmd, &bank->sectors[sector].offset, NULL, 0);
+ retval = jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
+ LOG_INFO("sector %d took %lld ms", sector, timeval_ms() - t0);
+ return retval;
+}
+
+static int jtagspi_erase(struct flash_bank *bank, int first, int last)
+{
+ int sector;
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+ int retval = ERROR_OK;
+
+ LOG_DEBUG("erase from sector %d to sector %d", first, last);
+
+ if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
+ LOG_ERROR("Flash sector invalid");
+ return ERROR_FLASH_SECTOR_INVALID;
+ }
+
+ if (!(info->probed)) {
+ LOG_ERROR("Flash bank not probed");
+ return ERROR_FLASH_BANK_NOT_PROBED;
+ }
+
+ for (sector = first; sector <= last; sector++) {
+ if (bank->sectors[sector].is_protected) {
+ LOG_ERROR("Flash sector %d protected", sector);
+ return ERROR_FAIL;
+ }
+ }
+
+ if (first == 0 && last == (bank->num_sectors - 1)
+ && info->dev->chip_erase_cmd != info->dev->erase_cmd) {
+ LOG_DEBUG("Trying bulk erase.");
+ retval = jtagspi_bulk_erase(bank);
+ if (retval == ERROR_OK)
+ return retval;
+ else
+ LOG_WARNING("Bulk flash erase failed. Falling back to sector erase.");
+ }
+
+ for (sector = first; sector <= last; sector++) {
+ retval = jtagspi_sector_erase(bank, sector);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Sector erase failed.");
+ break;
+ }
+ }
+
+ return retval;
+}
+
+static int jtagspi_protect(struct flash_bank *bank, int set, int first, int last)
+{
+ int sector;
+
+ if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
+ LOG_ERROR("Flash sector invalid");
+ return ERROR_FLASH_SECTOR_INVALID;
+ }
+
+ for (sector = first; sector <= last; sector++)
+ bank->sectors[sector].is_protected = set;
+ return ERROR_OK;
+}
+
+static int jtagspi_protect_check(struct flash_bank *bank)
+{
+ return ERROR_OK;
+}
+
+static int jtagspi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+
+ if (!(info->probed)) {
+ LOG_ERROR("Flash bank not yet probed.");
+ return ERROR_FLASH_BANK_NOT_PROBED;
+ }
+
+ jtagspi_cmd(bank, SPIFLASH_READ, &offset, buffer, -count*8);
+ return ERROR_OK;
+}
+
+static int jtagspi_page_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ int retval;
+
+ retval = jtagspi_write_enable(bank);
+ if (retval != ERROR_OK)
+ return retval;
+ jtagspi_cmd(bank, SPIFLASH_PAGE_PROGRAM, &offset, (uint8_t *) buffer, count*8);
+ return jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
+}
+
+static int jtagspi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+ int retval;
+ uint32_t n;
+
+ if (!(info->probed)) {
+ LOG_ERROR("Flash bank not yet probed.");
+ return ERROR_FLASH_BANK_NOT_PROBED;
+ }
+
+ for (n = 0; n < count; n += info->dev->pagesize) {
+ retval = jtagspi_page_write(bank, buffer + n, offset + n,
+ MIN(count - n, info->dev->pagesize));
+ if (retval != ERROR_OK) {
+ LOG_ERROR("page write error");
+ return retval;
+ }
+ LOG_DEBUG("wrote page at 0x%08" PRIx32, offset + n);
+ }
+ return ERROR_OK;
+}
+
+static int jtagspi_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+ struct jtagspi_flash_bank *info = bank->driver_priv;
+
+ if (!(info->probed)) {
+ snprintf(buf, buf_size, "\nJTAGSPI flash bank not probed yet\n");
+ return ERROR_OK;
+ }
+
+ snprintf(buf, buf_size, "\nSPIFI flash information:\n"
+ " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
+ info->dev->name, info->dev->device_id);
+
+ return ERROR_OK;
+}
+
+struct flash_driver jtagspi_flash = {
+ .name = "jtagspi",
+ .flash_bank_command = jtagspi_flash_bank_command,
+ .erase = jtagspi_erase,
+ .protect = jtagspi_protect,
+ .write = jtagspi_write,
+ .read = jtagspi_read,
+ .probe = jtagspi_probe,
+ .auto_probe = jtagspi_probe,
+ .erase_check = default_flash_blank_check,
+ .protect_check = jtagspi_protect_check,
+ .info = jtagspi_info
+};