- fixed several bugs in flash writing code (thanks to Pavel Chromy)
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 16 Aug 2007 09:09:44 +0000 (09:09 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 16 Aug 2007 09:09:44 +0000 (09:09 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@196 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/flash/flash.c
src/flash/flash.h
src/server/gdb_server.c

index 4481fc638955433527fed73d7f97c88a49ba7214..19d5c3c5870a7b1b5c65d71747ee46a4bdcd0954 100644 (file)
@@ -514,9 +514,9 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
        target_t *target = get_current_target(cmd_ctx);
        
        image_t image;
-       u32 image_size;
+       u32 written;
        char *error_str;
-       u32 *failed;
+       int *failed;
        
        int i;
        
@@ -564,9 +564,9 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
                return ERROR_OK;
        }
        
-       failed = malloc(sizeof(u32) * image.num_sections);
+       failed = malloc(sizeof(int) * image.num_sections);
 
-       if ((retval = flash_write(target, &image, &image_size, &error_str, failed)) != ERROR_OK)
+       if ((retval = flash_write(target, &image, &written, &error_str, failed)) != ERROR_OK)
        {
                command_print(cmd_ctx, "failed writing image %s: %s", args[0], error_str);
                free(error_str);
@@ -583,8 +583,8 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm
        
        duration_stop_measure(&duration, &duration_text);
        command_print(cmd_ctx, "wrote %u byte from file %s in %s (%f kb/s)",
-               image_size, args[0], duration_text,
-               (float)image_size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
+               written, args[0], duration_text,
+               (float)written / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
        free(duration_text);
 
        image_close(&image);
@@ -736,132 +736,160 @@ int flash_erase(target_t *target, u32 addr, u32 length)
        return c->driver->erase(c, first, last);
 }
 
-int flash_write(target_t *target, image_t *image, u32 *image_size, char **error_str, u32 *failed)
+/* write an image to flash memory of the given target */
+int flash_write(target_t *target, image_t *image, u32 *written, char **error_str, int *failed)
 {
-       int last_section;
-       int section;
-       int next_section;
        int retval;
-       
-       *image_size = 0;
-       
-       /* for each section in the image */
-       last_section = 0;
+       int i;
+
+       int section;
+       u32 section_offset;
+
        section = 0;
+       section_offset = 0;
+
+       if (written)
+               *written = 0;
+       
+       if (failed != NULL)
+               for (i = 0; i < image->num_sections; i++)
+                       failed[i] = 0;
+
+       /* loop until we reach end of the image */
        while (section < image->num_sections)
        {
-               u32 offset = 0;
-               u32 address = image->sections[section].base_address;
-               u32 size = image->sections[section].size;
-               
-               /* collect consecutive sections */
-               next_section = section + 1;
-               while ((next_section < image->num_sections)
-                               && (image->sections[next_section].base_address == (address + size)))
+               flash_bank_t *c;
+               u32 buffer_size;
+               u8 *buffer;
+               int section_first;
+               int section_last;
+               u32 run_address = image->sections[section].base_address+section_offset;
+               u32 run_size = image->sections[section].size-section_offset;
+
+               if (image->sections[section].size ==  0)
                {
-                       size += image->sections[next_section].size;
-                       next_section++;
+                       WARNING("empty section %d", section);
+                       section++;
+                       section_offset = 0;
+                       continue;
                }
-               
-               while (size != 0)
+
+               /* find the corresponding flash bank */
+               if ((c = get_flash_bank_by_addr(target, run_address)) == NULL)
                {
-                       flash_bank_t *c;
-                       u32 thisrun_size = size;
-                       u32 buffer_size;
-                       u32 size_read;
-                       u8 *buffer;
-                       
-                       /* find the corresponding flash bank */
-                       if ((c = get_flash_bank_by_addr(target, address)) == NULL)
+                       if (failed == NULL)
                        {
-                               /* mark as failed, and skip the current section */
-                               failed[section] = 1;
-                               break;
+                               if (error_str == NULL)
+                                       return ERROR_FLASH_DST_OUT_OF_BANK; /* abort operation */
+                               *error_str = malloc(FLASH_MAX_ERROR_STR);
+                               snprintf(*error_str, FLASH_MAX_ERROR_STR, "no flash mapped at requested address");
+                               return ERROR_FLASH_DST_OUT_OF_BANK; /* abort operation */
                        }
-                       
-                       /* 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;
+                       failed[section] = ERROR_FLASH_DST_OUT_OF_BANK; /* mark the section as failed */
+                       section++; /* and skip it */
+                       section_offset = 0;
+                       continue;
+               }
+
+               /* collect consecutive sections which fall into the same bank */
+               section_first = section;
+               section_last = section;
+               while ((run_address + run_size < c->base + c->size)
+                               && (section_last + 1 < image->num_sections))
+               {
+                       if (image->sections[section_last + 1].base_address > (run_address + run_size))
+                               break;
+                       if (image->sections[section_last + 1].base_address < (run_address + run_size))
+                               WARNING("section %d out of order", section_last + 1);
+                       run_size += image->sections[++section_last].size;
+               }
+
+               /* fit the run into bank constraints */
+               if (run_address + run_size > c->base + c->size)
+                       run_size = c->base + c->size - run_address;
+
+               /* allocate buffer */
+               buffer = malloc(run_size);
+               buffer_size = 0;
 
-                       buffer = malloc(thisrun_size);
-                       buffer_size = 0;
+               /* read sections to the buffer */
+               while (buffer_size < run_size)
+               {
+                       u32 size_read;
+                       
+                       if (buffer_size - run_size <= image->sections[section].size - section_offset)
+                               size_read = buffer_size - run_size;
+                       else
+                               size_read = image->sections[section].size - section_offset;
                        
-                       while (buffer_size < thisrun_size)
+                       if ((retval = image_read_section(image, section, section_offset,
+                                       size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
                        {
-                               u32 thissection_size = image->sections[section].size - offset;
+                               free(buffer);
                                
-                               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");
+                               if (error_str == NULL)
                                        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;
-                               }
+                               *error_str = malloc(FLASH_MAX_ERROR_STR);
                                
-                               buffer_size += size_read;
+                               /* if image_read_section returned an error there's an error string we can pass on */
+                               if (retval != ERROR_OK)
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "error reading from image: %s", image->error_str);
+                               else
+                                       
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "error reading from image");
+                               return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE;
                        }
-                       
-                       if ((retval = c->driver->write(c, buffer, address - c->base, thisrun_size)) != ERROR_OK)
+
+                       buffer_size += size_read;
+                       section_offset += size_read;
+
+                       if (section_offset >= image->sections[section].size)
                        {
-                               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)
-                               {
-                                       case ERROR_TARGET_NOT_HALTED:
-                                               snprintf(*error_str, FLASH_MAX_ERROR_STR, "can't flash image while target is running");
-                                               break;
-                                       case ERROR_INVALID_ARGUMENTS:
-                                               snprintf(*error_str, FLASH_MAX_ERROR_STR, "flash driver can't fulfill request");
-                                               break;
-                                       case ERROR_FLASH_OPERATION_FAILED:
-                                               snprintf(*error_str, FLASH_MAX_ERROR_STR, "flash program error");
-                                               break;
-                                       case ERROR_FLASH_DST_BREAKS_ALIGNMENT:
-                                               snprintf(*error_str, FLASH_MAX_ERROR_STR, "offset breaks required alignment");
-                                               break;
-                                       case ERROR_FLASH_DST_OUT_OF_BANK:
-                                               snprintf(*error_str, FLASH_MAX_ERROR_STR, "no flash mapped at requested address");
-                                               break;
-                                       case ERROR_FLASH_SECTOR_NOT_ERASED:
-                                               snprintf(*error_str, FLASH_MAX_ERROR_STR, "destination sector(s) not erased");
-                                               break;
-                                       default:
-                                               snprintf(*error_str, FLASH_MAX_ERROR_STR, "unknown error: %i", retval);
-                               }
-                               
-                               free(buffer);
-                               
-                               /* abort operation */
-                               return retval;
+                               section++;
+                               section_offset = 0;
                        }
-                       
-                       free(buffer);
-                       
-                       address += thisrun_size;
-                       size -= thisrun_size;
-                       *image_size += thisrun_size;
-                       last_section = section;
                }
+
+               retval = c->driver->write(c, buffer, run_address - c->base, run_size);
+               free(buffer);
+
+               if (retval != ERROR_OK)
+               {
+                       if (error_str == NULL)
+                               return retval; /* abort operation */
+
+                       *error_str = malloc(FLASH_MAX_ERROR_STR);
+                       switch (retval)
+                       {
+                               case ERROR_TARGET_NOT_HALTED:
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "can't flash image while target is running");
+                                       break;
+                               case ERROR_INVALID_ARGUMENTS:
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "flash driver can't fulfill request");
+                                       break;
+                               case ERROR_FLASH_OPERATION_FAILED:
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "flash program error");
+                                       break;
+                               case ERROR_FLASH_DST_BREAKS_ALIGNMENT:
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "offset breaks required alignment");
+                                       break;
+                               case ERROR_FLASH_DST_OUT_OF_BANK:
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "no flash mapped at requested address");
+                                       break;
+                               case ERROR_FLASH_SECTOR_NOT_ERASED:
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "destination sector(s) not erased");
+                                       break;
+                               default:
+                                       snprintf(*error_str, FLASH_MAX_ERROR_STR, "unknown error: %i", retval);
+                       }
+
+                       return retval; /* abort operation */
+               }
+
+               if (written != NULL)
+                       *written += run_size; /* add run size to total written counter */
        }
-       
+
        return ERROR_OK;
 }
index 513ede8130a1c1c6a4be447056b2741b1241e74d..7ba6ff54e688125e456893456779cb03b61efc89 100644 (file)
@@ -67,7 +67,7 @@ extern int flash_register_commands(struct command_context_s *cmd_ctx);
 extern int flash_init(struct command_context_s *cmd_ctx);
 
 extern int flash_erase(target_t *target, u32 addr, u32 length);
-extern int flash_write(target_t *target, image_t *image, u32 *image_size, char **error, u32 *failed);
+extern int flash_write(target_t *target, image_t *image, u32 *written, char **error, int *failed);
 
 extern flash_bank_t *get_flash_bank_by_num(int num);
 extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr);
index 3481625e9a359eab8d9ccf3a70364b96e665cec8..5dd6f3c207f9529a653cc99cadecf608a43bf398 100644 (file)
@@ -1270,29 +1270,29 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
 
        if (!strcmp(packet, "vFlashDone"))
        {
-               u32 image_size;
+               u32 written;
                char *error_str;
-               u32 *failed = malloc(sizeof(u32) * gdb_connection->vflash_image->num_sections);
-               
+
                /* process the flashing buffer */
-               if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &image_size, &error_str, failed)) != ERROR_OK)
+               if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, &error_str, NULL)) != ERROR_OK)
                {
                        if (result == ERROR_FLASH_DST_OUT_OF_BANK)
                                gdb_put_packet(connection, "E.memtype", 9);
                        else
                                gdb_send_error(connection, EIO);
                        
-                       ERROR("flash writing failed: %s", error_str);
-                       free(error_str);
+                       if (error_str)
+                       {
+                               ERROR("flash writing failed: %s", error_str);
+                               free(error_str);
+                       }
                }
                else
                {
-                       DEBUG("wrote %u bytes from vFlash image to flash", image_size);
+                       DEBUG("wrote %u bytes from vFlash image to flash", written);
                        gdb_put_packet(connection, "OK", 2);
                }
                
-               free(failed);
-               
                image_close(gdb_connection->vflash_image);
                free(gdb_connection->vflash_image);
                gdb_connection->vflash_image = NULL;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)