From 31965a5bbc5b9560c575e7b7701e75b2e2c52b87 Mon Sep 17 00:00:00 2001 From: Christopher Woodall Date: Sun, 25 Mar 2018 17:43:33 -0400 Subject: [PATCH] Added support for k64 (#301) --- src/target/kinetis.c | 87 +++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 22 deletions(-) diff --git a/src/target/kinetis.c b/src/target/kinetis.c index b65366c..4e18711 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -25,6 +25,12 @@ * KL25 Sub-family Reference Manual * * Extended with support for KL02 family + * + * Extended with support for K64 family with info from K22P64M50SF4RM: + * K22 Sub-Family Reference Manual + * + * Extended with support for K64 family with info from K64P144M120SF5RM: + * K64 Sub-Family Reference Manual, Rev. 2, */ #include "general.h" @@ -51,7 +57,9 @@ #define FTFA_CMD_CHECK_ERASE 0x01 #define FTFA_CMD_PROGRAM_CHECK 0x02 #define FTFA_CMD_READ_RESOURCE 0x03 -#define FTFA_CMD_PROGRAM_LONGWORD 0x06 +#define FTFA_CMD_PROGRAM_LONGWORD 0x06 +/* Part of the FTFE module for K64 */ +#define FTFE_CMD_PROGRAM_PHRASE 0x07 #define FTFA_CMD_ERASE_SECTOR 0x09 #define FTFA_CMD_CHECK_ERASE_ALL 0x40 #define FTFA_CMD_READ_ONCE 0x41 @@ -59,7 +67,9 @@ #define FTFA_CMD_ERASE_ALL 0x44 #define FTFA_CMD_BACKDOOR_ACCESS 0x45 -#define KL_GEN_PAGESIZE 0x400 +#define KL_WRITE_LEN 4 +/* 8 byte phrases need to be written to the k64 flash */ +#define K64_WRITE_LEN 8 static bool kinetis_cmd_unsafe(target *t, int argc, char *argv[]); static bool unsafe_enabled; @@ -85,7 +95,8 @@ static int kl_gen_flash_write(struct target_flash *f, static int kl_gen_flash_done(struct target_flash *f); static void kl_gen_add_flash(target *t, - uint32_t addr, size_t length, size_t erasesize) + uint32_t addr, size_t length, size_t erasesize, + size_t write_len) { struct target_flash *f = calloc(1, sizeof(*f)); f->start = addr; @@ -94,7 +105,7 @@ static void kl_gen_add_flash(target *t, f->erase = kl_gen_flash_erase; f->write = kl_gen_flash_write; f->done = kl_gen_flash_done; - f->align = 4; + f->align = write_len; f->erased = 0xff; target_add_flash(t, f); } @@ -107,13 +118,13 @@ bool kinetis_probe(target *t) t->driver = "KL25"; target_add_ram(t, 0x1ffff000, 0x1000); target_add_ram(t, 0x20000000, 0x3000); - kl_gen_add_flash(t, 0x00000000, 0x20000, 0x400); + kl_gen_add_flash(t, 0x00000000, 0x20000, 0x400, KL_WRITE_LEN); break; case 0x231: t->driver = "KL27"; target_add_ram(t, 0x1fffe000, 0x2000); target_add_ram(t, 0x20000000, 0x6000); - kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400); + kl_gen_add_flash(t, 0x00000000, 0x40000, 0x400, KL_WRITE_LEN); break; case 0x021: /* KL02 family */ switch((sdid>>16) & 0x0f){ @@ -121,19 +132,19 @@ bool kinetis_probe(target *t) t->driver = "KL02x32"; target_add_ram(t, 0x1FFFFC00, 0x400); target_add_ram(t, 0x20000000, 0xc00); - kl_gen_add_flash(t, 0x00000000, 0x7FFF, 0x400); + kl_gen_add_flash(t, 0x00000000, 0x7FFF, 0x400, KL_WRITE_LEN); break; case 2: t->driver = "KL02x16"; target_add_ram(t, 0x1FFFFE00, 0x200); target_add_ram(t, 0x20000000, 0x600); - kl_gen_add_flash(t, 0x00000000, 0x3FFF, 0x400); + kl_gen_add_flash(t, 0x00000000, 0x3FFF, 0x400, KL_WRITE_LEN); break; case 1: t->driver = "KL02x8"; target_add_ram(t, 0x1FFFFF00, 0x100); target_add_ram(t, 0x20000000, 0x300); - kl_gen_add_flash(t, 0x00000000, 0x1FFF, 0x400); + kl_gen_add_flash(t, 0x00000000, 0x1FFF, 0x400, KL_WRITE_LEN); break; default: return false; @@ -143,14 +154,25 @@ bool kinetis_probe(target *t) t->driver = "KL03"; target_add_ram(t, 0x1ffffe00, 0x200); target_add_ram(t, 0x20000000, 0x600); - kl_gen_add_flash(t, 0, 0x8000, 0x400); + kl_gen_add_flash(t, 0, 0x8000, 0x400, KL_WRITE_LEN); break; case 0x220: /* K22F family */ t->driver = "K22F"; target_add_ram(t, 0x1c000000, 0x4000000); target_add_ram(t, 0x20000000, 0x100000); - kl_gen_add_flash(t, 0, 0x40000, 0x800); - kl_gen_add_flash(t, 0x40000, 0x40000, 0x800); + kl_gen_add_flash(t, 0, 0x40000, 0x800, KL_WRITE_LEN); + kl_gen_add_flash(t, 0x40000, 0x40000, 0x800, KL_WRITE_LEN); + break; + case 0x620: /* K64F family. */ + /* This should be 0x640, but according to the errata sheet + * (KINETIS_1N83J) K64 and K24's will show up with the + * subfamily nibble as 2 + */ + t->driver = "K64"; + target_add_ram(t, 0x1FFF0000, 0x10000); + target_add_ram(t, 0x20000000, 0x30000); + kl_gen_add_flash(t, 0, 0x80000, 0x1000, K64_WRITE_LEN); + kl_gen_add_flash(t, 0x80000, 0x80000, 0x1000, K64_WRITE_LEN); break; default: return false; @@ -200,8 +222,9 @@ static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t l { while (len) { if (kl_gen_command(f->t, FTFA_CMD_ERASE_SECTOR, addr, NULL)) { - len -= KL_GEN_PAGESIZE; - addr += KL_GEN_PAGESIZE; + /* Different targets have different flash erase sizes */ + len -= f->blocksize; + addr += f->blocksize; } else { return 1; } @@ -223,11 +246,19 @@ static int kl_gen_flash_write(struct target_flash *f, FLASH_SECURITY_BYTE_UNSECURED; } + /* Determine write command based on the alignment. */ + uint8_t write_cmd; + if (f->align == K64_WRITE_LEN) { + write_cmd = FTFE_CMD_PROGRAM_PHRASE; + } else { + write_cmd = FTFA_CMD_PROGRAM_LONGWORD; + } + while (len) { - if (kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, dest, src)) { - len -= 4; - dest += 4; - src += 4; + if (kl_gen_command(f->t, write_cmd, dest, src)) { + len -= f->align; + dest += f->align; + src += f->align; } else { return 1; } @@ -245,10 +276,22 @@ static int kl_gen_flash_done(struct target_flash *f) FLASH_SECURITY_BYTE_UNSECURED) return 0; - uint32_t val = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); - val = (val & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; - kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, - FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&val); + /* Load the security byte based on the alignment (determine 8 byte phrases + * vs 4 byte phrases). + */ + if (f->align == 8) { + uint32_t vals[2]; + vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS-4); + vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); + vals[1] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; + kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE, + FLASH_SECURITY_BYTE_ADDRESS - 4, (uint8_t*)vals); + } else { + uint32_t val = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); + val = (val & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; + kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, + FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&val); + } return 0; }