diff options
Diffstat (limited to 'src/flash')
-rw-r--r-- | src/flash/at91sam7.c | 35 | ||||
-rw-r--r-- | src/flash/flash.c | 64 | ||||
-rw-r--r-- | src/flash/nand.c | 2 |
3 files changed, 76 insertions, 25 deletions
diff --git a/src/flash/at91sam7.c b/src/flash/at91sam7.c index fdc1c51a..b4b34758 100644 --- a/src/flash/at91sam7.c +++ b/src/flash/at91sam7.c @@ -326,7 +326,15 @@ int at91sam7_read_part_info(struct flash_bank_s *bank) at91sam7_info->cidr_version = cidr&0x001F; bank->size = NVPSIZ[at91sam7_info->cidr_nvpsiz]; at91sam7_info->target_name = "Unknown"; - + + /* Support just for bulk erase of the whole device */ + bank->num_sectors = 1; + bank->sectors = malloc(sizeof(flash_sector_t)); + bank->sectors[0].offset = 0; + bank->sectors[0].size = bank->size; + bank->sectors[0].is_erased = -1; + bank->sectors[0].is_protected = -1; + DEBUG("nvptyp: 0x%3.3x, arch: 0x%4.4x", at91sam7_info->cidr_nvptyp, at91sam7_info->cidr_arch ); /* Read main and master clock freqency register */ @@ -565,22 +573,27 @@ int at91sam7_erase(struct flash_bank_s *bank, int first, int last) return ERROR_FLASH_OPERATION_FAILED; } - if ((first < 0) || (last < first) || (last >= at91sam7_info->num_lockbits)) + if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { - return ERROR_FLASH_SECTOR_INVALID; + if ((first == 0) && (last == (at91sam7_info->num_lockbits-1))) + { + WARNING("Sector numbers based on lockbit count, probably a deprecated script"); + last = bank->num_sectors-1; + } + else return ERROR_FLASH_SECTOR_INVALID; } - /* Configure the flash controller timing */ - at91sam7_read_clock_info(bank); - at91sam7_set_flash_mode(bank,FMR_TIMING_FLASH); - - if ((first == 0) && (last == (at91sam7_info->num_lockbits-1))) + if ((first != 0) || (last != (bank->num_sectors-1))) { - return at91sam7_flash_command(bank, EA, 0); + WARNING("Can only erase the whole flash area, pages are autoerased on write"); + return ERROR_FLASH_OPERATION_FAILED; } - WARNING("Can only erase the whole flash area, pages are autoerased on write"); - return ERROR_FLASH_OPERATION_FAILED; + /* Configure the flash controller timing */ + at91sam7_read_clock_info(bank); + at91sam7_set_flash_mode(bank,FMR_TIMING_FLASH); + + return at91sam7_flash_command(bank, EA, 0); } int at91sam7_protect(struct flash_bank_s *bank, int set, int first, int last) diff --git a/src/flash/flash.c b/src/flash/flash.c index e3389b19..4481fc63 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -738,24 +738,36 @@ int flash_erase(target_t *target, u32 addr, u32 length) int flash_write(target_t *target, image_t *image, u32 *image_size, char **error_str, u32 *failed) { + int last_section; int section; + int next_section; int retval; *image_size = 0; /* for each section in the image */ - for (section = 0; section < image->num_sections; section++) + last_section = 0; + section = 0; + while (section < image->num_sections) { u32 offset = 0; u32 address = image->sections[section].base_address; u32 size = image->sections[section].size; - failed[section] = 0; + /* collect consecutive sections */ + next_section = section + 1; + while ((next_section < image->num_sections) + && (image->sections[next_section].base_address == (address + size))) + { + size += image->sections[next_section].size; + next_section++; + } while (size != 0) { flash_bank_t *c; u32 thisrun_size = size; + u32 buffer_size; u32 size_read; u8 *buffer; @@ -767,23 +779,50 @@ int flash_write(target_t *target, image_t *image, u32 *image_size, char **error_ break; } - /* check whether it fits, split into multiple runs if not */ + /* check whether cumulated sections fit the bank, split into multiple runs if not */ if ((address + size) > (c->base + c->size)) thisrun_size = c->base + c->size - address; buffer = malloc(thisrun_size); - if (((retval = image_read_section(image, section, offset, size, buffer, &size_read)) != ERROR_OK) - || (thisrun_size != size_read)) + buffer_size = 0; + + while (buffer_size < thisrun_size) { - *error_str = malloc(FLASH_MAX_ERROR_STR); - snprintf(*error_str, FLASH_MAX_ERROR_STR, "error reading from image"); - return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE; + u32 thissection_size = image->sections[section].size - offset; + + if ((retval = image_read_section(image, section, offset, + MIN(thisrun_size, thissection_size), + buffer + buffer_size, &size_read)) != ERROR_OK) + { + *error_str = malloc(FLASH_MAX_ERROR_STR); + snprintf(*error_str, FLASH_MAX_ERROR_STR, "error reading from image"); + return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE; + } + + /* see if we're done with the current section */ + if (thissection_size < thisrun_size) + { + /* start with the next section */ + offset = 0; + failed[section] = 0; + section++; + } + else + { + /* continue inside the current section */ + offset += size_read; + } + + buffer_size += size_read; } if ((retval = c->driver->write(c, buffer, address - c->base, thisrun_size)) != ERROR_OK) { - /* mark the current section as failed */ - failed[section] = 1; + int i; + /* mark sections as failed */ + for (i = last_section; i <= section; i++) + failed[i] = 1; + *error_str = malloc(FLASH_MAX_ERROR_STR); switch (retval) { @@ -817,12 +856,11 @@ int flash_write(target_t *target, image_t *image, u32 *image_size, char **error_ free(buffer); - offset += thisrun_size; address += thisrun_size; size -= thisrun_size; + *image_size += thisrun_size; + last_section = section; } - - *image_size += image->sections[section].size; } return ERROR_OK; diff --git a/src/flash/nand.c b/src/flash/nand.c index d06a232c..52c92328 100644 --- a/src/flash/nand.c +++ b/src/flash/nand.c @@ -256,7 +256,7 @@ int handle_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, cha int nand_register_commands(struct command_context_s *cmd_ctx) { - nand_cmd = register_command(cmd_ctx, NULL, "nand", NULL, COMMAND_ANY, NULL); + nand_cmd = register_command(cmd_ctx, NULL, "nand", NULL, COMMAND_ANY, "NAND specific commands"); register_command(cmd_ctx, nand_cmd, "device", handle_nand_device_command, COMMAND_CONFIG, NULL); |