aboutsummaryrefslogtreecommitdiffstats
path: root/openocd
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-08-19 14:26:41 +0200
committerHarald Welte <laforge@gnumonks.org>2012-08-19 14:26:41 +0200
commitdc7a5264932183b6f7d78f0ab0febe2edae74ab9 (patch)
tree20c3f4248776a4c8c62b31aebfdc119e710766ec /openocd
parentf063e0a623766540e32f81b83a87d0b233776563 (diff)
add OpenOCD driver for the CC32RS512 flash controller + openocd.cfg
Diffstat (limited to 'openocd')
-rw-r--r--openocd/0001-Add-a-flash-driver-for-the-CC32RS512-internal-flash-.patch379
-rw-r--r--openocd/cc32rs512.cfg21
2 files changed, 400 insertions, 0 deletions
diff --git a/openocd/0001-Add-a-flash-driver-for-the-CC32RS512-internal-flash-.patch b/openocd/0001-Add-a-flash-driver-for-the-CC32RS512-internal-flash-.patch
new file mode 100644
index 0000000..f0fd798
--- /dev/null
+++ b/openocd/0001-Add-a-flash-driver-for-the-CC32RS512-internal-flash-.patch
@@ -0,0 +1,379 @@
+From 93e330366eaad93ebcd764890ea4aa7e042737cd Mon Sep 17 00:00:00 2001
+From: Harald Welte <laforge@gnumonks.org>
+Date: Sun, 19 Aug 2012 14:25:20 +0200
+Subject: [PATCH] Add a flash driver for the CC32RS512 internal flash
+ controller
+
+---
+ src/flash/nor/Makefile.am | 3 +-
+ src/flash/nor/cc32rs512.c | 323 +++++++++++++++++++++++++++++++++++++++++++++
+ src/flash/nor/drivers.c | 2 +
+ 3 files changed, 327 insertions(+), 1 deletion(-)
+ create mode 100644 src/flash/nor/cc32rs512.c
+
+diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
+index fc64602..d789834 100644
+--- a/src/flash/nor/Makefile.am
++++ b/src/flash/nor/Makefile.am
+@@ -34,7 +34,8 @@ NOR_DRIVERS = \
+ virtual.c \
+ fm3.c \
+ dsp5680xx_flash.c \
+- kinetis.c
++ kinetis.c \
++ cc32rs512.c
+
+ noinst_HEADERS = \
+ core.h \
+diff --git a/src/flash/nor/cc32rs512.c b/src/flash/nor/cc32rs512.c
+new file mode 100644
+index 0000000..7a750a1
+--- /dev/null
++++ b/src/flash/nor/cc32rs512.c
+@@ -0,0 +1,323 @@
++/***************************************************************************
++ * Copyright (C) 2012 Harald Welte <laforge@gnumonks.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., *
++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
++ ***************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "imp.h"
++#include <target/image.h>
++#include "hello.h"
++
++struct cc32rs512_flash_bank {
++ struct target *target;
++ uint8_t *memory;
++ uint32_t start_address;
++
++ uint32_t flbuf;
++ uint32_t sector_size;
++};
++
++#define RAM_BASE 0xc0000
++#define RAM_SIZE (18*1024)
++
++/* According to the manual, this should be the default: */
++//#define FLBUF_BASE(psz) ((RAM_BASE + RAM_SIZE) - (psz))
++/* But: This is where the bootloader places its buffer */
++#define FLBUF_BASE(x) (RAM_BASE + 0x10)
++
++static const int sectorSize = 256;
++
++
++#define FLCON_BASE 0x0f2000
++
++enum flcon_reg {
++ FLCON = 0x00,
++ FLSDP1 = 0x04,
++ FLSDP2 = 0x08,
++ FLSTS = 0x0C,
++ FLBUF = 0x10,
++};
++
++#define FLCON_REG(x) (FLCON_BASE + (x))
++
++/* flash bank faux <base> <size> <chip_width> <bus_width> <target#> <driverPath>
++ */
++FLASH_BANK_COMMAND_HANDLER(cc32rs512_flash_bank_command)
++{
++ struct cc32rs512_flash_bank *info;
++
++ if (CMD_ARGC < 6)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ info = malloc(sizeof(struct cc32rs512_flash_bank));
++ if (info == NULL) {
++ LOG_ERROR("no memory for flash bank info");
++ return ERROR_FAIL;
++ }
++
++ info->start_address = 0;
++ info->sector_size = sectorSize;
++ info->flbuf = FLBUF_BASE(info->sector_size);
++
++ bank->driver_priv = info;
++
++ int i = 0;
++ uint32_t offset = 0;
++ bank->num_sectors = bank->size/info->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 = info->sector_size;
++ offset += bank->sectors[i].size;
++ bank->sectors[i].is_erased = -1;
++ bank->sectors[i].is_protected = 0;
++ }
++
++ info->target = get_target(CMD_ARGV[5]);
++ if (info->target == NULL) {
++ LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
++ free(info->memory);
++ free(info);
++ return ERROR_FAIL;
++ }
++ return ERROR_OK;
++}
++
++static int cc32rs512_getstatus(struct target *target)
++{
++ uint32_t tmp;
++ target_read_u32(target, FLCON_REG(FLSTS), &tmp);
++
++ return tmp;
++}
++
++static uint32_t cc32rs512_wait_status(struct target *target, int timeout)
++{
++ uint32_t status;
++
++ while (!(status = cc32rs512_getstatus(target)) && (timeout-- > 0)) {
++ alive_sleep(1);
++ }
++ return status;
++}
++
++static int cc32rs512_erase(struct flash_bank *bank, int first, int last)
++{
++ struct cc32rs512_flash_bank *info = bank->driver_priv;
++ struct target *target = bank->target;
++ uint32_t status;
++ int sec;
++
++ if (target->state != TARGET_HALTED) {
++ LOG_ERROR("Target not halted");
++ return ERROR_TARGET_NOT_HALTED;
++ }
++
++ if ((first < 0) || (last < first) || (last >= bank->num_sectors))
++ return ERROR_FLASH_SECTOR_INVALID;
++
++ switch (info->sector_size) {
++ case 256:
++ target_write_u32(target, FLCON_REG(FLCON), (1 << 3));
++ break;
++ case 512:
++ target_write_u32(target, FLCON_REG(FLCON), (0 << 3));
++ break;
++ default:
++ return ERROR_FAIL;
++ }
++
++ for (sec = first; sec <= last; sec++) {
++ /* FIXME: disable interrupts if we're flashing the firrst page? */
++
++ /* clear all flags */
++ target_write_u32(target, FLCON_REG(FLSTS), 3);
++ target_write_u32(target, FLCON_REG(FLSDP1), 0x55);
++ target_write_u32(target, FLCON_REG(FLSDP2), 0xAA);
++
++ /* FIXME: offset of flash bank? */
++ LOG_DEBUG("erase: start_addr = 0x%x, sec = %u, size = %u, result = 0x%x\n",
++ info->start_address, sec, info->sector_size,
++ info->start_address + sec*info->sector_size);
++ target_write_u32(target, info->start_address + sec*info->sector_size, 0xff);
++
++ status = cc32rs512_wait_status(target, 1000);
++ switch (status) {
++ case 0:
++ LOG_ERROR("timeout waiting for FLSTS finish\n");
++ return ERROR_FAIL;
++ case 1:
++ break;
++ default:
++ LOG_ERROR("Error (FLSTS=0x%x) during erase", status);
++ return ERROR_FAIL;
++ }
++
++ target_write_u32(target, FLCON_REG(FLSTS), 3);
++
++ bank->sectors[sec].is_erased = 1;
++ }
++
++ return ERROR_OK;
++}
++
++static int cc32rs512_protect(struct flash_bank *bank, int set, int first, int last)
++{
++ /* this chip has no protection */
++ return ERROR_FAIL;
++}
++
++static int cc32rs512_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
++{
++ struct cc32rs512_flash_bank *info = bank->driver_priv;
++ struct target *target = bank->target;
++ uint32_t status;
++ uint32_t first_page, last_page, pagen, buffer_pos;
++
++ LOG_DEBUG("cc32rs512_write entered!");
++
++ if (target->state != TARGET_HALTED) {
++ LOG_ERROR("Target not halted");
++ return ERROR_TARGET_NOT_HALTED;
++ }
++
++ if (offset + count > bank->size)
++ return ERROR_FLASH_DST_OUT_OF_BANK;
++
++ if (offset % info->sector_size) {
++ LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
++ offset, info->sector_size);
++ return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
++ }
++
++ first_page = offset / info->sector_size;
++ last_page = DIV_ROUND_UP(offset + count, info->sector_size);
++
++ LOG_DEBUG("first_page: %i, last_page: %i, count %i",
++ (int)first_page, (int)last_page, (int)count);
++
++ switch (info->sector_size) {
++ case 256:
++ target_write_u32(target, FLCON_REG(FLCON), (1 << 3));
++ break;
++ case 512:
++ target_write_u32(target, FLCON_REG(FLCON), (0 << 3));
++ break;
++ default:
++ return ERROR_FAIL;
++ }
++
++ target_write_u32(target, FLCON_REG(FLBUF), info->flbuf);
++
++ buffer_pos = 0;
++ for (pagen = first_page; pagen < last_page; pagen++) {
++ /* write to flash buffer base address */
++ target_write_memory(target, info->flbuf, 4, info->sector_size/4,
++ buffer + buffer_pos);
++
++ /* FIXME: disable interrupts if we're flashing the firrst page? */
++
++ /* clear all flags */
++ target_write_u32(target, FLCON_REG(FLSTS), 3);
++ target_write_u32(target, FLCON_REG(FLSDP1), 0xAA);
++ target_write_u32(target, FLCON_REG(FLSDP2), 0x55);
++
++ /* FIXME: offset of flash bank? */
++ target_write_u32(target, info->start_address + pagen*info->sector_size, 0x00);
++
++
++ status = cc32rs512_wait_status(target, 1000);
++ switch (status) {
++ case 0:
++ LOG_ERROR("timeout waiting for FLSTS finish\n");
++ return ERROR_FAIL;
++ case 1:
++ break;
++ default:
++ LOG_ERROR("Error (FLSTS=0x%x) during write", status);
++ return ERROR_FAIL;
++ }
++
++ target_write_u32(target, FLCON_REG(FLSTS), 3);
++
++ buffer_pos += info->sector_size;
++ }
++
++ return ERROR_OK;
++}
++
++static int cc32rs512_protect_check(struct flash_bank *bank)
++{
++ /* is_protected is initialized to 0 and we never change it */
++ return ERROR_OK;
++}
++
++static int cc32rs512_info(struct flash_bank *bank, char *buf, int buf_size)
++{
++ struct cc32rs512_flash_bank *info = bank->driver_priv;
++ int printed;
++
++ printed = snprintf(buf, buf_size, "cc32rs512 flash driver\n");
++ buf += printed;
++ buf_size -= printed;
++
++ printed = snprintf(buf, buf_size, "Page Size: %u, Buffer Base: 0x%08x\n",
++ info->sector_size, info->flbuf);
++ buf += printed;
++ buf_size -= printed;
++
++ return ERROR_OK;
++}
++
++static int cc32rs512_probe(struct flash_bank *bank)
++{
++
++ if (bank->target->state != TARGET_HALTED) {
++ LOG_ERROR("Target not halted");
++ return ERROR_TARGET_NOT_HALTED;
++ }
++ /* there's no way to probe this peripheral */
++ return ERROR_OK;
++}
++
++static const struct command_registration cc32rs512_command_handlers[] = {
++ {
++ .name = "cc32rs512",
++ .mode = COMMAND_ANY,
++ .help = "cc32rs512 flash command group",
++ .chain = hello_command_handlers,
++ },
++ COMMAND_REGISTRATION_DONE
++};
++
++struct flash_driver cc32rs512_flash = {
++ .name = "cc32rs512",
++ .commands = cc32rs512_command_handlers,
++ .flash_bank_command = cc32rs512_flash_bank_command,
++ .erase = cc32rs512_erase,
++ .protect = cc32rs512_protect,
++ .write = cc32rs512_write,
++ .read = default_flash_read,
++ .probe = cc32rs512_probe,
++ .auto_probe = cc32rs512_probe,
++ .erase_check = default_flash_blank_check,
++ .protect_check = cc32rs512_protect_check,
++ .info = cc32rs512_info
++};
+diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
+index 69c3387..fa0e199 100644
+--- a/src/flash/nor/drivers.c
++++ b/src/flash/nor/drivers.c
+@@ -48,6 +48,7 @@ extern struct flash_driver em357_flash;
+ extern struct flash_driver dsp5680xx_flash;
+ extern struct flash_driver fm3_flash;
+ extern struct flash_driver kinetis_flash;
++extern struct flash_driver cc32rs512_flash;
+
+ /**
+ * The list of built-in flash drivers.
+@@ -80,6 +81,7 @@ static struct flash_driver *flash_drivers[] = {
+ &fm3_flash,
+ &dsp5680xx_flash,
+ &kinetis_flash,
++ &cc32rs512_flash,
+ NULL,
+ };
+
+--
+1.7.10.4
+
diff --git a/openocd/cc32rs512.cfg b/openocd/cc32rs512.cfg
new file mode 100644
index 0000000..96a25d8
--- /dev/null
+++ b/openocd/cc32rs512.cfg
@@ -0,0 +1,21 @@
+reset_config trst_and_srst
+source [find interface/ftdi/jtagkey.cfg]
+#jtag_rclk 1000
+adapter_khz 1000
+
+
+set _CHIPNAME cc32rs512
+
+set _ENDIAN little
+
+set _CPUTAPID 0x11701f0f
+
+jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
+
+set _TARGETNAME $_CHIPNAME.cpu
+
+target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME -variant arm7tdmi
+
+set _FLASHNAME $_CHIPNAME.flash0
+# driver base_addr size chip_width bus_width target_number
+flash bank $_FLASHNAME cc32rs512 0x00000000 0x80000 0 0 $_TARGETNAME