summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorØyvind Harboe <oyvind.harboe@zylin.com>2010-11-22 11:16:40 +0100
committerØyvind Harboe <oyvind.harboe@zylin.com>2010-11-22 11:16:40 +0100
commit8902789f0de78f52d74e467017a064dcc568b66b (patch)
treec1d6a43589dae4e0499a0111546350ab53b5b6eb
parent17634b3760c58239f37d75113425e50fd3756470 (diff)
downloadopenocd+libswd-8902789f0de78f52d74e467017a064dcc568b66b.tar.gz
openocd+libswd-8902789f0de78f52d74e467017a064dcc568b66b.tar.bz2
openocd+libswd-8902789f0de78f52d74e467017a064dcc568b66b.tar.xz
openocd+libswd-8902789f0de78f52d74e467017a064dcc568b66b.zip
flash: iterating over an address range now handles multiple banks
e.g. flash erase_address now works across an address range that spans multiple flash chips. Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
-rw-r--r--src/flash/nor/core.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index da73bf64..ff467d3d 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -379,7 +379,7 @@ int default_flash_blank_check(struct flash_bank *bank)
* sectors will be added to the range, and that reason string is used when
* warning about those additions.
*/
-static int flash_iterate_address_range(struct target *target,
+static int flash_iterate_address_range_inner(struct target *target,
char *pad_reason, uint32_t addr, uint32_t length,
int (*callback)(struct flash_bank *bank, int first, int last))
{
@@ -498,6 +498,43 @@ static int flash_iterate_address_range(struct target *target,
return callback(c, first, last);
}
+/* The inner fn only handles a single bank, we could be spanning
+ * multiple chips.
+ */
+static int flash_iterate_address_range(struct target *target,
+ char *pad_reason, uint32_t addr, uint32_t length,
+ int (*callback)(struct flash_bank *bank, int first, int last))
+{
+ struct flash_bank *c;
+ int retval = ERROR_OK;
+
+ /* Danger! zero-length iterations means entire bank! */
+ do
+ {
+ retval = get_flash_bank_by_addr(target, addr, true, &c);
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint32_t cur_length = length;
+ /* check whether it all fits in this bank */
+ if (addr + length - 1 > c->base + c->size - 1)
+ {
+ LOG_DEBUG("iterating over more than one flash bank.");
+ cur_length = c->base + c->size - addr;
+ }
+ retval = flash_iterate_address_range_inner(target,
+ pad_reason, addr, cur_length,
+ callback);
+ if (retval != ERROR_OK)
+ break;
+
+ length -= cur_length;
+ addr += cur_length;
+ } while (length > 0);
+
+ return retval;
+}
+
int flash_erase_address_range(struct target *target,
bool pad, uint32_t addr, uint32_t length)
{