X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fcore.c;h=2c3b2f8212c1d976072fce2349cbd40894819542;hb=c69553cbc51770f61cf3b9225d46d058fa2544d0;hp=429bad6762dcbe606cb776f5f39e1eceefc4cfd0;hpb=9ab7636ce6276d222662be431a1e6be96d9d34c0;p=openocd.git diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 429bad6762..2c3b2f8212 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -46,7 +46,7 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last) retval = bank->driver->erase(bank, first, last); if (retval != ERROR_OK) { - LOG_ERROR("failed erasing sectors %d to %d (%d)", first, last, retval); + LOG_ERROR("failed erasing sectors %d to %d", first, last); } return retval; @@ -80,7 +80,7 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) retval = bank->driver->protect(bank, set, first, last); if (retval != ERROR_OK) { - LOG_ERROR("failed setting protection for areas %d to %d (%d)", first, last, retval); + LOG_ERROR("failed setting protection for areas %d to %d", first, last); } return retval; @@ -94,8 +94,8 @@ int flash_driver_write(struct flash_bank *bank, retval = bank->driver->write(bank, buffer, offset, count); if (retval != ERROR_OK) { - LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " (%d)", - bank->base, offset, retval); + LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, + bank->base, offset); } return retval; @@ -111,8 +111,8 @@ int flash_driver_read(struct flash_bank *bank, retval = bank->driver->read(bank, buffer, offset, count); if (retval != ERROR_OK) { - LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " (%d)", - bank->base, offset, retval); + LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32, + bank->base, offset); } return retval; @@ -197,7 +197,7 @@ struct flash_bank *get_flash_bank_by_name_noprobe(const char *name) return NULL; } -struct flash_bank *get_flash_bank_by_name(const char *name) +int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result) { struct flash_bank *bank; int retval; @@ -209,12 +209,13 @@ struct flash_bank *get_flash_bank_by_name(const char *name) if (retval != ERROR_OK) { - LOG_ERROR("auto_probe failed %d\n", retval); - return NULL; + LOG_ERROR("auto_probe failed\n"); + return retval; } } - return bank; + *bank_result = bank; + return ERROR_OK; } int get_flash_bank_by_num(int num, struct flash_bank **bank) @@ -231,15 +232,16 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank) if (retval != ERROR_OK) { - LOG_ERROR("auto_probe failed %d\n", retval); + LOG_ERROR("auto_probe failed\n"); return retval; } *bank = p; return ERROR_OK; } -/* lookup flash bank by address */ -struct flash_bank *get_flash_bank_by_addr(struct target *target, uint32_t addr) +/* lookup flash bank by address, bank not found is success, but + * result_bank is set to NULL. */ +int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank) { struct flash_bank *c; @@ -251,15 +253,23 @@ struct flash_bank *get_flash_bank_by_addr(struct target *target, uint32_t addr) if (retval != ERROR_OK) { - LOG_ERROR("auto_probe failed %d\n", retval); - return NULL; + LOG_ERROR("auto_probe failed\n"); + return retval; } /* check whether address belongs to this flash bank */ if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target) - return c; + { + *result_bank = c; + return ERROR_OK; + } } - LOG_ERROR("No flash at address 0x%08" PRIx32 "\n", addr); - return NULL; + *result_bank = NULL; + if (check) + { + LOG_ERROR("No flash at address 0x%08" PRIx32 "\n", addr); + return ERROR_FAIL; + } + return ERROR_OK; } int default_flash_mem_blank_check(struct flash_bank *bank) @@ -369,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)) { @@ -379,8 +389,9 @@ static int flash_iterate_address_range(struct target *target, int last = -1; int i; - if ((c = get_flash_bank_by_addr(target, addr)) == NULL) - return ERROR_FLASH_DST_OUT_OF_BANK; /* no corresponding bank found */ + int retval = get_flash_bank_by_addr(target, addr, true, &c); + if (retval != ERROR_OK) + return retval; if (c->size == 0 || c->num_sectors == 0) { @@ -487,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) { @@ -511,9 +559,9 @@ int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t le static int compare_section (const void * a, const void * b) { - struct imageection *b1, *b2; - b1=*((struct imageection **)a); - b2=*((struct imageection **)b); + struct imagesection *b1, *b2; + b1=*((struct imagesection **)a); + b2=*((struct imagesection **)b); if (b1->base_address == b2->base_address) { @@ -557,7 +605,7 @@ int flash_write_unlock(struct target *target, struct image *image, /* This fn requires all sections to be in ascending order of addresses, * whereas an image can have sections out of order. */ - struct imageection **sections = malloc(sizeof(struct imageection *) * + struct imagesection **sections = malloc(sizeof(struct imagesection *) * image->num_sections); int i; for (i = 0; i < image->num_sections; i++) @@ -565,7 +613,7 @@ int flash_write_unlock(struct target *target, struct image *image, sections[i] = &image->sections[i]; } - qsort(sections, image->num_sections, sizeof(struct imageection *), + qsort(sections, image->num_sections, sizeof(struct imagesection *), compare_section); /* loop until we reach end of the image */ @@ -588,7 +636,12 @@ int flash_write_unlock(struct target *target, struct image *image, } /* find the corresponding flash bank */ - if ((c = get_flash_bank_by_addr(target, run_address)) == NULL) + retval = get_flash_bank_by_addr(target, run_address, false, &c); + if (retval != ERROR_OK) + { + goto done; + } + if (c == NULL) { section++; /* and skip it */ section_offset = 0; @@ -638,8 +691,13 @@ int flash_write_unlock(struct target *target, struct image *image, if (run_address + run_size - 1 > c->base + c->size - 1) { - LOG_ERROR("The image is too big for the flash"); - return ERROR_FAIL; + /* If we have more than one flash chip back to back, then we limit + * the current write operation to the current chip. + */ + LOG_DEBUG("Truncate flash run size to the current flash chip."); + + run_size = c->base + c->size - run_address; + assert(run_size > 0); } /* If we're applying any sector automagic, then pad this @@ -665,6 +723,12 @@ int flash_write_unlock(struct target *target, struct image *image, /* allocate buffer */ buffer = malloc(run_size); + if (buffer == NULL) + { + LOG_ERROR("Out of memory for flash bank buffer"); + retval = ERROR_FAIL; + goto done; + } buffer_size = 0; /* read sections to the buffer */ @@ -682,7 +746,7 @@ int flash_write_unlock(struct target *target, struct image *image, * list of pointers to sections to invoke image_read_section()... */ intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections; - int t_section_num = diff / sizeof(struct imageection); + int t_section_num = diff / sizeof(struct imagesection); LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d", (int)section,