X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fcore.c;h=ab69a328bd8497ed3ad41dc29d7ee2e6e9e9accd;hp=cc2ecac08538a7c413826c14af1473224561a4ea;hb=93bc4ec40ffb9c30f170af3f1e3551c4b198507f;hpb=f132fcf636361009b4125827351ef01556d49b31 diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index cc2ecac085..ab69a328bd 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 @@ -52,10 +50,17 @@ 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 retval; + int num_blocks; + + if (bank->num_prot_blocks) + num_blocks = bank->num_prot_blocks; + else + num_blocks = bank->num_sectors; + /* callers may not supply illegal parameters ... */ - if (first < 0 || first > last || last >= bank->num_sectors) { - LOG_ERROR("illegal sector range"); + if (first < 0 || first > last || last >= num_blocks) { + LOG_ERROR("illegal protection block range"); return ERROR_FAIL; } @@ -71,11 +76,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) * the target could have reset, power cycled, been hot plugged, * the application could have run, etc. * - * Drivers only receive valid sector range. + * Drivers only receive valid protection block range. */ retval = bank->driver->protect(bank, set, first, last); if (retval != ERROR_OK) - LOG_ERROR("failed setting protection for areas %d to %d", first, last); + LOG_ERROR("failed setting protection for blocks %d to %d", first, last); return retval; } @@ -232,6 +237,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 +248,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; } @@ -287,7 +295,7 @@ static int default_flash_mem_blank_check(struct flash_bank *bank) goto done; for (nBytes = 0; nBytes < chunk; nBytes++) { - if (buffer[nBytes] != 0xFF) { + if (buffer[nBytes] != bank->erased_value) { bank->sectors[i].is_erased = 0; break; } @@ -318,12 +326,12 @@ int default_flash_blank_check(struct flash_bank *bank) uint32_t address = bank->base + bank->sectors[i].offset; uint32_t size = bank->sectors[i].size; - retval = target_blank_check_memory(target, address, size, &blank); + retval = target_blank_check_memory(target, address, size, &blank, bank->erased_value); if (retval != ERROR_OK) { fast_check = 0; break; } - if (blank == 0xFF) + if (blank == bank->erased_value) bank->sectors[i].is_erased = 1; else bank->sectors[i].is_erased = 0; @@ -342,8 +350,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 +363,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 +399,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 +491,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 +511,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 +527,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 +542,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) @@ -761,3 +783,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; +}