summaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
authorSpencer Oliver <ntfreak@users.sourceforge.net>2010-05-24 11:41:50 +0100
committerSpencer Oliver <ntfreak@users.sourceforge.net>2010-05-26 11:10:15 +0100
commit5319ccd7eb4761f1481dcbb041b256848efc005e (patch)
treeacf381a6b44b3db4c7fe76b074dbb5960b6bafc2 /src/flash
parentef72484b785ec7462a0415afea679d08b864c7fb (diff)
downloadopenocd_libswd-5319ccd7eb4761f1481dcbb041b256848efc005e.tar.gz
openocd_libswd-5319ccd7eb4761f1481dcbb041b256848efc005e.tar.bz2
openocd_libswd-5319ccd7eb4761f1481dcbb041b256848efc005e.tar.xz
openocd_libswd-5319ccd7eb4761f1481dcbb041b256848efc005e.zip
flash: add virtual flash bank driver
This adds a virtual flash bank driver that allows virtual banks to be defined that refer to an existing flash bank. For example the real address for bank0 on the pic32 is 0x1fc00000 but the user program will either be in kseg0 (0xbfc00000) or kseg1 (0x9fc00000). This also means that gdb will be aware of all the read only flash addresses. Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
Diffstat (limited to 'src/flash')
-rw-r--r--src/flash/nor/Makefile.am3
-rw-r--r--src/flash/nor/drivers.c2
-rw-r--r--src/flash/nor/virtual.c244
3 files changed, 248 insertions, 1 deletions
diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am
index 5d0a4dfc..eec6f504 100644
--- a/src/flash/nor/Makefile.am
+++ b/src/flash/nor/Makefile.am
@@ -28,7 +28,8 @@ NOR_DRIVERS = \
str7x.c \
str9x.c \
str9xpec.c \
- tms470.c
+ tms470.c \
+ virtual.c
noinst_HEADERS = \
at91sam7.h \
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index 3e09a004..68f2f88a 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -39,6 +39,7 @@ extern struct flash_driver ocl_flash;
extern struct flash_driver pic32mx_flash;
extern struct flash_driver avr_flash;
extern struct flash_driver faux_flash;
+extern struct flash_driver virtual_flash;
/**
* The list of built-in flash drivers.
@@ -63,6 +64,7 @@ static struct flash_driver *flash_drivers[] = {
&pic32mx_flash,
&avr_flash,
&faux_flash,
+ &virtual_flash,
NULL,
};
diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c
new file mode 100644
index 00000000..4908c0c8
--- /dev/null
+++ b/src/flash/nor/virtual.c
@@ -0,0 +1,244 @@
+/***************************************************************************
+ * Copyright (C) 2010 by Spencer Oliver *
+ * spen@spen-soft.co.uk *
+ * *
+ * 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"
+
+static struct flash_bank* virtual_get_master_bank(struct flash_bank *bank)
+{
+ struct flash_bank* master_bank;
+
+ master_bank = get_flash_bank_by_name(bank->driver_priv);
+ if (master_bank == NULL) {
+ LOG_ERROR("master flash bank '%s' does not exist", (char*)bank->driver_priv);
+ }
+
+ return master_bank;
+}
+
+static void virtual_update_bank_info(struct flash_bank *bank)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+
+ if (master_bank == NULL) {
+ return;
+ }
+
+ /* update the info we do not have */
+ bank->size = master_bank->size;
+ bank->chip_width = master_bank->chip_width;
+ bank->bus_width = master_bank->bus_width;
+ bank->num_sectors = master_bank->num_sectors;
+ bank->sectors = master_bank->sectors;
+}
+
+FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command)
+{
+ if (CMD_ARGC < 7)
+ {
+ LOG_WARNING("incomplete flash_bank virtual configuration");
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* get the master flash bank */
+ const char *bank_name = CMD_ARGV[6];
+ struct flash_bank *master_bank = get_flash_bank_by_name(bank_name);
+
+ if (master_bank == NULL)
+ {
+ LOG_ERROR("master flash bank '%s' does not exist", bank_name);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* save master bank name - use this to get settings later */
+ bank->driver_priv = strdup(bank_name);
+
+ return ERROR_OK;
+}
+
+static int virtual_protect(struct flash_bank *bank, int set, int first, int last)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+ int retval;
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* call master handler */
+ if ((retval = master_bank->driver->protect(master_bank, set,
+ first, last)) != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+static int virtual_protect_check(struct flash_bank *bank)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+ int retval;
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* call master handler */
+ if ((retval = master_bank->driver->protect_check(master_bank)) != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+static int virtual_erase(struct flash_bank *bank, int first, int last)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+ int retval;
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* call master handler */
+ if ((retval = master_bank->driver->erase(master_bank,
+ first, last)) != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+static int virtual_write(struct flash_bank *bank, uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+ int retval;
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* call master handler */
+ if ((retval = master_bank->driver->write(master_bank, buffer,
+ offset, count)) != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+static int virtual_probe(struct flash_bank *bank)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+ int retval;
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* call master handler */
+ if ((retval = master_bank->driver->probe(master_bank)) != ERROR_OK)
+ return retval;
+
+ /* update the info we do not have */
+ virtual_update_bank_info(bank);
+
+ return ERROR_OK;
+}
+
+static int virtual_auto_probe(struct flash_bank *bank)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+ int retval;
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* call master handler */
+ if ((retval = master_bank->driver->auto_probe(master_bank)) != ERROR_OK)
+ return retval;
+
+ /* update the info we do not have */
+ virtual_update_bank_info(bank);
+
+ return ERROR_OK;
+}
+
+static int virtual_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ snprintf(buf, buf_size, "%s driver for flash bank %s at 0x%8.8" PRIx32 "",
+ bank->driver->name, master_bank->name, master_bank->base);
+
+ return ERROR_OK;
+}
+
+int virtual_blank_check(struct flash_bank *bank)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+ int retval;
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* call master handler */
+ if ((retval = master_bank->driver->erase_check(master_bank)) != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+int virtual_flash_read(struct flash_bank *bank,
+ uint8_t *buffer, uint32_t offset, uint32_t count)
+{
+ struct flash_bank *master_bank = virtual_get_master_bank(bank);
+ int retval;
+
+ if (master_bank == NULL) {
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ /* call master handler */
+ if ((retval = master_bank->driver->read(master_bank, buffer,
+ offset, count)) != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+}
+
+struct flash_driver virtual_flash = {
+ .name = "virtual",
+ .flash_bank_command = virtual_flash_bank_command,
+ .erase = virtual_erase,
+ .protect = virtual_protect,
+ .write = virtual_write,
+ .read = virtual_flash_read,
+ .probe = virtual_probe,
+ .auto_probe = virtual_auto_probe,
+ .erase_check = virtual_blank_check,
+ .protect_check = virtual_protect_check,
+ .info = virtual_info,
+};