X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fcore.c;h=da73bf6405fab4730a422337f8cbd5af6877c508;hp=00f73f214ae0a4a00a392cc1ab48ca7df0c4950f;hb=7bbd6c76838ffc639226897328d8ec7069b1769d;hpb=bc8be110ff314cab0e09792a05b6871672c18302 diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 00f73f214a..da73bf6405 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -178,7 +178,7 @@ int flash_get_bank_count(void) return i; } -struct flash_bank *get_flash_bank_by_name(const char *name) +struct flash_bank *get_flash_bank_by_name_noprobe(const char *name) { unsigned requested = get_flash_name_index(name); unsigned found = 0; @@ -197,6 +197,27 @@ struct flash_bank *get_flash_bank_by_name(const char *name) return NULL; } +int get_flash_bank_by_name(const char *name, struct flash_bank **bank_result) +{ + struct flash_bank *bank; + int retval; + + bank = get_flash_bank_by_name_noprobe(name); + if (bank != NULL) + { + retval = bank->driver->auto_probe(bank); + + if (retval != ERROR_OK) + { + LOG_ERROR("auto_probe failed %d\n", retval); + return retval; + } + } + + *bank_result = bank; + return ERROR_OK; +} + int get_flash_bank_by_num(int num, struct flash_bank **bank) { struct flash_bank *p = get_flash_bank_by_num_noprobe(num); @@ -218,8 +239,9 @@ int get_flash_bank_by_num(int num, struct flash_bank **bank) 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; @@ -232,14 +254,22 @@ 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; + 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) @@ -359,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) { @@ -491,9 +522,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) { @@ -537,7 +568,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++) @@ -545,7 +576,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 */ @@ -568,7 +599,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; @@ -616,7 +652,16 @@ int flash_write_unlock(struct target *target, struct image *image, LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes); } - assert (run_address + run_size - 1 <= c->base + c->size - 1); + if (run_address + run_size - 1 > c->base + c->size - 1) + { + /* 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 * (maybe-combined) segment to the end of its last sector. @@ -641,6 +686,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 */ @@ -658,9 +709,9 @@ 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", + LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d", (int)section, (int)t_section_num, (int)section_offset, (int)buffer_size, (int)size_read); if ((retval = image_read_section(image, t_section_num, section_offset,