diff options
author | Christopher Kilgour <techie@whiterocker.com> | 2012-07-07 16:47:06 -0700 |
---|---|---|
committer | Freddie Chopin <freddie.chopin@gmail.com> | 2012-08-29 06:25:41 +0000 |
commit | 4c3972c1df759564343aa63a424f7791a8ab9b19 (patch) | |
tree | 5491ee18d0ccc274e5be8df751ae729e03b7d263 /src | |
parent | 09f9596ae0cfb70a6ddceefd144b0e892a984b16 (diff) |
kinetis: ensure flash writes are not truncated
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/flash/nor/kinetis.c | 65 |
1 files changed, 54 insertions, 11 deletions
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index e0bb5c20..71722c64 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -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) { + /* + * 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; + uint32_t section_count = 256; + uint32_t residual_wc = 0; + /* + * Assume the word count covers an entire + * sector. + */ 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) { - 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"); - 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); - w1 = ((wc * 4 / prog_section_bytes) << 16); + w1 = section_count << 16; result = kinetis_ftfx_command(bank, w0, w1, w2, &ftfx_fstat); |