X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fcore.c;h=7a62ba1c76223d03f130d109ead872d7d6ff6a82;hp=21ea05d33782feb96d7934d42fdb4c5bda723532;hb=refs%2Fchanges%2F45%2F3545%2F6;hpb=08d4411b59dd8bd0e7d8009003b71d23acbf6eee diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 21ea05d337..7a62ba1c76 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -16,9 +16,7 @@ * 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. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -232,6 +230,9 @@ int get_flash_bank_by_addr(struct target *target, /* cycle through bank list */ for (c = flash_banks; c; c = c->next) { + if (c->target != target) + continue; + int retval; retval = c->driver->auto_probe(c); @@ -240,7 +241,7 @@ int get_flash_bank_by_addr(struct target *target, return retval; } /* check whether address belongs to this flash bank */ - if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target) { + if ((addr >= c->base) && (addr <= c->base + (c->size - 1))) { *result_bank = c; return ERROR_OK; } @@ -342,8 +343,9 @@ int default_flash_blank_check(struct flash_bank *bank) * and address. Maps an address range to a set of sectors, and issues * the callback() on that set ... e.g. to erase or unprotect its members. * - * (Note a current bad assumption: that protection operates on the same - * size sectors as erase operations use.) + * Parameter iterate_protect_blocks switches iteration of protect block + * instead of erase sectors. If there is no protect blocks array, sectors + * are used in iteration, so compatibility for old flash drivers is retained. * * The "pad_reason" parameter is a kind of boolean: when it's NULL, the * range must fit those sectors exactly. This is clearly safe; it can't @@ -354,13 +356,16 @@ int default_flash_blank_check(struct flash_bank *bank) */ static int flash_iterate_address_range_inner(struct target *target, char *pad_reason, uint32_t addr, uint32_t length, + bool iterate_protect_blocks, int (*callback)(struct flash_bank *bank, int first, int last)) { struct flash_bank *c; + struct flash_sector *block_array; uint32_t last_addr = addr + length; /* first address AFTER end */ int first = -1; int last = -1; int i; + int num_blocks; int retval = get_flash_bank_by_addr(target, addr, true, &c); if (retval != ERROR_OK) @@ -387,13 +392,21 @@ static int flash_iterate_address_range_inner(struct target *target, return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } - /** @todo: handle erasures that cross into adjacent banks */ - addr -= c->base; last_addr -= c->base; - for (i = 0; i < c->num_sectors; i++) { - struct flash_sector *f = c->sectors + i; + if (iterate_protect_blocks && c->prot_blocks && c->num_prot_blocks) { + block_array = c->prot_blocks; + num_blocks = c->num_prot_blocks; + } else { + block_array = c->sectors; + num_blocks = c->num_sectors; + iterate_protect_blocks = false; + } + + + for (i = 0; i < num_blocks; i++) { + struct flash_sector *f = &block_array[i]; uint32_t end = f->offset + f->size; /* start only on a sector boundary */ @@ -471,6 +484,7 @@ static int flash_iterate_address_range_inner(struct target *target, */ static int flash_iterate_address_range(struct target *target, char *pad_reason, uint32_t addr, uint32_t length, + bool iterate_protect_blocks, int (*callback)(struct flash_bank *bank, int first, int last)) { struct flash_bank *c; @@ -490,6 +504,7 @@ static int flash_iterate_address_range(struct target *target, } retval = flash_iterate_address_range_inner(target, pad_reason, addr, cur_length, + iterate_protect_blocks, callback); if (retval != ERROR_OK) break; @@ -505,7 +520,7 @@ int flash_erase_address_range(struct target *target, bool pad, uint32_t addr, uint32_t length) { return flash_iterate_address_range(target, pad ? "erase" : NULL, - addr, length, &flash_driver_erase); + addr, length, false, &flash_driver_erase); } static int flash_driver_unprotect(struct flash_bank *bank, int first, int last) @@ -520,7 +535,7 @@ int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t le * and doesn't restore it. */ return flash_iterate_address_range(target, "unprotect", - addr, length, &flash_driver_unprotect); + addr, length, true, &flash_driver_unprotect); } static int compare_section(const void *a, const void *b) @@ -595,7 +610,7 @@ int flash_write_unlock(struct target *target, struct image *image, if (retval != ERROR_OK) goto done; if (c == NULL) { - LOG_WARNING("no flash bank found for address %x", run_address); + LOG_WARNING("no flash bank found for address %" PRIx32, run_address); section++; /* and skip it */ section_offset = 0; continue; @@ -710,7 +725,7 @@ int flash_write_unlock(struct target *target, struct image *image, /* see if we need to pad the section */ while (padding[section]--) - (buffer + buffer_size)[size_read++] = 0xff; + (buffer + buffer_size)[size_read++] = c->default_padded_value; buffer_size += size_read; section_offset += size_read; @@ -761,3 +776,22 @@ int flash_write(struct target *target, struct image *image, { return flash_write_unlock(target, image, written, erase, false); } + +struct flash_sector *alloc_block_array(uint32_t offset, uint32_t size, int num_blocks) +{ + int i; + + struct flash_sector *array = calloc(num_blocks, sizeof(struct flash_sector)); + if (array == NULL) + return NULL; + + for (i = 0; i < num_blocks; i++) { + array[i].offset = offset; + array[i].size = size; + array[i].is_erased = -1; + array[i].is_protected = -1; + offset += size; + } + + return array; +}