kinetis: ensure flash writes are not truncated
authorChristopher Kilgour <techie@whiterocker.com>
Sat, 7 Jul 2012 23:47:06 +0000 (16:47 -0700)
committerFreddie Chopin <freddie.chopin@gmail.com>
Wed, 29 Aug 2012 06:25:41 +0000 (06:25 +0000)
The number if longwords or "sections" (Freescale term) written for a Kinetis
flash write (4, 8, or 16 bytes depending on the part density/granularity) are
now rounded up to ensure there are no truncations when the desired write is
not a multiple of the minimum write size.

Change-Id: I8db40a8769d8ac5393a46cbf4e5ff0df82faf916
Signed-off-by: Christopher Kilgour <techie@whiterocker.com>
Reviewed-on: http://openocd.zylin.com/738
Tested-by: jenkins
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
src/flash/nor/kinetis.c

index e0bb5c20ba59784c1faf5c221ce8069bdf0b2025..71722c645fef6120155a95e0646a48ec0ae56d14 100644 (file)
@@ -351,32 +351,75 @@ static int kinetis_write(struct flash_bank *bank, uint8_t *buffer,
        if (fallback == 0) {
                unsigned prog_section_bytes = kinfo->sector_size >> 8;
                for (i = 0; i < count; i += kinfo->sector_size) {
        if (fallback == 0) {
                unsigned prog_section_bytes = kinfo->sector_size >> 8;
                for (i = 0; i < count; i += kinfo->sector_size) {
+                       /*
+                        * The largest possible Kinetis "section" is
+                        * 16 bytes.  A full Kinetis sector is always
+                        * 256 "section"s.
+                        */
+                       uint8_t residual_buffer[16];
                        uint8_t ftfx_fstat;
                        uint8_t ftfx_fstat;
+                       uint32_t section_count = 256;
+                       uint32_t residual_wc = 0;
 
 
+                       /*
+                        * Assume the word count covers an entire
+                        * sector.
+                        */
                        wc = kinfo->sector_size / 4;
 
                        wc = kinfo->sector_size / 4;
 
+                       /*
+                        * If bytes to be programmed are less than the
+                        * full sector, then determine the number of
+                        * full-words to program, and put together the
+                        * residual buffer so that a full "section"
+                        * may always be programmed.
+                        */
                        if ((count - i) < kinfo->sector_size) {
                        if ((count - i) < kinfo->sector_size) {
-                               wc = count - i;
-                               wc /= 4;
+                               /* number of bytes to program beyond full section */
+                               unsigned residual_bc = (count-i) % prog_section_bytes;
+
+                               /* number of complete words to copy directly from buffer */
+                               wc = (count - i) / 4;
+
+                               /* number of total sections to write, including residual */
+                               section_count = DIV_ROUND_UP((count-i), prog_section_bytes);
+
+                               /* any residual bytes delivers a whole residual section */
+                               residual_wc = (residual_bc ? prog_section_bytes : 0)/4;
+
+                               /* clear residual buffer then populate residual bytes */
+                               (void) memset(residual_buffer, 0xff, prog_section_bytes);
+                               (void) memcpy(residual_buffer, &buffer[i+4*wc], residual_bc);
                        }
 
                        }
 
-                       LOG_DEBUG("write section @ %08X with length %d",
-                                 offset + i, wc * 4);
+                       LOG_DEBUG("write section @ %08X with length %d bytes",
+                                 offset + i, (count - i));
 
 
-                       /* write data to flexram */
-                       result =
-                               target_write_memory(bank->target, 0x14000000, 4, wc,
-                                                   buffer + i);
+                       /* write data to flexram as whole-words */
+                       result = target_write_memory(bank->target, 0x14000000, 4, wc,
+                                                    buffer + i);
 
                        if (result != ERROR_OK) {
                                LOG_ERROR("target_write_memory failed");
 
                        if (result != ERROR_OK) {
                                LOG_ERROR("target_write_memory failed");
-
                                return result;
                        }
 
                                return result;
                        }
 
-                       /* execute section command */
+                       /* write the residual words to the flexram */
+                       if (residual_wc) {
+                               result = target_write_memory(bank->target,
+                                                            0x14000000+4*wc,
+                                                            4, residual_wc,
+                                                            residual_buffer);
+
+                               if (result != ERROR_OK) {
+                                       LOG_ERROR("target_write_memory failed");
+                                       return result;
+                               }
+                       }
+
+                       /* execute section-write command */
                        w0 = (0x0b << 24) | (bank->base + offset + i);
                        w0 = (0x0b << 24) | (bank->base + offset + i);
-                       w1 = ((wc * 4 / prog_section_bytes) << 16);
+                       w1 = section_count << 16;
 
                        result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat);
 
 
                        result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat);
 

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)