NOR: make flash_write_unlock() pad to sector end
authorDavid Brownell <dbrownell@users.sourceforge.net>
Sun, 27 Dec 2009 19:34:31 +0000 (11:34 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Sun, 27 Dec 2009 19:34:31 +0000 (11:34 -0800)
Resolve a regression when using newish automagic "write_image"
modes, by always padding to the end of affected sectors.

Also document some issues associated with those automagic options,
in the User's Guide and also some related code comments.

We might need similar padding at the *beginning* of some sectors,
but this is a minimalist fix for the problems which have currently
been reported (plus doc updates).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
doc/openocd.texi
src/flash/nor/core.c

index 1c20716c9d1e3b38e5da6b9e8addf47095da7a3b..154ecbcaec5e7ddc850b31bbe7d59e1e9d0ea311 100644 (file)
@@ -3857,8 +3857,29 @@ explicitly as @option{bin} (binary), @option{ihex} (Intel hex),
 The relevant flash sectors will be erased prior to programming
 if the @option{erase} parameter is given. If @option{unlock} is
 provided, then the flash banks are unlocked before erase and
-program. The flash bank to use is inferred from the @var{address} of
-each image segment.
+program. The flash bank to use is inferred from the address of
+each image section.
+
+@quotation Warning
+Be careful using the @option{erase} flag when the flash is holding
+data you want to preserve.
+Portions of the flash outside those described in the image's
+sections might be erased with no notice.
+@itemize
+@item
+When a section of the image being written does not fill out all the
+sectors it uses, the unwritten parts of those sectors are necessarily
+also erased, because sectors can't be partially erased.
+@item
+Data stored in sector "holes" between image sections are also affected.
+For example, "@command{flash write_image erase ...}" of an image with
+one byte at the beginning of a flash bank and one byte at the end
+erases the entire bank -- not just the two sectors being written.
+@end itemize
+Also, when flash protection is important, you must re-apply it after
+it has been removed by the @option{unlock} flag.
+@end quotation
+
 @end deffn
 
 @section Other Flash commands
index fe5372b6cd7cb901a752d0336289764f739708cc..5eb51cd2dad99dcfe58ed5552ea0202b6c4e1daa 100644 (file)
@@ -439,9 +439,26 @@ int flash_write_unlock(struct target *target, struct image *image,
                {
                        if (image->sections[section_last + 1].base_address < (run_address + run_size))
                        {
-                               LOG_DEBUG("section %d out of order(very slightly surprising, but supported)", section_last + 1);
+                               LOG_DEBUG("section %d out of order "
+                                               "(surprising, but supported)",
+                                               section_last + 1);
+                               /* REVISIT this can break with autoerase ...
+                                * clobbering data after it's written.
+                                */
                                break;
                        }
+
+                       /* REVISIT This needlessly touches sectors BETWEEN the
+                        * sections it's writing.  Without auto erase, it just
+                        * writes ones; unlikely to destroy data.
+                        *
+                        * With auto erase enabled, data in those sectors will
+                        * be needlessly destroyed; and some of the limited
+                        * number of flash erase cycles will be wasted...
+                        *
+                        * In both cases, the extra writes slow things down.
+                        */
+
                        /* if we have multiple sections within our image, flash programming could fail due to alignment issues
                         * attempt to rebuild a consecutive buffer for the flash loader */
                        pad_bytes = (image->sections[section_last + 1].base_address) - (run_address + run_size);
@@ -450,7 +467,6 @@ int flash_write_unlock(struct target *target, struct image *image,
                        padding[section_last] = pad_bytes;
                        run_size += image->sections[++section_last].size;
                        run_size += pad_bytes;
-                       padding[section_last] = 0;
 
                        LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
                }
@@ -458,11 +474,35 @@ int flash_write_unlock(struct target *target, struct image *image,
                /* fit the run into bank constraints */
                if (run_address + run_size - 1 > c->base + c->size - 1)
                {
+                       /* REVISIT isn't this superfluous, given the while()
+                        * loop conditions above??
+                        */
                        LOG_WARNING("writing %d bytes only - as image section is %d bytes and bank is only %d bytes", \
                                    (int)(c->base + c->size - run_address), (int)(run_size), (int)(c->size));
                        run_size = c->base + c->size - run_address;
                }
 
+               /* If we're applying any sector automagic, then pad this
+                * (maybe-combined) segment to the end of its last sector.
+                */
+               if (unlock || erase) {
+                       int sector;
+                       uint32_t offset_start = run_address - c->base;
+                       uint32_t offset_end = offset_start + run_size;
+                       uint32_t end = offset_end, delta;
+
+                       for (sector = 0; sector < c->num_sectors; sector++) {
+                               end = c->sectors[sector].offset
+                                               + c->sectors[sector].size;
+                               if (offset_end <= end)
+                                       break;
+                       }
+
+                       delta = end - offset_end;
+                       padding[section_last] += delta;
+                       run_size += delta;
+               }
+
                /* allocate buffer */
                buffer = malloc(run_size);
                buffer_size = 0;

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)