summaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
Diffstat (limited to 'src/flash')
-rw-r--r--src/flash/at91sam7.c35
-rw-r--r--src/flash/flash.c64
-rw-r--r--src/flash/nand.c2
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);